diff --git a/TODO.md b/TODO.md index 3790f69..db062e8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ # Acute Tasks - [x] Implement Material Import for Maxim Data - [x] Implement Robust DataFlowKind for list-like / spectral-like composite types -- [ ] Unify random node/socket caches. +- [x] Unify random node/socket caches. - [ ] Finish the "Low-Hanging Fruit" Nodes - [ ] Move preview GN trees to the asset library. @@ -344,6 +344,10 @@ # Internal / Architecture +## IDEAS +- [ ] Socket "guarding" - let nodes influence the dynamic capabilities of sockets to prevent links (with a `self.report` explanation) to an output socket that won't yet produce a value. + - [ ] Prevents some uses of loose sockets (we want less loose sockets!) + ## CRITICAL - [ ] License header UI for MaxwellSimTrees, to clarify the AGPL-compatible potentially user-selected license that trees must be distributed under. - [ ] Document the node tree cache semantics thoroughly; it's a VERY nuanced piece of logic, and its invariants may not survive Blender versions / the author's working memory @@ -463,6 +467,7 @@ This is where we keep track of them for now. - [ ] Cloud task socket loads folders before its node shows, which can be slow (and error prone if offline) - [ ] Dispersive fit is slow, which means lag on normal operations that rely on the fit result - fit computation should be integrated into the node, and the output socket should only appear when the fit is available. - [ ] Numerical, Physical Constant is missing entries +- [ ] Numerical, Physical Constant is missing entries BROKE NODES - [ ] Numerical constant doesn't switch types diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_collection.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_collection.py index b139c34..712104e 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_collection.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_collection.py @@ -13,7 +13,6 @@ PREVIEW_COLLECTION_NAME = 'BLMaxwell Visible' #################### # - Global Collection Handling #################### -@functools.cache def collection(collection_name: str, view_layer_exclude: bool) -> bpy.types.Collection: # Init the "Managed Collection" # Ensure Collection exists (and is in the Scene collection) diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/node_tree.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/node_tree.py index d32849d..d41ccc4 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/node_tree.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/node_tree.py @@ -254,8 +254,8 @@ class MaxwellSimTree(bpy.types.NodeTree): #################### # - Update Methods #################### - def sync_node_removed(self, node: bpy.types.Node): - """Run by `Node.free()` when a node is being removed. + def on_node_removed(self, node: bpy.types.Node): + """Run by `MaxwellSimNode.free()` when a node is being removed. ONLY input socket links are removed from the NodeLink cache. - `self.update()` handles link-removal from existing nodes. @@ -275,6 +275,20 @@ class MaxwellSimTree(bpy.types.NodeTree): self.node_link_cache.remove_link(link_ptr) self.node_link_cache.remove_sockets_by_link_ptr(link_ptr) + def on_node_socket_removed(self, bl_socket: bpy.types.NodeSocket) -> None: + """Run by `MaxwellSimNode._prune_inactive_sockets()` when a socket is being removed (but not the node). + + Parameters: + bl_socket: The node socket that's about to be removed. + """ + # Compute About-To-Be-Freed Link Ptrs + link_ptrs = {link.as_pointer() for link in bl_socket.links} + + if link_ptrs: + for link_ptr in link_ptrs: + self.node_link_cache.remove_link(link_ptr) + self.node_link_cache.remove_sockets_by_link_ptr(link_ptr) + def update(self) -> None: """Monitors all changes to the node tree, potentially responding with appropriate callbacks. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py index 64a6e5c..1383590 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py @@ -381,6 +381,7 @@ class MaxwellSimNode(bpy.types.Node): A socket is considered "inactive" when it shouldn't be defined (per `self.active_socket_defs), but is present nonetheless. """ + node_tree = self.id_data for direc in ['input', 'output']: all_bl_sockets = self._bl_sockets(direc) active_bl_socket_defs = self.active_socket_defs(direc) @@ -400,6 +401,7 @@ class MaxwellSimNode(bpy.types.Node): # Remove Sockets for bl_socket in bl_sockets_to_remove: + node_tree.on_node_socket_removed(bl_socket) all_bl_sockets.remove(bl_socket) def _add_new_active_sockets(self): @@ -964,7 +966,7 @@ class MaxwellSimNode(bpy.types.Node): ## The NodeTree keeps caches to for optimized event triggering. ## However, ex. deleted nodes also deletes links, without cache update. ## By reporting that we're deleting the node, the cache stays happy. - node_tree.sync_node_removed(self) + node_tree.on_node_removed(self) # Invalidate Non-Persistent Cache ## Prevents memory leak due to dangling cache entries for deleted nodes. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py index 5095970..2b40173 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py @@ -210,7 +210,6 @@ class MaxwellSimSocket(bpy.types.NodeSocket): Returns a bool, whether or not the socket consents to the link change. """ - ## TODO: Crash if deleting removing linked loose sockets. if self.locked: return False if self.is_output: