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!main
parent
269af4ba32
commit
568fc449e8
4
TODO.md
4
TODO.md
|
@ -504,7 +504,7 @@ Unreported:
|
||||||
- We found the translation callback! https://projects.blender.org/blender/blender/commit/8564e03cdf59fb2a71d545e81871411b82f561d9
|
- We found the translation callback! https://projects.blender.org/blender/blender/commit/8564e03cdf59fb2a71d545e81871411b82f561d9
|
||||||
- This can update the node center!!
|
- This can update the node center!!
|
||||||
|
|
||||||
- [ ] Optimize the `DataChanged` invalidator.
|
- [x] Optimize the `DataChanged` invalidator.
|
||||||
- [ ] Optimize unit stripping.
|
- [ ] 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] 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
|
- [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
|
- [ ] 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
|
### Sweeping Features
|
||||||
- [ ] Replace all raw Blender properties with `BLField`.
|
- [ ] Replace all raw Blender properties with `BLField`.
|
||||||
|
|
|
@ -33,9 +33,11 @@ class BLInstance(typ.Protocol):
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
PropGetMethod: typ.TypeAlias = typ.Callable[[BLInstance], serialize.EncodableValue]
|
PropGetMethod: typ.TypeAlias = typ.Callable[
|
||||||
|
[BLInstance], serialize.NaivelyEncodableType
|
||||||
|
]
|
||||||
PropSetMethod: typ.TypeAlias = typ.Callable[
|
PropSetMethod: typ.TypeAlias = typ.Callable[
|
||||||
[BLInstance, serialize.EncodableValue], None
|
[BLInstance, serialize.NaivelyEncodableType], None
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ def _socket_def_from_bl_socket(
|
||||||
|
|
||||||
def socket_def_from_bl_socket(
|
def socket_def_from_bl_socket(
|
||||||
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
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."""
|
"""Computes an appropriate (no-arg) SocketDef from the given `bl_interface_socket`, by parsing it."""
|
||||||
return _socket_def_from_bl_socket(
|
return _socket_def_from_bl_socket(
|
||||||
bl_interface_socket.description, bl_interface_socket.bl_socket_idname
|
bl_interface_socket.description, bl_interface_socket.bl_socket_idname
|
||||||
|
|
|
@ -65,11 +65,6 @@ from .data_flows import (
|
||||||
)
|
)
|
||||||
from .data_flow_actions import DataFlowAction
|
from .data_flow_actions import DataFlowAction
|
||||||
|
|
||||||
####################
|
|
||||||
# - Schemas
|
|
||||||
####################
|
|
||||||
from . import schemas
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Export
|
# - Export
|
||||||
####################
|
####################
|
||||||
|
@ -103,5 +98,4 @@ __all__ = [
|
||||||
'LazyDataValueRange',
|
'LazyDataValueRange',
|
||||||
'LazyDataValueSpectrum',
|
'LazyDataValueSpectrum',
|
||||||
'DataFlowAction',
|
'DataFlowAction',
|
||||||
'schemas',
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -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',
|
|
||||||
]
|
|
|
@ -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])
|
|
|
@ -1,9 +1,12 @@
|
||||||
import abc
|
import abc
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
from ....utils import serialize
|
from blender_maxwell.utils import logger, serialize
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
|
||||||
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ManagedObj(abc.ABC):
|
class ManagedObj(abc.ABC):
|
||||||
managed_obj_type: ct.ManagedObjType
|
managed_obj_type: ct.ManagedObjType
|
||||||
|
@ -50,9 +53,13 @@ class ManagedObj(abc.ABC):
|
||||||
return [
|
return [
|
||||||
serialize.TypeID.ManagedObj,
|
serialize.TypeID.ManagedObj,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
(self.managed_obj_type, self.name),
|
self.name,
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self:
|
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]
|
||||||
|
)
|
||||||
|
|
|
@ -24,23 +24,12 @@ class VizNode(base.MaxwellSimNode):
|
||||||
'Data': sockets.AnySocketDef(),
|
'Data': sockets.AnySocketDef(),
|
||||||
'Freq': sockets.PhysicalFreqSocketDef(),
|
'Freq': sockets.PhysicalFreqSocketDef(),
|
||||||
}
|
}
|
||||||
# input_sockets_sets: typ.ClassVar = {
|
|
||||||
# '2D Freq': {
|
|
||||||
# 'Data': sockets.AnySocketDef(),
|
|
||||||
# 'Freq': sockets.PhysicalFreqSocketDef(),
|
|
||||||
# },
|
|
||||||
# }
|
|
||||||
output_sockets: typ.ClassVar = {
|
output_sockets: typ.ClassVar = {
|
||||||
'Preview': sockets.AnySocketDef(),
|
'Preview': sockets.AnySocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'plot': ct.schemas.ManagedObjDef(
|
'plot': managed_objs.ManagedBLImage,
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
|
||||||
),
|
|
||||||
#'empty': ct.schemas.ManagedObjDef(
|
|
||||||
# mk=lambda name: managed_objs.ManagedBLEmpty(name),
|
|
||||||
# ),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
|
@ -78,7 +67,7 @@ class VizNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
props: dict,
|
props: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
|
|
|
@ -12,11 +12,13 @@ import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import typing_extensions as typx
|
import typing_extensions as typx
|
||||||
|
|
||||||
from ....utils import logger
|
from blender_maxwell.utils import logger
|
||||||
from .. import bl_cache
|
|
||||||
|
from .. import bl_cache, sockets
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
from .. import managed_objs as _managed_objs
|
from .. import managed_objs as _managed_objs
|
||||||
from . import events
|
from . import events
|
||||||
|
from . import presets as _presets
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
@ -42,17 +44,23 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
## TODO: bl_description from first line of __doc__?
|
## TODO: bl_description from first line of __doc__?
|
||||||
|
|
||||||
# Sockets
|
# Sockets
|
||||||
input_sockets: typ.ClassVar[dict[str, ct.schemas.SocketDef]] = MappingProxyType({})
|
input_sockets: typ.ClassVar[dict[str, sockets.base.SocketDef]] = MappingProxyType(
|
||||||
output_sockets: typ.ClassVar[dict[str, ct.schemas.SocketDef]] = MappingProxyType({})
|
{}
|
||||||
input_socket_sets: typ.ClassVar[dict[str, dict[str, ct.schemas.SocketDef]]] = (
|
)
|
||||||
|
output_sockets: typ.ClassVar[dict[str, sockets.base.SocketDef]] = MappingProxyType(
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
input_socket_sets: typ.ClassVar[dict[str, dict[str, sockets.base.SocketDef]]] = (
|
||||||
MappingProxyType({})
|
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({})
|
MappingProxyType({})
|
||||||
)
|
)
|
||||||
|
|
||||||
# Presets
|
# Presets
|
||||||
presets: typ.ClassVar = MappingProxyType({})
|
presets: typ.ClassVar[dict[str, dict[str, _presets.PresetDef]]] = MappingProxyType(
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
|
||||||
# Managed Objects
|
# Managed Objects
|
||||||
managed_obj_types: typ.ClassVar[
|
managed_obj_types: typ.ClassVar[
|
||||||
|
@ -300,8 +308,8 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
####################
|
####################
|
||||||
# - Loose Sockets w/Events
|
# - Loose Sockets w/Events
|
||||||
####################
|
####################
|
||||||
loose_input_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, ct.schemas.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'})
|
@events.on_value_changed(prop_name={'loose_input_sockets', 'loose_output_sockets'})
|
||||||
def _on_loose_sockets_changed(self):
|
def _on_loose_sockets_changed(self):
|
||||||
|
@ -331,7 +339,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
def _active_socket_set_socket_defs(
|
def _active_socket_set_socket_defs(
|
||||||
self,
|
self,
|
||||||
direc: typx.Literal['input', 'output'],
|
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`.
|
"""Retrieve all socket definitions for sockets that should be defined, according to the `self.active_socket_set`.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
@ -341,7 +349,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
direc: The direction to load Blender sockets from.
|
direc: The direction to load Blender sockets from.
|
||||||
|
|
||||||
Returns:
|
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.
|
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(
|
def active_socket_defs(
|
||||||
self, direc: typx.Literal['input', 'output']
|
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.
|
"""Retrieve all socket definitions for sockets that should be defined.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
direc: The direction to load Blender sockets from.
|
direc: The direction to load Blender sockets from.
|
||||||
|
|
||||||
Returns:
|
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
|
static_sockets = self.input_sockets if direc == 'input' else self.output_sockets
|
||||||
loose_sockets = (
|
loose_sockets = (
|
||||||
|
@ -700,13 +708,6 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
stop_propagation |= event_method.stop_propagation
|
stop_propagation |= event_method.stop_propagation
|
||||||
event_method(self)
|
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"
|
# Propagate Action to All Sockets in "Trigger Direction"
|
||||||
## The trigger chain goes node/socket/node/socket/...
|
## The trigger chain goes node/socket/node/socket/...
|
||||||
if not stop_propagation:
|
if not stop_propagation:
|
||||||
|
|
|
@ -47,11 +47,8 @@ class Tidy3DFileImporterNode(base.MaxwellSimNode):
|
||||||
input_sockets: typ.ClassVar = {
|
input_sockets: typ.ClassVar = {
|
||||||
'File Path': sockets.FilePathSocketDef(),
|
'File Path': sockets.FilePathSocketDef(),
|
||||||
}
|
}
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'plot': ct.schemas.ManagedObjDef(
|
'plot': managed_objs.ManagedBLImage,
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
|
||||||
name_prefix='',
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -26,11 +26,8 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
'Medium': sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_types = {
|
||||||
'nk_plot': ct.schemas.ManagedObjDef(
|
'nk_plot': managed_objs.ManagedBLImage,
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
|
||||||
name_prefix='',
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -125,8 +122,8 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
props: dict[str, typ.Any],
|
props: dict,
|
||||||
):
|
):
|
||||||
medium = td.material_library[props['material']].medium
|
medium = td.material_library[props['material']].medium
|
||||||
freq_range = [
|
freq_range = [
|
||||||
|
|
|
@ -49,13 +49,9 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()},
|
'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()},
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -117,7 +113,7 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
def on_inputs_changed(
|
def on_inputs_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
):
|
):
|
||||||
|
|
|
@ -48,13 +48,9 @@ class PowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()},
|
'Time Domain': {'Time Monitor': sockets.MaxwellMonitorSocketDef()},
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -96,7 +92,7 @@ class PowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
center=input_sockets['Center'],
|
center=input_sockets['Center'],
|
||||||
size=input_sockets['Size'],
|
size=input_sockets['Size'],
|
||||||
name=props['sim_node_name'],
|
name=props['sim_node_name'],
|
||||||
interval_space=(1,1,1),
|
interval_space=(1, 1, 1),
|
||||||
freqs=input_sockets['Freqs'].realize().values,
|
freqs=input_sockets['Freqs'].realize().values,
|
||||||
normal_dir='+' if input_sockets['Direction'] else '-',
|
normal_dir='+' if input_sockets['Direction'] else '-',
|
||||||
)
|
)
|
||||||
|
@ -118,7 +114,7 @@ class PowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
def on_inputs_changed(
|
def on_inputs_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
):
|
):
|
||||||
|
|
|
@ -2,10 +2,10 @@ import typing as typ
|
||||||
|
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from ..bl import PresetName, SocketName
|
from .. import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
class PresetDef(pyd.BaseModel):
|
class PresetDef(pyd.BaseModel):
|
||||||
label: PresetName
|
label: ct.PresetName
|
||||||
description: str
|
description: str
|
||||||
values: dict[SocketName, typ.Any]
|
values: dict[ct.SocketName, typ.Any]
|
|
@ -28,14 +28,9 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
'Domain': sockets.MaxwellSimDomainSocketDef(),
|
'Domain': sockets.MaxwellSimDomainSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
name_prefix='',
|
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -75,7 +70,7 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
def on_input_changed(
|
def on_input_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
):
|
):
|
||||||
|
|
|
@ -56,11 +56,8 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
'Source': sockets.MaxwellSourceSocketDef(),
|
'Source': sockets.MaxwellSourceSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'plane_wave_source': ct.schemas.ManagedObjDef(
|
'plane_wave_source': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
|
||||||
name_prefix='',
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -26,11 +26,8 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
'Source': sockets.MaxwellSourceSocketDef(),
|
'Source': sockets.MaxwellSourceSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_types = {
|
||||||
'sphere_empty': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
|
||||||
name_prefix='',
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -41,11 +41,8 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_types = {
|
||||||
'amp_time': ct.schemas.ManagedObjDef(
|
'amp_time': managed_objs.ManagedBLImage,
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
|
||||||
name_prefix='amp_time_',
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -123,9 +120,9 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
output_sockets: dict[str, typ.Any],
|
output_sockets: dict,
|
||||||
props: dict[str, typ.Any],
|
props: dict,
|
||||||
):
|
):
|
||||||
temporal_shape = output_sockets['Temporal Shape']
|
temporal_shape = output_sockets['Temporal Shape']
|
||||||
plot_time_start = props['plot_time_start'] * 1e-15
|
plot_time_start = props['plot_time_start'] * 1e-15
|
||||||
|
|
|
@ -27,13 +27,9 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
'Structure': sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -46,8 +42,8 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
def compute_structure(
|
def compute_structure(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict[str, typ.Any],
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
) -> td.Structure:
|
) -> td.Structure:
|
||||||
# Simulate Input Value Change
|
# Simulate Input Value Change
|
||||||
## This ensures that the mesh has been re-computed.
|
## This ensures that the mesh has been re-computed.
|
||||||
|
@ -68,7 +64,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
# - Event Methods
|
# - Event Methods
|
||||||
####################
|
####################
|
||||||
@events.on_value_changed(
|
@events.on_value_changed(
|
||||||
socket_name='GeoNodes',
|
socket_name={'GeoNodes', 'Center'},
|
||||||
prop_name='preview_active',
|
prop_name='preview_active',
|
||||||
any_loose_input_socket=True,
|
any_loose_input_socket=True,
|
||||||
run_on_init=True,
|
run_on_init=True,
|
||||||
|
@ -83,7 +79,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
def on_input_changed(
|
def on_input_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
loose_input_sockets: dict,
|
loose_input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
|
|
|
@ -29,13 +29,9 @@ class BoxStructureNode(base.MaxwellSimNode):
|
||||||
'Structure': sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -74,7 +70,7 @@ class BoxStructureNode(base.MaxwellSimNode):
|
||||||
def on_inputs_changed(
|
def on_inputs_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
):
|
):
|
||||||
|
|
|
@ -28,13 +28,9 @@ class SphereStructureNode(base.MaxwellSimNode):
|
||||||
'Structure': sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs: typ.ClassVar = {
|
managed_obj_types: typ.ClassVar = {
|
||||||
'mesh': ct.schemas.ManagedObjDef(
|
'mesh': managed_objs.ManagedBLMesh,
|
||||||
mk=lambda name: managed_objs.ManagedBLMesh(name),
|
'modifier': managed_objs.ManagedBLModifier,
|
||||||
),
|
|
||||||
'modifier': ct.schemas.ManagedObjDef(
|
|
||||||
mk=lambda name: managed_objs.ManagedBLModifier(name),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -77,7 +73,7 @@ class SphereStructureNode(base.MaxwellSimNode):
|
||||||
def on_inputs_changed(
|
def on_inputs_changed(
|
||||||
self,
|
self,
|
||||||
props: dict,
|
props: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
unit_systems: dict,
|
unit_systems: dict,
|
||||||
):
|
):
|
||||||
|
|
|
@ -7,10 +7,8 @@ import pydantic as pyd
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import typing_extensions as typx
|
import typing_extensions as typx
|
||||||
|
|
||||||
from .....utils import serialize
|
from ....utils import logger, serialize
|
||||||
from ....utils import logger
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
from ..socket_types import SocketType
|
|
||||||
|
|
||||||
log = logger.get(__name__)
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
@ -19,7 +17,7 @@ log = logger.get(__name__)
|
||||||
# - SocketDef
|
# - SocketDef
|
||||||
####################
|
####################
|
||||||
class SocketDef(pyd.BaseModel, abc.ABC):
|
class SocketDef(pyd.BaseModel, abc.ABC):
|
||||||
socket_type: SocketType
|
socket_type: ct.SocketType
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def init(self, bl_socket: bpy.types.NodeSocket) -> None:
|
def init(self, bl_socket: bpy.types.NodeSocket) -> None:
|
||||||
|
@ -33,7 +31,11 @@ class SocketDef(pyd.BaseModel, abc.ABC):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_as_msgspec(obj: serialize.NaiveRepresentation) -> typ.Self:
|
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]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -3,9 +3,10 @@ import types
|
||||||
from .. import contracts as ct
|
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(
|
def scan_for_socket_defs(
|
||||||
sockets_module: types.ModuleType,
|
sockets_module: types.ModuleType,
|
||||||
) -> dict[ct.SocketType, type[ct.schemas.SocketDef]]:
|
) -> dict:
|
||||||
return {
|
return {
|
||||||
socket_type: getattr(
|
socket_type: getattr(
|
||||||
sockets_module,
|
sockets_module,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import typing as typ
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
SympyType = sp.Basic | sp.Expr | sp.MatrixBase | sp.Quantity
|
SympyType = sp.Basic | sp.Expr | sp.MatrixBase | spu.Quantity
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Attributes:
|
"""Robust serialization tool for use in the addon.
|
||||||
NaiveEncodableType:
|
|
||||||
See <https://jcristharif.com/msgspec/supported-types.html> for details.
|
Attributes:
|
||||||
|
NaiveEncodableType: See <https://jcristharif.com/msgspec/supported-types.html> for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
@ -61,19 +62,20 @@ NaivelyEncodableType: typ.TypeAlias = (
|
||||||
| enum.Flag
|
| enum.Flag
|
||||||
| enum.IntFlag
|
| enum.IntFlag
|
||||||
| dataclasses.dataclass
|
| dataclasses.dataclass
|
||||||
| typ.Optional
|
| typ.Optional[typ.Any] # noqa: UP007
|
||||||
| typ.Union
|
| typ.Union[typ.Any, ...] # noqa: UP007
|
||||||
| typ.NewType
|
| typ.NewType
|
||||||
| typ.TypeAlias
|
| typ.TypeAlias
|
||||||
| typ.TypeAliasType
|
## SUPPORT:
|
||||||
| typ.Generic
|
# | typ.Generic[typ.Any]
|
||||||
| typ.TypeVar
|
# | typ.TypeVar
|
||||||
| typ.Final
|
# | typ.Final
|
||||||
| msgspec.Raw
|
| msgspec.Raw
|
||||||
## NO SUPPORT:
|
## NO SUPPORT:
|
||||||
# | msgspec.UNSET
|
# | msgspec.UNSET
|
||||||
)
|
)
|
||||||
_NaivelyEncodableTypeSet = frozenset(typ.get_args(NaivelyEncodableType))
|
_NaivelyEncodableTypeSet = frozenset(typ.get_args(NaivelyEncodableType))
|
||||||
|
## TODO: Use for runtime type check? Beartype?
|
||||||
|
|
||||||
|
|
||||||
class TypeID(enum.StrEnum):
|
class TypeID(enum.StrEnum):
|
||||||
|
@ -87,7 +89,7 @@ NaiveRepresentation: typ.TypeAlias = list[TypeID, str | None, typ.Any]
|
||||||
|
|
||||||
|
|
||||||
def is_representation(obj: NaivelyEncodableType) -> bool:
|
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]
|
obj_value = obj[2]
|
||||||
return sp.sympify(obj_value).subs(spux.ALL_UNIT_SYMBOLS)
|
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)
|
return _type.parse_as_msgspec(obj)
|
||||||
|
|
||||||
msg = f'Can\'t decode "{obj}" to type {type(obj)}'
|
msg = f'Can\'t decode "{obj}" to type {type(obj)}'
|
||||||
|
|
Loading…
Reference in New Issue