@volter/blender-engine 0.1.40 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1412,10 +1412,14 @@ class Session:
1412
1412
  # automatic one is the evaluated bounds the presenter already holds.
1413
1413
  if graphs:
1414
1414
  depsgraph = bpy.context.evaluated_depsgraph_get()
1415
+ # BY NAME THROUGH ONE MAP: `scene.objects.get` searches the collection linearly, so a
1416
+ # lookup per row was quadratic -- measured on the Stoneguard file (11,702 rows): 11,343
1417
+ # calls, 14.4 s of every present.
1418
+ by_name = {obj.name: obj for obj in scene.objects}
1415
1419
  for row in frame["objects"]:
1416
1420
  if not any(m in graphs for m in row["materials"] if m is not None):
1417
1421
  continue
1418
- obj = scene.objects.get(row["name"])
1422
+ obj = by_name.get(row["name"])
1419
1423
  data = obj.evaluated_get(depsgraph).data if obj is not None else None
1420
1424
  if getattr(data, "use_auto_texspace", True) is False:
1421
1425
  row["texspace"] = [[float(v) for v in data.texspace_location],
@@ -1764,12 +1768,20 @@ class Session:
1764
1768
  if not os.path.exists(self.document):
1765
1769
  return {"document": relative_path, "opened": False}
1766
1770
  bpy.ops.wm.open_mainfile(filepath=self.document)
1771
+ size = os.path.getsize(self.document)
1772
+ # THE STAGED COPY GOES ONCE BLENDER HAS READ IT. It sits in the engine's heap (WasmFS keeps
1773
+ # file data in linear memory) and nothing reads it again: the load took everything into
1774
+ # Blender's own memory, packed pictures included, and the next save writes the path anew.
1775
+ # Freed before the first present, its bytes serve that present's evaluation instead of
1776
+ # raising the heap's high-water mark by the file's size (307 MB for the Stoneguard file).
1777
+ # The worker still holds the host's stamp for it, so it is not staged in again.
1778
+ os.remove(self.document)
1767
1779
  self.present()
1768
1780
  # The load did not dirty anything: what is in memory IS the file.
1769
1781
  self.save_due = False
1770
1782
  return {"document": relative_path, "opened": True,
1771
1783
  "objects": len(bpy.data.objects),
1772
- "size": os.path.getsize(self.document)}
1784
+ "size": size}
1773
1785
 
1774
1786
  def mark_changed(self):
1775
1787
  """A request that can change the model ran: the next present carries
@@ -1493,9 +1493,22 @@ export class BlenderRuntimeView {
1493
1493
  // is ahead of this presenter — a page reloaded under a still-running
1494
1494
  // session — and saying so by name is what makes it re-send the frame
1495
1495
  // in full (`dispatch.mts`, `runtime_present`).
1496
- if (this.frame?.session === next.session && this.meshes.has(id)) continue;
1496
+ // AND AT THAT REVISION: the frame names every mesh with the revision the engine holds
1497
+ // it at, so it is a whole manifest of what this presenter should hold, and a resident
1498
+ // geometry at another revision has drifted from the engine (a present the session
1499
+ // recorded that never landed here). Refusing it by name is the same resync as a mesh
1500
+ // not held at all: the session drops its record and re-sends in full.
1501
+ const resident = this.meshes.get(id)?.signature;
1502
+ if (
1503
+ this.frame?.session === next.session &&
1504
+ resident !== undefined &&
1505
+ (resident === `revision:${data.revision}` || !resident.startsWith('revision:'))
1506
+ )
1507
+ continue;
1497
1508
  throw new Error(
1498
- `${UNKNOWN_GEOMETRY}: the presenter does not hold runtime mesh ${id} (store ${data.store}, revision ${data.revision})`,
1509
+ resident === undefined
1510
+ ? `${UNKNOWN_GEOMETRY}: the presenter does not hold runtime mesh ${id} (store ${data.store}, revision ${data.revision})`
1511
+ : `${UNKNOWN_GEOMETRY}: the presenter holds runtime mesh ${id} at ${resident}, not revision ${data.revision}`,
1499
1512
  );
1500
1513
  }
1501
1514
  const drawn = 'hash' in data;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/blender-engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "GPL-3.0-or-later",
5
- "version": "0.1.40",
5
+ "version": "0.1.42",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },