From 0f1465768bc718dfc33a538f6310bf8458247adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofus=20Albert=20H=C3=B8gsbro=20Rose?= Date: Tue, 20 Feb 2024 13:16:23 +0100 Subject: [PATCH] feat: We did it, GeoNodes node w/live update! We also implemented the TriMesh node, and established a strong convention for updating nodes from sockets via. socket superclass method. `trigger_updates`. It should be triggered as the `update=` callback on **ALL PROPERTIES IN ALL SOCKETS**. This method in turn calls the nodal `update()` function, which in turn causes the node to chain-update all nodes linked to any output socket. By default, `update()` is `pass`, so performance shouldn't be a concern, but we should think about this deeper at some point. Because update-chaining is done, we're ready for preview toggles on node outputs. A lot of exciting things to do now! --- .../node_trees/maxwell_sim_nodes/contracts.py | 35 ++++ .../maxwell_sim_nodes/nodes/base.py | 28 ++- .../nodes/structures/geonodes_structure.py | 176 +++++++++++++++++- .../nodes/structures/object_structure.py | 83 ++++++++- .../maxwell_sim_nodes/sockets/base.py | 7 + .../sockets/basic/bool_socket.py | 1 + .../sockets/basic/file_path_socket.py | 1 + .../sockets/basic/text_socket.py | 1 + .../sockets/blender/collection_socket.py | 19 +- .../sockets/blender/geonodes_socket.py | 29 ++- .../sockets/blender/image_socket.py | 1 + .../sockets/blender/object_socket.py | 19 +- .../sockets/blender/text_socket.py | 1 + .../sockets/blender/volume_socket.py | 1 + .../sockets/maxwell/medium_socket.py | 1 + .../sockets/number/complex_number_socket.py | 5 +- .../sockets/number/real_number_socket.py | 1 + .../sockets/physical/accel_scalar_socket.py | 1 + .../sockets/physical/angle_socket.py | 1 + .../sockets/physical/area_socket.py | 1 + .../sockets/physical/force_scalar_socket.py | 1 + .../sockets/physical/freq_socket.py | 1 + .../sockets/physical/length_socket.py | 1 + .../sockets/physical/point_3d_socket.py | 1 + .../sockets/physical/size_3d_socket.py | 1 + .../sockets/physical/time_socket.py | 1 + .../sockets/physical/volume_socket.py | 1 + blender_maxwell/requirements.txt | 1 + 28 files changed, 394 insertions(+), 26 deletions(-) diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py b/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py index a417a04..c710744 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py @@ -450,6 +450,41 @@ SocketType_to_color = { SocketType.MaxwellSimGridAxis: (0.4, 0.3, 0.25, 1.0), # Darkest Gold } +BLNodeSocket_to_SocketType = { + "NodeSocketBool": SocketType.Bool, + "NodeSocketCollection": SocketType.BlenderCollection, + "NodeSocketColor": SocketType.Real3DVector, + "NodeSocketFloat": SocketType.RealNumber, + "NodeSocketFloatAngle": SocketType.RealNumber, + "NodeSocketFloatDistance": SocketType.RealNumber, + "NodeSocketFloatFactor": SocketType.RealNumber, + "NodeSocketFloatPercentage": SocketType.RealNumber, + "NodeSocketFloatTime": SocketType.RealNumber, + "NodeSocketFloatTimeAbsolute": SocketType.RealNumber, + "NodeSocketFloatUnsigned": SocketType.RealNumber, + "NodeSocketGeometry": SocketType.Any, + "NodeSocketImage": SocketType.BlenderImage, + "NodeSocketInt": SocketType.IntegerNumber, + "NodeSocketIntFactor": SocketType.IntegerNumber, + "NodeSocketIntPercentage": SocketType.IntegerNumber, + "NodeSocketIntUnsigned": SocketType.IntegerNumber, + "NodeSocketMaterial": SocketType.Any, + "NodeSocketObject": SocketType.BlenderObject, + "NodeSocketRotation": SocketType.Real3DVector, + "NodeSocketShader": SocketType.Any, + "NodeSocketStandard": SocketType.Any, + "NodeSocketString": SocketType.Text, + "NodeSocketTexture": SocketType.Any, + "NodeSocketVector": SocketType.Real3DVector, + "NodeSocketVectorAcceleration": SocketType.Real3DVector, + "NodeSocketVectorDirection": SocketType.Real3DVector, + "NodeSocketVectorEuler": SocketType.Real3DVector, + "NodeSocketVectorTranslation": SocketType.Real3DVector, + "NodeSocketVectorVelocity": SocketType.Real3DVector, + "NodeSocketVectorXYZ": SocketType.Real3DVector, + "NodeSocketVirtual": SocketType.Any, +} + #################### # - Node Types #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py index 6f131f2..06a2084 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py @@ -155,11 +155,6 @@ class MaxwellSimTreeNode(bpy.types.Node): # Declare Node Property: 'preset' EnumProperty if hasattr(cls, "input_socket_sets") or hasattr(cls, "output_socket_sets"): - if not hasattr(cls, "input_socket_sets"): - cls.input_socket_sets = {} - if not hasattr(cls, "output_socket_sets"): - cls.output_socket_sets = {} - socket_set_keys = [ input_socket_set_key for input_socket_set_key in cls.input_socket_sets.keys() @@ -188,6 +183,11 @@ class MaxwellSimTreeNode(bpy.types.Node): default=socket_set_keys[0] ) + if not hasattr(cls, "input_socket_sets"): + cls.input_socket_sets = {} + if not hasattr(cls, "output_socket_sets"): + cls.output_socket_sets = {} + # Declare Node Property: 'preset' EnumProperty if hasattr(cls, "presets"): first_preset = list(cls.presets.keys())[0] @@ -292,6 +292,18 @@ class MaxwellSimTreeNode(bpy.types.Node): return ntree.bl_idname == contracts.TreeType.MaxwellSim.value + def update(self) -> None: + """Called when some node properties (ex. links) change, + and/or by custom code.""" + if hasattr(self, "update_cb"): + self.update_cb() + + for bl_socket in self.outputs: + if bl_socket.is_linked: + for node_link in bl_socket.links: + linked_node = node_link.to_node + linked_node.update() + def _update_socket(self): if not hasattr(self, "socket_set"): raise ValueError("no socket") @@ -379,7 +391,7 @@ class MaxwellSimTreeNode(bpy.types.Node): return self.inputs[self.input_sockets[input_socket_name].label] - elif hasattr(self, "input_socket_sets"): + elif hasattr(self, "socket_set"): # You're on your own, chump return self.inputs[next( @@ -412,7 +424,7 @@ class MaxwellSimTreeNode(bpy.types.Node): return self.outputs[self.output_sockets[output_socket_name].label] - elif hasattr(self, "input_socket_sets"): + elif hasattr(self, "socket_set"): return self.outputs[next( socket_def.label for socket_set, socket_dict in self.input_socket_sets.items() @@ -424,7 +436,7 @@ class MaxwellSimTreeNode(bpy.types.Node): self, output_bl_socket_name: contracts.BLSocketName, ) -> contracts.SocketName: - if hasattr(self, "output_socket_sets"): + if hasattr(self, "socket_set"): return next( socket_name for socket_set, socket_dict in self.output_socket_sets.items() diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py index 41fac16..63d5d42 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py @@ -1,5 +1,177 @@ +import tidy3d as td +import numpy as np +import sympy as sp +import sympy.physics.units as spu + +import bpy +import bmesh + +from ... import contracts +from ... import sockets +from .. import base + +GEONODES_MODIFIER_NAME = "BLMaxwell_GeoNodes" + +class GeoNodesStructureNode(base.MaxwellSimTreeNode): + node_type = contracts.NodeType.GeoNodesStructure + bl_label = "GeoNodes Structure" + #bl_icon = ... + + #################### + # - Sockets + #################### + input_sockets = { + "medium": sockets.MaxwellMediumSocketDef( + label="Medium", + ), + "object": sockets.BlenderObjectSocketDef( + label="Object", + ), + "geo_nodes": sockets.BlenderGeoNodesSocketDef( + label="GeoNodes", + ), + } + output_sockets = { + "structure": sockets.MaxwellStructureSocketDef( + label="Structure", + ), + } + + #################### + # - Output Socket Computation + #################### + @base.computes_output_socket("structure") + def compute_simulation(self: contracts.NodeTypeProtocol) -> td.TriangleMesh: + # Extract the Blender Object + bl_object = self.compute_input("object") + + # Ensure Updated Geometry + bpy.context.view_layer.update() + + # Triangulate Object Mesh + bmesh_mesh = bmesh.new() + bmesh_mesh.from_mesh(bl_object.data) + bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces) + + mesh = bpy.data.meshes.new(name="TriangulatedMesh") + bmesh_mesh.to_mesh(mesh) + bmesh_mesh.free() + + # Extract Vertices and Faces + vertices = np.array([vert.co for vert in mesh.vertices]) + faces = np.array([ + [vert for vert in poly.vertices] + for poly in mesh.polygons + ]) + + # Remove Temporary Mesh + bpy.data.meshes.remove(mesh) + + return td.Structure( + geometry=td.TriangleMesh.from_vertices_faces(vertices, faces), + medium=self.compute_input("medium") + ) + + #################### + # - Update Function + #################### + def update_cb(self) -> None: + bl_object = self.compute_input("object") + if bl_object is None: return + + geo_nodes = self.compute_input("geo_nodes") + if geo_nodes is None: return + + bl_modifier = bl_object.modifiers.get(GEONODES_MODIFIER_NAME) + if bl_modifier is None: return + + # Set GeoNodes Modifier Attributes + for idx, interface_item in enumerate( + geo_nodes.interface.items_tree.values() + ): + if idx == 0: continue ## Always-on "Geometry" Input (from Object) + + bl_socket = self.inputs[ + interface_item.name + ] + if bl_socket.is_linked: + linked_bl_socket = bl_socket.links[0].from_socket + linked_bl_node = bl_socket.links[0].from_node + val = linked_bl_node.compute_output( + linked_bl_node.g_output_socket_name( + linked_bl_socket.name + ) + ) ## What a bunch of spaghetti + else: + val = self.inputs[ + interface_item.name + ].default_value + + # Conservatively Set Differing Values + if bl_modifier[interface_item.identifier] != val: + bl_modifier[interface_item.identifier] = val + + # Update DepGraph + bl_object.data.update() + + def update_sockets_from_geonodes(self) -> None: + # Remove All "Loose" Sockets + socket_labels = { + socket_def.label + for socket_def in self.input_sockets.values() + } | { + socket_def.label + for socket_set_name, socket_set in self.input_socket_sets.items() + for socket_name, socket_def in socket_set.items() + } + bl_sockets_to_remove = { + bl_socket + for bl_socket_name, bl_socket in self.inputs.items() + if bl_socket_name not in socket_labels + } + + for bl_socket in bl_sockets_to_remove: + self.inputs.remove(bl_socket) + + # Query for Blender Object / Geo Nodes + bl_object = self.compute_input("object") + if bl_object is None: return + ## TODO: Make object? Gray out geonodes if object not defined? + + geo_nodes = self.compute_input("geo_nodes") + if geo_nodes is None: return + + + # Add Non-Static Sockets from GeoNodes + for bl_socket_name, bl_socket in geo_nodes.interface.items_tree.items(): + # For now, don't allow Geometry inputs. + if bl_socket.socket_type == "NodeSocketGeometry": continue + + self.inputs.new( + contracts.BLNodeSocket_to_SocketType[bl_socket.socket_type], + bl_socket_name, + ) + + # Create New GeoNodes Modifier + if GEONODES_MODIFIER_NAME not in bl_object.modifiers: + modifier = bl_object.modifiers.new( + name=GEONODES_MODIFIER_NAME, + type="NODES", + ) + modifier.node_group = geo_nodes + + self.update() + + + #################### # - Blender Registration #################### -BL_REGISTER = [] -BL_NODES = {} +BL_REGISTER = [ + GeoNodesStructureNode, +] +BL_NODES = { + contracts.NodeType.GeoNodesStructure: ( + contracts.NodeCategory.MAXWELLSIM_STRUCTURES + ) +} diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/object_structure.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/object_structure.py index 8f4a665..bdc51e7 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/object_structure.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/object_structure.py @@ -1,6 +1,83 @@ +import tidy3d as td +import numpy as np +import sympy as sp +import sympy.physics.units as spu + +import bpy +import bmesh + +from ... import contracts +from ... import sockets +from .. import base + +class ObjectStructureNode(base.MaxwellSimTreeNode): + node_type = contracts.NodeType.ObjectStructure + bl_label = "Object Structure" + #bl_icon = ... + + #################### + # - Sockets + #################### + input_sockets = { + "medium": sockets.MaxwellMediumSocketDef( + label="Medium", + ), + "object": sockets.BlenderObjectSocketDef( + label="Object", + ), + } + output_sockets = { + "structure": sockets.MaxwellStructureSocketDef( + label="Structure", + ), + } + + #################### + # - Output Socket Computation + #################### + @base.computes_output_socket("structure") + def compute_structure(self: contracts.NodeTypeProtocol) -> td.Structure: + # Extract the Blender Object + bl_object = self.compute_input("object") + + # Ensure Updated Geometry + bpy.context.view_layer.update() + + # Triangulate Object Mesh + bmesh_mesh = bmesh.new() + bmesh_mesh.from_mesh(bl_object.data) + bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces) + + mesh = bpy.data.meshes.new(name="TriangulatedMesh") + bmesh_mesh.to_mesh(mesh) + bmesh_mesh.free() + + # Extract Vertices and Faces + vertices = np.array([vert.co for vert in mesh.vertices]) + faces = np.array([ + [vert for vert in poly.vertices] + for poly in mesh.polygons + ]) + + # Remove Temporary Mesh + bpy.data.meshes.remove(mesh) + + print(vertices) + return td.Structure( + geometry=td.TriangleMesh.from_vertices_faces(vertices, faces), + medium=self.compute_input("medium") + ) + + + #################### # - Blender Registration #################### -BL_REGISTER = [] -BL_NODES = {} - +BL_REGISTER = [ + ObjectStructureNode, +] +BL_NODES = { + contracts.NodeType.ObjectStructure: ( + contracts.NodeCategory.MAXWELLSIM_STRUCTURES + ) +} diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py index bfd451a..0437595 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py @@ -140,6 +140,13 @@ class BLSocket(bpy.types.NodeSocket): self._unit_previous = self.unit + #################### + # - Callback Dispatcher + #################### + def trigger_updates(self) -> None: + if not self.is_output: + self.node.update() + #################### # - Methods #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py index a417304..0eb9f12 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py @@ -25,6 +25,7 @@ class BoolBLSocket(base.BLSocket): name="Boolean", description="Represents a boolean", default=False, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/file_path_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/file_path_socket.py index 5edf3c6..7dac99b 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/file_path_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/file_path_socket.py @@ -27,6 +27,7 @@ class FilePathBLSocket(base.BLSocket): description="Represents the path to a file", #default="", subtype="FILE_PATH", + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py index c6b2fd0..779d1a7 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py @@ -27,6 +27,7 @@ class TextBLSocket(base.BLSocket): name="Text", description="Represents some text", default="", + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/collection_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/collection_socket.py index 8243375..8e541ef 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/collection_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/collection_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -12,16 +13,26 @@ class BlenderCollectionBLSocket(base.BLSocket): socket_type = contracts.SocketType.BlenderCollection bl_label = "BlenderCollection" + #################### + # - Properties + #################### + raw_value: bpy.props.PointerProperty( + name="Blender Collection", + description="Represents a Blender collection", + type=bpy.types.Collection, + update=(lambda self, context: self.trigger_updates()), + ) + #################### # - Default Value #################### @property - def default_value(self) -> None: - pass + def default_value(self) -> bpy.types.Collection | None: + return self.raw_value @default_value.setter - def default_value(self, value: typ.Any) -> None: - pass + def default_value(self, value: bpy.types.Collection) -> None: + self.raw_value = value #################### # - Socket Configuration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/geonodes_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/geonodes_socket.py index 13fb4f9..2862200 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/geonodes_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/geonodes_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -12,16 +13,36 @@ class BlenderGeoNodesBLSocket(base.BLSocket): socket_type = contracts.SocketType.BlenderGeoNodes bl_label = "BlenderGeoNodes" + #################### + # - Properties + #################### + def update_geonodes_node(self): + if hasattr(self.node, "update_sockets_from_geonodes"): + self.node.update_sockets_from_geonodes() + else: + raise ValueError("Node doesn't have GeoNodes socket update method.") + + # Run the Usual Updates + self.trigger_updates() + + raw_value: bpy.props.PointerProperty( + name="Blender GeoNodes Tree", + description="Represents a Blender GeoNodes Tree", + type=bpy.types.NodeTree, + poll=(lambda self, obj: obj.bl_idname == 'GeometryNodeTree'), + update=(lambda self, context: self.update_geonodes_node()), + ) + #################### # - Default Value #################### @property - def default_value(self) -> None: - pass + def default_value(self) -> bpy.types.Object | None: + return self.raw_value @default_value.setter - def default_value(self, value: typ.Any) -> None: - pass + def default_value(self, value: bpy.types.Object) -> None: + self.raw_value = value #################### # - Socket Configuration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/image_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/image_socket.py index 247cadb..1786d8d 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/image_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/image_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/object_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/object_socket.py index 69e7284..358daa5 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/object_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/object_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -12,16 +13,26 @@ class BlenderObjectBLSocket(base.BLSocket): socket_type = contracts.SocketType.BlenderObject bl_label = "BlenderObject" + #################### + # - Properties + #################### + raw_value: bpy.props.PointerProperty( + name="Blender Object", + description="Represents a Blender object", + type=bpy.types.Object, + update=(lambda self, context: self.trigger_updates()), + ) + #################### # - Default Value #################### @property - def default_value(self) -> None: - pass + def default_value(self) -> bpy.types.Object | None: + return self.raw_value @default_value.setter - def default_value(self, value: typ.Any) -> None: - pass + def default_value(self, value: bpy.types.Object) -> None: + self.raw_value = value #################### # - Socket Configuration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/text_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/text_socket.py index 0c95c84..9381b77 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/text_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/text_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/volume_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/volume_socket.py index c0bfc1c..dc4aadc 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/volume_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/volume_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py index cd9312f..e4ce5ce 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py @@ -23,6 +23,7 @@ class MaxwellMediumBLSocket(base.BLSocket): description="Represents a simple, real permittivity.", default=0.0, precision=4, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/complex_number_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/complex_number_socket.py index e5f466c..563d8ee 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/complex_number_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/complex_number_socket.py @@ -30,7 +30,8 @@ class ComplexNumberBLSocket(base.BLSocket): description="Represents a complex number (real, imaginary)", size=2, default=(0.0, 0.0), - subtype='NONE' + subtype='NONE', + update=(lambda self, context: self.trigger_updates()), ) coord_sys: bpy.props.EnumProperty( name="Coordinate System", @@ -135,6 +136,8 @@ class ComplexNumberBLSocket(base.BLSocket): sp.Abs(cart_value), sp.arg(cart_value) if y != 0 else 0, ) + + self.trigger_updates() #################### # - Socket Configuration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py index 7a3da98..5ce1c5b 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py @@ -30,6 +30,7 @@ class RealNumberBLSocket(base.BLSocket): description="Represents a real number", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py index 02d9b5a..ffff7a3 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py @@ -22,6 +22,7 @@ class PhysicalAccelScalarBLSocket(base.BLSocket): description="Represents the unitless part of the acceleration", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py index ac4bfc5..83bb9bd 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py @@ -22,6 +22,7 @@ class PhysicalAngleBLSocket(base.BLSocket): description="Represents the unitless part of the acceleration", default=0.0, precision=4, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py index 5ad6dea..55f2387 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py @@ -32,6 +32,7 @@ class PhysicalAreaBLSocket(base.BLSocket): description="Represents the unitless part of the area", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py index 1e84256..a47deb1 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py @@ -22,6 +22,7 @@ class PhysicalForceScalarBLSocket(base.BLSocket): description="Represents the unitless part of the force", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py index 0ef7376..651472f 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py @@ -22,6 +22,7 @@ class PhysicalFreqBLSocket(base.BLSocket): description="Represents the unitless part of the frequency", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py index 109f29b..0f744af 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py @@ -22,6 +22,7 @@ class PhysicalLengthBLSocket(base.BLSocket): description="Represents the unitless part of the force", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py index 812f84b..20d310c 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py @@ -33,6 +33,7 @@ class PhysicalPoint3DBLSocket(base.BLSocket): size=3, default=(0.0, 0.0, 0.0), precision=4, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py index aabd749..c8af3d9 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py @@ -33,6 +33,7 @@ class PhysicalSize3DBLSocket(base.BLSocket): size=3, default=(1.0, 1.0, 1.0), precision=4, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py index a35759b..e429721 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py @@ -22,6 +22,7 @@ class PhysicalTimeBLSocket(base.BLSocket): description="Represents the unitless part of the force", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py index cd465c6..97b5d6b 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py @@ -32,6 +32,7 @@ class PhysicalVolumeBLSocket(base.BLSocket): description="Represents the unitless part of the area", default=0.0, precision=6, + update=(lambda self, context: self.trigger_updates()), ) #################### diff --git a/blender_maxwell/requirements.txt b/blender_maxwell/requirements.txt index 4bcb244..8db1534 100644 --- a/blender_maxwell/requirements.txt +++ b/blender_maxwell/requirements.txt @@ -2,3 +2,4 @@ tidy3d==2.5.2 pydantic==2.6.0 sympy==1.12 scipy==1.12.0 +trimesh==4.1.4