diff --git a/TODO.md b/TODO.md index 4282714..72590ac 100644 --- a/TODO.md +++ b/TODO.md @@ -504,7 +504,7 @@ Unreported: - We found the translation callback! https://projects.blender.org/blender/blender/commit/8564e03cdf59fb2a71d545e81871411b82f561d9 - This can update the node center!! -- [ ] Optimize the `DataChanged` invalidator. +- [x] Optimize the `DataChanged` invalidator. - [ ] Optimize unit stripping. @@ -551,7 +551,7 @@ We need support for arbitrary objects, but still backed by the persistance seman - [x] For serializeability, let the encoder/decoder be able to make use of an optional `.msgspec_encodable()` and similar decoder respectively, and add support for these in the ENCODER/DECODER functions. - [x] Define a superclass for `SocketDef` and make everyone inherit from it - [ ] Collect with a `BL_SOCKET_DEFS` object, instead of manually from `__init__.py`s - - [ ] Add support for `.msgspec_*()` methods, so that we remove the dependency on sockets from the serialization module. + - [x] Add support for `.msgspec_*()` methods, so that we remove the dependency on sockets from the serialization module. ### Sweeping Features - [ ] Replace all raw Blender properties with `BLField`. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_cache.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_cache.py index 0aa16a5..2cd6e4d 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_cache.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_cache.py @@ -33,9 +33,11 @@ class BLInstance(typ.Protocol): ) -> None: ... -PropGetMethod: typ.TypeAlias = typ.Callable[[BLInstance], serialize.EncodableValue] +PropGetMethod: typ.TypeAlias = typ.Callable[ + [BLInstance], serialize.NaivelyEncodableType +] PropSetMethod: typ.TypeAlias = typ.Callable[ - [BLInstance, serialize.EncodableValue], None + [BLInstance, serialize.NaivelyEncodableType], None ] diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_socket_map.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_socket_map.py index 7fe24d2..9021820 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_socket_map.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/bl_socket_map.py @@ -132,7 +132,7 @@ def _socket_def_from_bl_socket( def socket_def_from_bl_socket( bl_interface_socket: bpy.types.NodeTreeInterfaceSocket, -) -> ct.schemas.SocketDef: +) -> sockets.base.SocketDef: """Computes an appropriate (no-arg) SocketDef from the given `bl_interface_socket`, by parsing it.""" return _socket_def_from_bl_socket( bl_interface_socket.description, bl_interface_socket.bl_socket_idname diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/__init__.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/__init__.py index d322a7f..4aacd15 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/__init__.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/__init__.py @@ -65,11 +65,6 @@ from .data_flows import ( ) from .data_flow_actions import DataFlowAction -#################### -# - Schemas -#################### -from . import schemas - #################### # - Export #################### @@ -103,5 +98,4 @@ __all__ = [ 'LazyDataValueRange', 'LazyDataValueSpectrum', 'DataFlowAction', - 'schemas', ] diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/__init__.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/__init__.py deleted file mode 100644 index ae4047e..0000000 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from .managed_obj import ManagedObj -from .managed_obj_def import ManagedObjDef -from .preset_def import PresetDef -from .socket_def import SocketDef - -__all__ = [ - 'SocketDef', - 'ManagedObj', - 'ManagedObjDef', - 'PresetDef', -] diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj_def.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj_def.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/socket_def.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/socket_def.py deleted file mode 100644 index e9818ee..0000000 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/socket_def.py +++ /dev/null @@ -1,26 +0,0 @@ -import abc -import typing as typ - -import bpy -import pydantic as pyd - -from .....utils import serialize -from ..socket_types import SocketType - - -class SocketDef(pyd.BaseModel, abc.ABC): - socket_type: SocketType - - @abc.abstractmethod - def init(self, bl_socket: bpy.types.NodeSocket) -> None: - """Initializes a real Blender node socket from this socket definition.""" - - #################### - # - Serialization - #################### - def dump_as_msgspec(self) -> serialize.NaiveRepresentation: - return [serialize.TypeID.SocketDef, self.__class__.__name__, self.model_dump()] - - @staticmethod - def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self: - return SocketDef.__subclasses__[obj[1]](**obj[2]) diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/base.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/base.py index 47c6222..3c668a9 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/base.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/base.py @@ -1,9 +1,12 @@ import abc import typing as typ -from ....utils import serialize +from blender_maxwell.utils import logger, serialize + from .. import contracts as ct +log = logger.get(__name__) + class ManagedObj(abc.ABC): managed_obj_type: ct.ManagedObjType @@ -50,9 +53,13 @@ class ManagedObj(abc.ABC): return [ serialize.TypeID.ManagedObj, self.__class__.__name__, - (self.managed_obj_type, self.name), + self.name, ] @staticmethod def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self: - return ManagedObj.__subclasses__[obj[1]](**obj[2]) + return next( + subclass(obj[2]) + for subclass in ManagedObj.__subclasses__() + if subclass.__name__ == obj[1] + ) diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/analysis/viz.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/analysis/viz.py index 21d8990..ca17501 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/analysis/viz.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/analysis/viz.py @@ -24,23 +24,12 @@ class VizNode(base.MaxwellSimNode): 'Data': sockets.AnySocketDef(), 'Freq': sockets.PhysicalFreqSocketDef(), } - # input_sockets_sets: typ.ClassVar = { - # '2D Freq': { - # 'Data': sockets.AnySocketDef(), - # 'Freq': sockets.PhysicalFreqSocketDef(), - # }, - # } output_sockets: typ.ClassVar = { 'Preview': sockets.AnySocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'plot': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLImage(name), - ), - #'empty': ct.schemas.ManagedObjDef( - # mk=lambda name: managed_objs.ManagedBLEmpty(name), - # ), + managed_obj_types: typ.ClassVar = { + 'plot': managed_objs.ManagedBLImage, } ##################### @@ -78,7 +67,7 @@ class VizNode(base.MaxwellSimNode): ) def on_show_plot( self, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, props: dict, unit_systems: dict, 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 cc0ddb0..a420db3 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 @@ -12,11 +12,13 @@ import bpy import sympy as sp import typing_extensions as typx -from ....utils import logger -from .. import bl_cache +from blender_maxwell.utils import logger + +from .. import bl_cache, sockets from .. import contracts as ct from .. import managed_objs as _managed_objs from . import events +from . import presets as _presets log = logger.get(__name__) @@ -42,17 +44,23 @@ class MaxwellSimNode(bpy.types.Node): ## TODO: bl_description from first line of __doc__? # Sockets - input_sockets: typ.ClassVar[dict[str, ct.schemas.SocketDef]] = MappingProxyType({}) - output_sockets: typ.ClassVar[dict[str, ct.schemas.SocketDef]] = MappingProxyType({}) - input_socket_sets: typ.ClassVar[dict[str, dict[str, ct.schemas.SocketDef]]] = ( + input_sockets: typ.ClassVar[dict[str, sockets.base.SocketDef]] = MappingProxyType( + {} + ) + output_sockets: typ.ClassVar[dict[str, sockets.base.SocketDef]] = MappingProxyType( + {} + ) + input_socket_sets: typ.ClassVar[dict[str, dict[str, sockets.base.SocketDef]]] = ( MappingProxyType({}) ) - output_socket_sets: typ.ClassVar[dict[str, dict[str, ct.schemas.SocketDef]]] = ( + output_socket_sets: typ.ClassVar[dict[str, dict[str, sockets.base.SocketDef]]] = ( MappingProxyType({}) ) # Presets - presets: typ.ClassVar = MappingProxyType({}) + presets: typ.ClassVar[dict[str, dict[str, _presets.PresetDef]]] = MappingProxyType( + {} + ) # Managed Objects managed_obj_types: typ.ClassVar[ @@ -300,8 +308,8 @@ class MaxwellSimNode(bpy.types.Node): #################### # - Loose Sockets w/Events #################### - loose_input_sockets: dict[str, ct.schemas.SocketDef] = bl_cache.BLField({}) - loose_output_sockets: dict[str, ct.schemas.SocketDef] = bl_cache.BLField({}) + loose_input_sockets: dict[str, sockets.base.SocketDef] = bl_cache.BLField({}) + loose_output_sockets: dict[str, sockets.base.SocketDef] = bl_cache.BLField({}) @events.on_value_changed(prop_name={'loose_input_sockets', 'loose_output_sockets'}) def _on_loose_sockets_changed(self): @@ -331,7 +339,7 @@ class MaxwellSimNode(bpy.types.Node): def _active_socket_set_socket_defs( self, direc: typx.Literal['input', 'output'], - ) -> dict[ct.SocketName, ct.schemas.SocketDef]: + ) -> dict[ct.SocketName, sockets.base.SocketDef]: """Retrieve all socket definitions for sockets that should be defined, according to the `self.active_socket_set`. Notes: @@ -341,7 +349,7 @@ class MaxwellSimNode(bpy.types.Node): direc: The direction to load Blender sockets from. Returns: - Mapping from socket names to corresponding `ct.schemas.SocketDef`s. + Mapping from socket names to corresponding `sockets.base.SocketDef`s. If `self.active_socket_set` is None, the empty dict is returned. """ @@ -357,14 +365,14 @@ class MaxwellSimNode(bpy.types.Node): def active_socket_defs( self, direc: typx.Literal['input', 'output'] - ) -> dict[ct.SocketName, ct.schemas.SocketDef]: + ) -> dict[ct.SocketName, sockets.base.SocketDef]: """Retrieve all socket definitions for sockets that should be defined. Parameters: direc: The direction to load Blender sockets from. Returns: - Mapping from socket names to corresponding `ct.schemas.SocketDef`s. + Mapping from socket names to corresponding `sockets.base.SocketDef`s. """ static_sockets = self.input_sockets if direc == 'input' else self.output_sockets loose_sockets = ( @@ -700,13 +708,6 @@ class MaxwellSimNode(bpy.types.Node): stop_propagation |= event_method.stop_propagation event_method(self) - # Stop Propagation (maybe) - if ( - ct.DataFlowAction.stop_if_no_event_methods(action) - and len(triggered_event_methods) == 0 - ): - return - # Propagate Action to All Sockets in "Trigger Direction" ## The trigger chain goes node/socket/node/socket/... if not stop_propagation: diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/file_importers/tidy_3d_file_importer.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/file_importers/tidy_3d_file_importer.py index ad91f2d..dc0008c 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/file_importers/tidy_3d_file_importer.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/file_importers/tidy_3d_file_importer.py @@ -47,11 +47,8 @@ class Tidy3DFileImporterNode(base.MaxwellSimNode): input_sockets: typ.ClassVar = { 'File Path': sockets.FilePathSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'plot': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLImage(name), - name_prefix='', - ), + managed_obj_types: typ.ClassVar = { + 'plot': managed_objs.ManagedBLImage, } #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/mediums/library_medium.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/mediums/library_medium.py index 28289e6..aff1e9f 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/mediums/library_medium.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/mediums/library_medium.py @@ -26,11 +26,8 @@ class LibraryMediumNode(base.MaxwellSimNode): 'Medium': sockets.MaxwellMediumSocketDef(), } - managed_obj_defs = { - 'nk_plot': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLImage(name), - name_prefix='', - ) + managed_obj_types = { + 'nk_plot': managed_objs.ManagedBLImage, } #################### @@ -125,8 +122,8 @@ class LibraryMediumNode(base.MaxwellSimNode): ) def on_show_plot( self, - managed_objs: dict[str, ct.schemas.ManagedObj], - props: dict[str, typ.Any], + managed_objs: dict, + props: dict, ): medium = td.material_library[props['material']].medium freq_range = [ diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/eh_field_monitor.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/eh_field_monitor.py index b29c127..e10d243 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/eh_field_monitor.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/eh_field_monitor.py @@ -49,13 +49,9 @@ class EHFieldMonitorNode(base.MaxwellSimNode): 'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()}, } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -117,7 +113,7 @@ class EHFieldMonitorNode(base.MaxwellSimNode): def on_inputs_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, unit_systems: dict, ): diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/field_power_flux_monitor.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/field_power_flux_monitor.py index d84a5d2..805488c 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/field_power_flux_monitor.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/monitors/field_power_flux_monitor.py @@ -48,13 +48,9 @@ class PowerFluxMonitorNode(base.MaxwellSimNode): 'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()}, } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -96,7 +92,7 @@ class PowerFluxMonitorNode(base.MaxwellSimNode): center=input_sockets['Center'], size=input_sockets['Size'], name=props['sim_node_name'], - interval_space=(1,1,1), + interval_space=(1, 1, 1), freqs=input_sockets['Freqs'].realize().values, normal_dir='+' if input_sockets['Direction'] else '-', ) @@ -118,7 +114,7 @@ class PowerFluxMonitorNode(base.MaxwellSimNode): def on_inputs_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, unit_systems: dict, ): diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/preset_def.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/presets.py similarity index 51% rename from src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/preset_def.py rename to src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/presets.py index 4ef1a2b..66c72e4 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/preset_def.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/presets.py @@ -2,10 +2,10 @@ import typing as typ import pydantic as pyd -from ..bl import PresetName, SocketName +from .. import contracts as ct class PresetDef(pyd.BaseModel): - label: PresetName + label: ct.PresetName description: str - values: dict[SocketName, typ.Any] + values: dict[ct.SocketName, typ.Any] diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/sim_domain.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/sim_domain.py index 39cfbc8..ba7f199 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/sim_domain.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/sim_domain.py @@ -28,14 +28,9 @@ class SimDomainNode(base.MaxwellSimNode): 'Domain': sockets.MaxwellSimDomainSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - name_prefix='', - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -75,7 +70,7 @@ class SimDomainNode(base.MaxwellSimNode): def on_input_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, unit_systems: dict, ): diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py index 7629831..551d2e5 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py @@ -56,11 +56,8 @@ class PlaneWaveSourceNode(base.MaxwellSimNode): 'Source': sockets.MaxwellSourceSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'plane_wave_source': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLObject(name), - name_prefix='', - ) + managed_obj_types: typ.ClassVar = { + 'plane_wave_source': managed_objs.ManagedBLMesh, } #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py index a231a6a..9aa7931 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py @@ -26,11 +26,8 @@ class PointDipoleSourceNode(base.MaxwellSimNode): 'Source': sockets.MaxwellSourceSocketDef(), } - managed_obj_defs = { - 'sphere_empty': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLObject(name), - name_prefix='', - ) + managed_obj_types = { + 'mesh': managed_objs.ManagedBLMesh, } #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py index 9724104..6a4eb61 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py @@ -41,11 +41,8 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode): 'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(), } - managed_obj_defs = { - 'amp_time': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLImage(name), - name_prefix='amp_time_', - ) + managed_obj_types = { + 'amp_time': managed_objs.ManagedBLImage, } #################### @@ -123,9 +120,9 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode): ) def on_show_plot( self, - managed_objs: dict[str, ct.schemas.ManagedObj], - output_sockets: dict[str, typ.Any], - props: dict[str, typ.Any], + managed_objs: dict, + output_sockets: dict, + props: dict, ): temporal_shape = output_sockets['Temporal Shape'] plot_time_start = props['plot_time_start'] * 1e-15 diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py index df542f2..1a11837 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/geonodes_structure.py @@ -27,13 +27,9 @@ class GeoNodesStructureNode(base.MaxwellSimNode): 'Structure': sockets.MaxwellStructureSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -46,8 +42,8 @@ class GeoNodesStructureNode(base.MaxwellSimNode): ) def compute_structure( self, - input_sockets: dict[str, typ.Any], - managed_objs: dict[str, ct.schemas.ManagedObj], + input_sockets: dict, + managed_objs: dict, ) -> td.Structure: # Simulate Input Value Change ## This ensures that the mesh has been re-computed. @@ -68,7 +64,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode): # - Event Methods #################### @events.on_value_changed( - socket_name='GeoNodes', + socket_name={'GeoNodes', 'Center'}, prop_name='preview_active', any_loose_input_socket=True, run_on_init=True, @@ -83,7 +79,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode): def on_input_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, loose_input_sockets: dict, unit_systems: dict, diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py index 9dc8635..e096972 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py @@ -29,13 +29,9 @@ class BoxStructureNode(base.MaxwellSimNode): 'Structure': sockets.MaxwellStructureSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -74,7 +70,7 @@ class BoxStructureNode(base.MaxwellSimNode): def on_inputs_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, unit_systems: dict, ): diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/sphere_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/sphere_structure.py index fae1deb..75cfcc0 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/sphere_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/sphere_structure.py @@ -28,13 +28,9 @@ class SphereStructureNode(base.MaxwellSimNode): 'Structure': sockets.MaxwellStructureSocketDef(), } - managed_obj_defs: typ.ClassVar = { - 'mesh': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLMesh(name), - ), - 'modifier': ct.schemas.ManagedObjDef( - mk=lambda name: managed_objs.ManagedBLModifier(name), - ), + managed_obj_types: typ.ClassVar = { + 'mesh': managed_objs.ManagedBLMesh, + 'modifier': managed_objs.ManagedBLModifier, } #################### @@ -77,7 +73,7 @@ class SphereStructureNode(base.MaxwellSimNode): def on_inputs_changed( self, props: dict, - managed_objs: dict[str, ct.schemas.ManagedObj], + managed_objs: dict, input_sockets: dict, unit_systems: dict, ): 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 64193dd..8db6141 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 @@ -7,10 +7,8 @@ import pydantic as pyd import sympy as sp import typing_extensions as typx -from .....utils import serialize -from ....utils import logger +from ....utils import logger, serialize from .. import contracts as ct -from ..socket_types import SocketType log = logger.get(__name__) @@ -19,7 +17,7 @@ log = logger.get(__name__) # - SocketDef #################### class SocketDef(pyd.BaseModel, abc.ABC): - socket_type: SocketType + socket_type: ct.SocketType @abc.abstractmethod def init(self, bl_socket: bpy.types.NodeSocket) -> None: @@ -33,7 +31,11 @@ class SocketDef(pyd.BaseModel, abc.ABC): @staticmethod def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self: - return SocketDef.__subclasses__[obj[1]](**obj[2]) + return next( + subclass(**obj[2]) + for subclass in SocketDef.__subclasses__() + if subclass.__name__ == obj[1] + ) #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/scan_socket_defs.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/scan_socket_defs.py index 44ebbb5..f0f82e5 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/scan_socket_defs.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/scan_socket_defs.py @@ -3,9 +3,10 @@ import types from .. import contracts as ct +## TODO: Replace with BL_SOCKET_DEFS export from each module, a little like BL_NODES. def scan_for_socket_defs( sockets_module: types.ModuleType, -) -> dict[ct.SocketType, type[ct.schemas.SocketDef]]: +) -> dict: return { socket_type: getattr( sockets_module, diff --git a/src/blender_maxwell/utils/extra_sympy_units.py b/src/blender_maxwell/utils/extra_sympy_units.py index 91ce27e..83bcefd 100644 --- a/src/blender_maxwell/utils/extra_sympy_units.py +++ b/src/blender_maxwell/utils/extra_sympy_units.py @@ -5,7 +5,7 @@ import typing as typ import sympy as sp import sympy.physics.units as spu -SympyType = sp.Basic | sp.Expr | sp.MatrixBase | sp.Quantity +SympyType = sp.Basic | sp.Expr | sp.MatrixBase | spu.Quantity #################### diff --git a/src/blender_maxwell/utils/serialize.py b/src/blender_maxwell/utils/serialize.py index 36a1030..6e3dfc3 100644 --- a/src/blender_maxwell/utils/serialize.py +++ b/src/blender_maxwell/utils/serialize.py @@ -1,6 +1,7 @@ -"""Attributes: -NaiveEncodableType: -See for details. +"""Robust serialization tool for use in the addon. + +Attributes: + NaiveEncodableType: See for details. """ import dataclasses @@ -61,19 +62,20 @@ NaivelyEncodableType: typ.TypeAlias = ( | enum.Flag | enum.IntFlag | dataclasses.dataclass - | typ.Optional - | typ.Union + | typ.Optional[typ.Any] # noqa: UP007 + | typ.Union[typ.Any, ...] # noqa: UP007 | typ.NewType | typ.TypeAlias - | typ.TypeAliasType - | typ.Generic - | typ.TypeVar - | typ.Final + ## SUPPORT: + # | typ.Generic[typ.Any] + # | typ.TypeVar + # | typ.Final | msgspec.Raw ## NO SUPPORT: # | msgspec.UNSET ) _NaivelyEncodableTypeSet = frozenset(typ.get_args(NaivelyEncodableType)) +## TODO: Use for runtime type check? Beartype? class TypeID(enum.StrEnum): @@ -87,7 +89,7 @@ NaiveRepresentation: typ.TypeAlias = list[TypeID, str | None, typ.Any] def is_representation(obj: NaivelyEncodableType) -> bool: - return isinstance(obj, list) and obj[0] in set(TypeID) and len(obj) == 3 # noqa: PLR2004 + return isinstance(obj, list) and len(obj) == 3 and obj[0] in set(TypeID) # noqa: PLR2004 #################### @@ -141,7 +143,9 @@ def _dec_hook(_type: type, obj: NaivelyEncodableType) -> typ.Any: obj_value = obj[2] return sp.sympify(obj_value).subs(spux.ALL_UNIT_SYMBOLS) - if hasattr(obj, 'parse_as_msgspec'): + if hasattr(_type, 'parse_as_msgspec') and ( + is_representation(obj) and obj[0] in [TypeID.SocketDef, TypeID.ManagedObj] + ): return _type.parse_as_msgspec(obj) msg = f'Can\'t decode "{obj}" to type {type(obj)}'