From d19fa0044a341606b5b033a535c9dd7a8a034eb6 Mon Sep 17 00:00:00 2001 From: Nicolas Predella Date: Thu, 14 May 2026 23:40:13 +0300 Subject: [PATCH] up --- core/nodeslicer/tree.py | 19 ++++++++++++++----- infra/blender_mesh_capture.py | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/core/nodeslicer/tree.py b/core/nodeslicer/tree.py index 0aca907..7bcea9d 100644 --- a/core/nodeslicer/tree.py +++ b/core/nodeslicer/tree.py @@ -39,25 +39,34 @@ def get_referenced_objects(node, visited=None): return objs _is_updating = False - @persistent def depsgraph_update_handler(scene, depsgraph): global _is_updating if _is_updating: return - updated_objects = {update.id.name for update in depsgraph.updates if isinstance(update.id, bpy.types.Object)} - if not updated_objects: + # Names of objects that have changed + updated_object_names = {update.id.name for update in depsgraph.updates if isinstance(update.id, bpy.types.Object)} + + # Also check for mesh updates (happens in Edit Mode) + updated_meshes = {update.id.name for update in depsgraph.updates if isinstance(update.id, bpy.types.Mesh)} + if updated_meshes: + for obj in bpy.data.objects: + if obj.type == 'MESH' and obj.data in updated_meshes: + updated_object_names.add(obj.name) + + if not updated_object_names: return for tree in bpy.data.node_groups: if tree.bl_idname != "SLICETREE_NodeTree": continue - + for node in tree.nodes: if node.bl_idname == "SLICENODE_Executor" and getattr(node, "auto_refresh", False): referenced = get_referenced_objects(node) - if any(obj.name in updated_objects for obj in referenced): + referenced_names = {obj.name for obj in referenced if obj} + if updated_object_names & referenced_names: _is_updating = True try: node.evaluate() diff --git a/infra/blender_mesh_capture.py b/infra/blender_mesh_capture.py index d66c9c4..746f51f 100644 --- a/infra/blender_mesh_capture.py +++ b/infra/blender_mesh_capture.py @@ -33,6 +33,8 @@ class SlicingObject(): scene_scale: float = bpy.context.scene.unit_settings.scale_length if obj: + if obj.mode == 'EDIT': + obj.update_from_editmode() eval_objects = obj.evaluated_get(depsgraph) self.mesh = objects_to_tris([eval_objects], 1000 * scene_scale) else: @@ -219,6 +221,8 @@ class SlicingGroup(): self.wipe_tower_xy = self.center_xy[0:2] for obj in objs: + if obj.mode == 'EDIT': + obj.update_from_editmode() eval_obj = obj.evaluated_get(depsgraph) if eval_obj.blendertoprusaslicer.object_type == 'WipeTower': self.wipe_tower_xy = np.array(eval_obj.location[0:2]) * scale_tx @@ -367,7 +371,7 @@ def _cached_capture_mesh_edges( # This helper expects that the object and mesh exist and are accessible via bpy.data obj = bpy.data.objects.get(obj_name) if not obj: return [] - + # We don't use obj_eval here directly as it's not hashable, # but we assume this is called when we know we need to re-capture. # The actual capture logic stays the same but is now inside this cached function. @@ -386,7 +390,7 @@ def _cached_capture_mesh_edges( num_verts = len(mesh.vertices) verts = np.empty((num_verts, 3), dtype=np.float64) mesh.vertices.foreach_get("co", verts.ravel()) - + tx_verts = (verts @ world_mat[:3, :3].T + world_mat[:3, 3]) * scene_scale edges_set = {tuple(sorted(e.vertices)) for e in mesh.edges} @@ -406,20 +410,23 @@ def _cached_capture_mesh_edges( final_paths.append(path_coords) return final_paths - + finally: if hasattr(obj_eval, "to_mesh_clear"): obj_eval.to_mesh_clear() def capture_mesh_edges(obj: Object) -> list[NDArray[float64]]: if not obj or not obj.data: return [] - + + if obj.mode == 'EDIT': + obj.update_from_editmode() + assert bpy.context.scene and bpy.context.scene.unit_settings scene_scale = 1000.0 * bpy.context.scene.unit_settings.scale_length - + # Create a hashable key from object state matrix_tuple = tuple(val for row in obj.matrix_world for val in row) # Flattened tuple - + return _cached_capture_mesh_edges( obj.name, obj.data.name,