From 568fc449e818da3e06e799c9789dff7f8c2eaf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofus=20Albert=20H=C3=B8gsbro=20Rose?= Date: Mon, 15 Apr 2024 19:15:20 +0200 Subject: [PATCH] fix: Caching now (seems to) work robustly. The serialization routines are fast and effective. Overall, the node graph feels snappy, and everything updates smoothly. Logging on the action chain suggests that there aren't extraneous calls, and that existing calls (ex. no-op previews) are fast. There will likely be edge cases, and we'll see how it scales - but for now, let's go with it! --- TODO.md | 4 +- .../node_trees/maxwell_sim_nodes/bl_cache.py | 6 ++- .../maxwell_sim_nodes/bl_socket_map.py | 2 +- .../maxwell_sim_nodes/contracts/__init__.py | 6 --- .../contracts/schemas/__init__.py | 11 ----- .../contracts/schemas/managed_obj.py | 0 .../contracts/schemas/managed_obj_def.py | 0 .../contracts/schemas/socket_def.py | 26 ------------ .../maxwell_sim_nodes/managed_objs/base.py | 13 ++++-- .../maxwell_sim_nodes/nodes/analysis/viz.py | 17 ++------ .../maxwell_sim_nodes/nodes/base.py | 41 ++++++++++--------- .../file_importers/tidy_3d_file_importer.py | 7 +--- .../nodes/mediums/library_medium.py | 11 ++--- .../nodes/monitors/eh_field_monitor.py | 12 ++---- .../monitors/field_power_flux_monitor.py | 14 +++---- .../preset_def.py => nodes/presets.py} | 6 +-- .../nodes/simulations/sim_domain.py | 13 ++---- .../nodes/sources/plane_wave_source.py | 7 +--- .../nodes/sources/point_dipole_source.py | 7 +--- .../gaussian_pulse_temporal_shape.py | 13 +++--- .../nodes/structures/geonodes_structure.py | 18 ++++---- .../structures/primitives/box_structure.py | 12 ++---- .../structures/primitives/sphere_structure.py | 12 ++---- .../maxwell_sim_nodes/sockets/base.py | 12 +++--- .../sockets/scan_socket_defs.py | 3 +- .../utils/extra_sympy_units.py | 2 +- src/blender_maxwell/utils/serialize.py | 26 +++++++----- 27 files changed, 112 insertions(+), 189 deletions(-) delete mode 100644 src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/__init__.py delete mode 100644 src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj.py delete mode 100644 src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/managed_obj_def.py delete mode 100644 src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/schemas/socket_def.py rename src/blender_maxwell/node_trees/maxwell_sim_nodes/{contracts/schemas/preset_def.py => nodes/presets.py} (51%) 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)}'