chore: Ran code formatter over all files
parent
be4eec2242
commit
0fbf201d08
|
@ -41,7 +41,7 @@ PATH_ADDON_ZIP = (
|
||||||
|
|
||||||
PATH_ADDON_BLEND_STARTER = PATH_ADDON_PKG / 'blenders' / 'starter.blend'
|
PATH_ADDON_BLEND_STARTER = PATH_ADDON_PKG / 'blenders' / 'starter.blend'
|
||||||
|
|
||||||
# Install the ZIPped Addon
|
# Install the ZIPped Addon
|
||||||
####################
|
####################
|
||||||
# - Development Information
|
# - Development Information
|
||||||
####################
|
####################
|
||||||
|
@ -49,4 +49,3 @@ PATH_ADDON_DEV_BLEND = PATH_DEV / 'demo.blend'
|
||||||
|
|
||||||
PATH_ADDON_DEV_DEPS = PATH_DEV / '.cached-dev-dependencies'
|
PATH_ADDON_DEV_DEPS = PATH_DEV / '.cached-dev-dependencies'
|
||||||
PATH_ADDON_DEV_DEPS.mkdir(exist_ok=True)
|
PATH_ADDON_DEV_DEPS.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,10 @@ def zipped_addon(
|
||||||
tempfile.NamedTemporaryFile(mode='w') as f_tmp,
|
tempfile.NamedTemporaryFile(mode='w') as f_tmp,
|
||||||
):
|
):
|
||||||
initpy = f_init.read()
|
initpy = f_init.read()
|
||||||
for to_replace, replacement in BL_INFO_REPLACEMENTS.items():
|
for (
|
||||||
|
to_replace,
|
||||||
|
replacement,
|
||||||
|
) in BL_INFO_REPLACEMENTS.items():
|
||||||
initpy = initpy.replace(to_replace, replacement)
|
initpy = initpy.replace(to_replace, replacement)
|
||||||
f_tmp.write(initpy)
|
f_tmp.write(initpy)
|
||||||
|
|
||||||
|
@ -67,10 +70,7 @@ def zipped_addon(
|
||||||
f_zip.write(
|
f_zip.write(
|
||||||
path_pyproject_toml,
|
path_pyproject_toml,
|
||||||
str(
|
str(
|
||||||
(
|
(Path(path_addon_pkg.name) / Path(path_pyproject_toml.name))
|
||||||
Path(path_addon_pkg.name)
|
|
||||||
/ Path(path_pyproject_toml.name)
|
|
||||||
)
|
|
||||||
.with_suffix('')
|
.with_suffix('')
|
||||||
.with_suffix('.toml')
|
.with_suffix('.toml')
|
||||||
),
|
),
|
||||||
|
|
|
@ -11,7 +11,7 @@ import info
|
||||||
def run_blender(py_script: Path, print_live: bool = False):
|
def run_blender(py_script: Path, print_live: bool = False):
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
['blender', '--python', str(py_script)],
|
['blender', '--python', str(py_script)],
|
||||||
env = os.environ | {'PYTHONUNBUFFERED': '1'},
|
env=os.environ | {'PYTHONUNBUFFERED': '1'},
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
text=True,
|
text=True,
|
||||||
|
@ -28,7 +28,7 @@ def run_blender(py_script: Path, print_live: bool = False):
|
||||||
print(line, end='') # noqa: T201
|
print(line, end='') # noqa: T201
|
||||||
elif (
|
elif (
|
||||||
info.SIGNAL_START_CLEAN_BLENDER in line
|
info.SIGNAL_START_CLEAN_BLENDER in line
|
||||||
#or 'Traceback (most recent call last)' in line
|
# or 'Traceback (most recent call last)' in line
|
||||||
):
|
):
|
||||||
printing_live = True
|
printing_live = True
|
||||||
print(''.join(output)) # noqa: T201
|
print(''.join(output)) # noqa: T201
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
|
|
||||||
sp.printing.str.StrPrinter._default_settings['abbrev'] = True
|
sp.printing.str.StrPrinter._default_settings['abbrev'] = True
|
||||||
## In this tree, all Sympy unit printing must be abbreviated.
|
## In this tree, all Sympy unit printing must be abbreviated.
|
||||||
## By configuring this in __init__.py, we guarantee it for all subimports.
|
## By configuring this in __init__.py, we guarantee it for all subimports.
|
||||||
|
|
|
@ -26,36 +26,35 @@ Unit = typ.Any ## Type of a valid unit
|
||||||
SOCKET_DEFS = {
|
SOCKET_DEFS = {
|
||||||
socket_type: getattr(
|
socket_type: getattr(
|
||||||
sck,
|
sck,
|
||||||
socket_type.value.removesuffix("SocketType") + "SocketDef",
|
socket_type.value.removesuffix('SocketType') + 'SocketDef',
|
||||||
)
|
)
|
||||||
for socket_type in ST
|
for socket_type in ST
|
||||||
if hasattr(
|
if hasattr(sck, socket_type.value.removesuffix('SocketType') + 'SocketDef')
|
||||||
sck,
|
|
||||||
socket_type.value.removesuffix("SocketType") + "SocketDef"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
## TODO: Bit of a hack. Is it robust enough?
|
## TODO: Bit of a hack. Is it robust enough?
|
||||||
|
|
||||||
for socket_type in ST:
|
for socket_type in ST:
|
||||||
if not hasattr(
|
if not hasattr(
|
||||||
sck,
|
sck,
|
||||||
socket_type.value.removesuffix("SocketType") + "SocketDef",
|
socket_type.value.removesuffix('SocketType') + 'SocketDef',
|
||||||
):
|
):
|
||||||
print("Missing SocketDef for", socket_type.value)
|
print('Missing SocketDef for', socket_type.value)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - BL Socket Size Parser
|
# - BL Socket Size Parser
|
||||||
####################
|
####################
|
||||||
BL_SOCKET_3D_TYPE_PREFIXES = {
|
BL_SOCKET_3D_TYPE_PREFIXES = {
|
||||||
"NodeSocketVector",
|
'NodeSocketVector',
|
||||||
"NodeSocketRotation",
|
'NodeSocketRotation',
|
||||||
}
|
}
|
||||||
BL_SOCKET_4D_TYPE_PREFIXES = {
|
BL_SOCKET_4D_TYPE_PREFIXES = {
|
||||||
"NodeSocketColor",
|
'NodeSocketColor',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def size_from_bl_interface_socket(
|
def size_from_bl_interface_socket(
|
||||||
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket
|
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
||||||
) -> typx.Literal[1, 2, 3, 4]:
|
) -> typx.Literal[1, 2, 3, 4]:
|
||||||
"""Parses the `size`, aka. number of elements, contained within the `default_value` of a Blender interface socket.
|
"""Parses the `size`, aka. number of elements, contained within the `default_value` of a Blender interface socket.
|
||||||
|
|
||||||
|
@ -66,7 +65,8 @@ def size_from_bl_interface_socket(
|
||||||
- For 3D sockets, a hard-coded list of Blender node socket types is used.
|
- For 3D sockets, a hard-coded list of Blender node socket types is used.
|
||||||
- Else, it is a 1D socket type.
|
- Else, it is a 1D socket type.
|
||||||
"""
|
"""
|
||||||
if bl_interface_socket.description.startswith("2D"): return 2
|
if bl_interface_socket.description.startswith('2D'):
|
||||||
|
return 2
|
||||||
if any(
|
if any(
|
||||||
bl_interface_socket.socket_type.startswith(bl_socket_3d_type_prefix)
|
bl_interface_socket.socket_type.startswith(bl_socket_3d_type_prefix)
|
||||||
for bl_socket_3d_type_prefix in BL_SOCKET_3D_TYPE_PREFIXES
|
for bl_socket_3d_type_prefix in BL_SOCKET_3D_TYPE_PREFIXES
|
||||||
|
@ -114,7 +114,7 @@ def parse_bl_interface_socket(
|
||||||
# Parse Description for Socket Type
|
# Parse Description for Socket Type
|
||||||
tokens = (
|
tokens = (
|
||||||
_tokens
|
_tokens
|
||||||
if (_tokens := bl_interface_socket.description.split(" "))[0] != "2D"
|
if (_tokens := bl_interface_socket.description.split(' '))[0] != '2D'
|
||||||
else _tokens[1:]
|
else _tokens[1:]
|
||||||
) ## Don't include the "2D" token, if defined.
|
) ## Don't include the "2D" token, if defined.
|
||||||
if (
|
if (
|
||||||
|
@ -122,25 +122,36 @@ def parse_bl_interface_socket(
|
||||||
(tokens[0], bl_interface_socket.socket_type, size)
|
(tokens[0], bl_interface_socket.socket_type, size)
|
||||||
)
|
)
|
||||||
) is None:
|
) is None:
|
||||||
return (direct_socket_type, None) ## Description doesn't map to anything
|
return (
|
||||||
|
direct_socket_type,
|
||||||
|
None,
|
||||||
|
) ## Description doesn't map to anything
|
||||||
|
|
||||||
# Determine Socket Unit (to use instead of "unit system")
|
# Determine Socket Unit (to use instead of "unit system")
|
||||||
## This is entirely OPTIONAL
|
## This is entirely OPTIONAL
|
||||||
socket_unit = None
|
socket_unit = None
|
||||||
if socket_type in ct.SOCKET_UNITS:
|
if socket_type in ct.SOCKET_UNITS:
|
||||||
## Case: Unit is User-Defined
|
## Case: Unit is User-Defined
|
||||||
if len(tokens) > 1 and "(" in tokens[1] and ")" in tokens[1]:
|
if len(tokens) > 1 and '(' in tokens[1] and ')' in tokens[1]:
|
||||||
# Compute (<unit_str>) as Unit Token
|
# Compute (<unit_str>) as Unit Token
|
||||||
unit_token = tokens[1].removeprefix("(").removesuffix(")")
|
unit_token = tokens[1].removeprefix('(').removesuffix(')')
|
||||||
|
|
||||||
# Compare Unit Token to Valid Sympy-Printed Units
|
# Compare Unit Token to Valid Sympy-Printed Units
|
||||||
socket_unit = _socket_unit if (_socket_unit := [
|
socket_unit = (
|
||||||
|
_socket_unit
|
||||||
|
if (
|
||||||
|
_socket_unit := [
|
||||||
unit
|
unit
|
||||||
for unit in ct.SOCKET_UNITS[socket_type]["values"].values()
|
for unit in ct.SOCKET_UNITS[socket_type][
|
||||||
|
'values'
|
||||||
|
].values()
|
||||||
if str(unit) == unit_token
|
if str(unit) == unit_token
|
||||||
]) else ct.SOCKET_UNITS[socket_type]["values"][
|
|
||||||
ct.SOCKET_UNITS[socket_type]["default"]
|
|
||||||
]
|
]
|
||||||
|
)
|
||||||
|
else ct.SOCKET_UNITS[socket_type]['values'][
|
||||||
|
ct.SOCKET_UNITS[socket_type]['default']
|
||||||
|
]
|
||||||
|
)
|
||||||
## TODO: Enforce abbreviated sympy printing here, not globally
|
## TODO: Enforce abbreviated sympy printing here, not globally
|
||||||
|
|
||||||
return (socket_type, socket_unit)
|
return (socket_type, socket_unit)
|
||||||
|
@ -152,11 +163,8 @@ def parse_bl_interface_socket(
|
||||||
def socket_def_from_bl_interface_socket(
|
def socket_def_from_bl_interface_socket(
|
||||||
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
||||||
):
|
):
|
||||||
"""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_DEFS[parse_bl_interface_socket(bl_interface_socket)[0]]
|
||||||
return SOCKET_DEFS[
|
|
||||||
parse_bl_interface_socket(bl_interface_socket)[0]
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -190,6 +198,7 @@ def value_from_bl(
|
||||||
|
|
||||||
return parsed_bl_socket_value
|
return parsed_bl_socket_value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Convert to Blender-Compatible Value
|
# - Convert to Blender-Compatible Value
|
||||||
####################
|
####################
|
||||||
|
@ -211,6 +220,7 @@ def make_scalar_bl_compat(scalar: typ.Any) -> typ.Any:
|
||||||
|
|
||||||
return scalar
|
return scalar
|
||||||
|
|
||||||
|
|
||||||
def value_to_bl(
|
def value_to_bl(
|
||||||
bl_interface_socket: bpy.types.NodeSocket,
|
bl_interface_socket: bpy.types.NodeSocket,
|
||||||
value: typ.Any,
|
value: typ.Any,
|
||||||
|
@ -221,31 +231,29 @@ def value_to_bl(
|
||||||
# Set Socket
|
# Set Socket
|
||||||
if unit is not None:
|
if unit is not None:
|
||||||
bl_socket_value = spu.convert_to(value, unit) / unit
|
bl_socket_value = spu.convert_to(value, unit) / unit
|
||||||
elif (
|
elif unit_system is not None and socket_type in unit_system:
|
||||||
unit_system is not None
|
bl_socket_value = (
|
||||||
and socket_type in unit_system
|
spu.convert_to(value, unit_system[socket_type])
|
||||||
):
|
/ unit_system[socket_type]
|
||||||
bl_socket_value = spu.convert_to(
|
)
|
||||||
value, unit_system[socket_type]
|
|
||||||
) / unit_system[socket_type]
|
|
||||||
else:
|
else:
|
||||||
bl_socket_value = value
|
bl_socket_value = value
|
||||||
|
|
||||||
return {
|
return {
|
||||||
1: lambda: make_scalar_bl_compat(bl_socket_value),
|
1: lambda: make_scalar_bl_compat(bl_socket_value),
|
||||||
2: lambda: tuple([
|
2: lambda: tuple(
|
||||||
|
[
|
||||||
make_scalar_bl_compat(bl_socket_value[0]),
|
make_scalar_bl_compat(bl_socket_value[0]),
|
||||||
make_scalar_bl_compat(bl_socket_value[1]),
|
make_scalar_bl_compat(bl_socket_value[1]),
|
||||||
bl_interface_socket.default_value[2]
|
bl_interface_socket.default_value[2],
|
||||||
## Don't touch (unused) 3rd bl_socket coordinate
|
## Don't touch (unused) 3rd bl_socket coordinate
|
||||||
]),
|
]
|
||||||
3: lambda: tuple([
|
),
|
||||||
make_scalar_bl_compat(el)
|
3: lambda: tuple(
|
||||||
for el in bl_socket_value
|
[make_scalar_bl_compat(el) for el in bl_socket_value]
|
||||||
]),
|
),
|
||||||
4: lambda: tuple([
|
4: lambda: tuple(
|
||||||
make_scalar_bl_compat(el)
|
[make_scalar_bl_compat(el) for el in bl_socket_value]
|
||||||
for el in bl_socket_value
|
),
|
||||||
]),
|
|
||||||
}[size_from_bl_interface_socket(bl_interface_socket)]()
|
}[size_from_bl_interface_socket(bl_interface_socket)]()
|
||||||
## The 'lambda' delays construction until size is determined
|
## The 'lambda' delays construction until size is determined
|
||||||
|
|
|
@ -6,16 +6,18 @@ from . import contracts as ct
|
||||||
from .nodes import BL_NODES
|
from .nodes import BL_NODES
|
||||||
|
|
||||||
DYNAMIC_SUBMENU_REGISTRATIONS = []
|
DYNAMIC_SUBMENU_REGISTRATIONS = []
|
||||||
|
|
||||||
|
|
||||||
def mk_node_categories(
|
def mk_node_categories(
|
||||||
tree,
|
tree,
|
||||||
syllable_prefix = [],
|
syllable_prefix=[],
|
||||||
#root = True,
|
# root = True,
|
||||||
):
|
):
|
||||||
global DYNAMIC_SUBMENU_REGISTRATIONS
|
global DYNAMIC_SUBMENU_REGISTRATIONS
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
# Add Node Items
|
# Add Node Items
|
||||||
base_category = ct.NodeCategory["_".join(syllable_prefix)]
|
base_category = ct.NodeCategory['_'.join(syllable_prefix)]
|
||||||
for node_type, node_category in BL_NODES.items():
|
for node_type, node_category in BL_NODES.items():
|
||||||
if node_category == base_category:
|
if node_category == base_category:
|
||||||
items.append(nodeitems_utils.NodeItem(node_type.value))
|
items.append(nodeitems_utils.NodeItem(node_type.value))
|
||||||
|
@ -23,16 +25,15 @@ def mk_node_categories(
|
||||||
# Add Node Sub-Menus
|
# Add Node Sub-Menus
|
||||||
for syllable, sub_tree in tree.items():
|
for syllable, sub_tree in tree.items():
|
||||||
current_syllable_path = syllable_prefix + [syllable]
|
current_syllable_path = syllable_prefix + [syllable]
|
||||||
current_category = ct.NodeCategory[
|
current_category = ct.NodeCategory['_'.join(current_syllable_path)]
|
||||||
"_".join(current_syllable_path)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Build Items for Sub-Categories
|
# Build Items for Sub-Categories
|
||||||
subitems = mk_node_categories(
|
subitems = mk_node_categories(
|
||||||
sub_tree,
|
sub_tree,
|
||||||
current_syllable_path,
|
current_syllable_path,
|
||||||
)
|
)
|
||||||
if len(subitems) == 0: continue
|
if len(subitems) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
# Define Dynamic Node Submenu
|
# Define Dynamic Node Submenu
|
||||||
def draw_factory(items):
|
def draw_factory(items):
|
||||||
|
@ -44,7 +45,7 @@ def mk_node_categories(
|
||||||
):
|
):
|
||||||
nodeitem = nodeitem_or_submenu
|
nodeitem = nodeitem_or_submenu
|
||||||
op_add_node_cfg = self.layout.operator(
|
op_add_node_cfg = self.layout.operator(
|
||||||
"node.add_node",
|
'node.add_node',
|
||||||
text=nodeitem.label,
|
text=nodeitem.label,
|
||||||
)
|
)
|
||||||
op_add_node_cfg.type = nodeitem.nodetype
|
op_add_node_cfg.type = nodeitem.nodetype
|
||||||
|
@ -52,13 +53,18 @@ def mk_node_categories(
|
||||||
elif isinstance(nodeitem_or_submenu, str):
|
elif isinstance(nodeitem_or_submenu, str):
|
||||||
submenu_id = nodeitem_or_submenu
|
submenu_id = nodeitem_or_submenu
|
||||||
self.layout.menu(submenu_id)
|
self.layout.menu(submenu_id)
|
||||||
|
|
||||||
return draw
|
return draw
|
||||||
|
|
||||||
menu_class = type(str(current_category.value), (bpy.types.Menu,), {
|
menu_class = type(
|
||||||
|
str(current_category.value),
|
||||||
|
(bpy.types.Menu,),
|
||||||
|
{
|
||||||
'bl_idname': current_category.value,
|
'bl_idname': current_category.value,
|
||||||
'bl_label': ct.NODE_CAT_LABELS[current_category],
|
'bl_label': ct.NODE_CAT_LABELS[current_category],
|
||||||
'draw': draw_factory(tuple(subitems)),
|
'draw': draw_factory(tuple(subitems)),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
# Report to Items and Registration List
|
# Report to Items and Registration List
|
||||||
items.append(current_category.value)
|
items.append(current_category.value)
|
||||||
|
@ -67,19 +73,19 @@ def mk_node_categories(
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_NODE_CATEGORIES = mk_node_categories(
|
BL_NODE_CATEGORIES = mk_node_categories(
|
||||||
ct.NodeCategory.get_tree()["MAXWELLSIM"],
|
ct.NodeCategory.get_tree()['MAXWELLSIM'],
|
||||||
syllable_prefix = ["MAXWELLSIM"],
|
syllable_prefix=['MAXWELLSIM'],
|
||||||
)
|
)
|
||||||
## TODO: refactor, this has a big code smell
|
## TODO: refactor, this has a big code smell
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*DYNAMIC_SUBMENU_REGISTRATIONS
|
*DYNAMIC_SUBMENU_REGISTRATIONS
|
||||||
] ## Must be run after, right now.
|
] ## Must be run after, right now.
|
||||||
|
|
||||||
|
|
||||||
## TEST - TODO this is a big code smell
|
## TEST - TODO this is a big code smell
|
||||||
def menu_draw(self, context):
|
def menu_draw(self, context):
|
||||||
if context.space_data.tree_type == ct.TreeType.MaxwellSim.value:
|
if context.space_data.tree_type == ct.TreeType.MaxwellSim.value:
|
||||||
|
@ -88,4 +94,5 @@ def menu_draw(self, context):
|
||||||
submenu_id = nodeitem_or_submenu
|
submenu_id = nodeitem_or_submenu
|
||||||
self.layout.menu(submenu_id)
|
self.layout.menu(submenu_id)
|
||||||
|
|
||||||
|
|
||||||
bpy.types.NODE_MT_add.append(menu_draw)
|
bpy.types.NODE_MT_add.append(menu_draw)
|
||||||
|
|
|
@ -7,20 +7,32 @@ import bpy
|
||||||
####################
|
####################
|
||||||
# - Pure BL Types
|
# - Pure BL Types
|
||||||
####################
|
####################
|
||||||
BLEnumID = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
BLEnumID = pytypes_ext.Annotated[
|
||||||
|
str,
|
||||||
|
pyd.StringConstraints(
|
||||||
pattern=r'^[A-Z_]+$',
|
pattern=r'^[A-Z_]+$',
|
||||||
)]
|
),
|
||||||
SocketName = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
]
|
||||||
|
SocketName = pytypes_ext.Annotated[
|
||||||
|
str,
|
||||||
|
pyd.StringConstraints(
|
||||||
pattern=r'^[a-zA-Z0-9_]+$',
|
pattern=r'^[a-zA-Z0-9_]+$',
|
||||||
)]
|
),
|
||||||
PresetName = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
]
|
||||||
|
PresetName = pytypes_ext.Annotated[
|
||||||
|
str,
|
||||||
|
pyd.StringConstraints(
|
||||||
pattern=r'^[a-zA-Z0-9_]+$',
|
pattern=r'^[a-zA-Z0-9_]+$',
|
||||||
)]
|
),
|
||||||
|
]
|
||||||
BLColorRGBA = tuple[float, float, float, float]
|
BLColorRGBA = tuple[float, float, float, float]
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Shared-With-BL Types
|
# - Shared-With-BL Types
|
||||||
####################
|
####################
|
||||||
ManagedObjName = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
ManagedObjName = pytypes_ext.Annotated[
|
||||||
|
str,
|
||||||
|
pyd.StringConstraints(
|
||||||
pattern=r'^[a-z_]+$',
|
pattern=r'^[a-z_]+$',
|
||||||
)]
|
),
|
||||||
|
]
|
||||||
|
|
|
@ -2,6 +2,7 @@ import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import BlenderTypeEnum
|
from ....utils.blender_type_enum import BlenderTypeEnum
|
||||||
|
|
||||||
|
|
||||||
class DataFlowKind(BlenderTypeEnum):
|
class DataFlowKind(BlenderTypeEnum):
|
||||||
"""Defines a shape/kind of data that may flow through a node tree.
|
"""Defines a shape/kind of data that may flow through a node tree.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from ....utils.blender_type_enum import BlenderTypeEnum
|
from ....utils.blender_type_enum import BlenderTypeEnum
|
||||||
|
|
||||||
|
|
||||||
class Icon(BlenderTypeEnum):
|
class Icon(BlenderTypeEnum):
|
||||||
SimNodeEditor = "MOD_SIMPLEDEFORM"
|
SimNodeEditor = 'MOD_SIMPLEDEFORM'
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import (
|
from ....utils.blender_type_enum import BlenderTypeEnum
|
||||||
BlenderTypeEnum
|
|
||||||
)
|
|
||||||
|
|
||||||
class ManagedObjType(BlenderTypeEnum):
|
class ManagedObjType(BlenderTypeEnum):
|
||||||
ManagedBLObject = enum.auto()
|
ManagedBLObject = enum.auto()
|
||||||
|
|
|
@ -2,48 +2,39 @@ from .node_cats import NodeCategory as NC
|
||||||
|
|
||||||
NODE_CAT_LABELS = {
|
NODE_CAT_LABELS = {
|
||||||
# Inputs/
|
# Inputs/
|
||||||
NC.MAXWELLSIM_INPUTS: "Inputs",
|
NC.MAXWELLSIM_INPUTS: 'Inputs',
|
||||||
NC.MAXWELLSIM_INPUTS_IMPORTERS: "Importers",
|
NC.MAXWELLSIM_INPUTS_IMPORTERS: 'Importers',
|
||||||
NC.MAXWELLSIM_INPUTS_SCENE: "Scene",
|
NC.MAXWELLSIM_INPUTS_SCENE: 'Scene',
|
||||||
NC.MAXWELLSIM_INPUTS_PARAMETERS: "Parameters",
|
NC.MAXWELLSIM_INPUTS_PARAMETERS: 'Parameters',
|
||||||
NC.MAXWELLSIM_INPUTS_CONSTANTS: "Constants",
|
NC.MAXWELLSIM_INPUTS_CONSTANTS: 'Constants',
|
||||||
NC.MAXWELLSIM_INPUTS_LISTS: "Lists",
|
NC.MAXWELLSIM_INPUTS_LISTS: 'Lists',
|
||||||
|
|
||||||
# Outputs/
|
# Outputs/
|
||||||
NC.MAXWELLSIM_OUTPUTS: "Outputs",
|
NC.MAXWELLSIM_OUTPUTS: 'Outputs',
|
||||||
NC.MAXWELLSIM_OUTPUTS_VIEWERS: "Viewers",
|
NC.MAXWELLSIM_OUTPUTS_VIEWERS: 'Viewers',
|
||||||
NC.MAXWELLSIM_OUTPUTS_EXPORTERS: "Exporters",
|
NC.MAXWELLSIM_OUTPUTS_EXPORTERS: 'Exporters',
|
||||||
NC.MAXWELLSIM_OUTPUTS_PLOTTERS: "Plotters",
|
NC.MAXWELLSIM_OUTPUTS_PLOTTERS: 'Plotters',
|
||||||
|
|
||||||
# Sources/
|
# Sources/
|
||||||
NC.MAXWELLSIM_SOURCES: "Sources",
|
NC.MAXWELLSIM_SOURCES: 'Sources',
|
||||||
NC.MAXWELLSIM_SOURCES_TEMPORALSHAPES: "Temporal Shapes",
|
NC.MAXWELLSIM_SOURCES_TEMPORALSHAPES: 'Temporal Shapes',
|
||||||
|
|
||||||
# Mediums/
|
# Mediums/
|
||||||
NC.MAXWELLSIM_MEDIUMS: "Mediums",
|
NC.MAXWELLSIM_MEDIUMS: 'Mediums',
|
||||||
NC.MAXWELLSIM_MEDIUMS_NONLINEARITIES: "Non-Linearities",
|
NC.MAXWELLSIM_MEDIUMS_NONLINEARITIES: 'Non-Linearities',
|
||||||
|
|
||||||
# Structures/
|
# Structures/
|
||||||
NC.MAXWELLSIM_STRUCTURES: "Structures",
|
NC.MAXWELLSIM_STRUCTURES: 'Structures',
|
||||||
NC.MAXWELLSIM_STRUCTURES_PRIMITIVES: "Primitives",
|
NC.MAXWELLSIM_STRUCTURES_PRIMITIVES: 'Primitives',
|
||||||
|
|
||||||
# Bounds/
|
# Bounds/
|
||||||
NC.MAXWELLSIM_BOUNDS: "Bounds",
|
NC.MAXWELLSIM_BOUNDS: 'Bounds',
|
||||||
NC.MAXWELLSIM_BOUNDS_BOUNDCONDS: "Bound Conds",
|
NC.MAXWELLSIM_BOUNDS_BOUNDCONDS: 'Bound Conds',
|
||||||
|
|
||||||
# Monitors/
|
# Monitors/
|
||||||
NC.MAXWELLSIM_MONITORS: "Monitors",
|
NC.MAXWELLSIM_MONITORS: 'Monitors',
|
||||||
NC.MAXWELLSIM_MONITORS_NEARFIELDPROJECTIONS: "Near-Field Projections",
|
NC.MAXWELLSIM_MONITORS_NEARFIELDPROJECTIONS: 'Near-Field Projections',
|
||||||
|
|
||||||
# Simulations/
|
# Simulations/
|
||||||
NC.MAXWELLSIM_SIMS: "Simulations",
|
NC.MAXWELLSIM_SIMS: 'Simulations',
|
||||||
NC.MAXWELLSIM_SIMGRIDAXES: "Sim Grid Axes",
|
NC.MAXWELLSIM_SIMGRIDAXES: 'Sim Grid Axes',
|
||||||
|
|
||||||
# Utilities/
|
# Utilities/
|
||||||
NC.MAXWELLSIM_UTILITIES: "Utilities",
|
NC.MAXWELLSIM_UTILITIES: 'Utilities',
|
||||||
NC.MAXWELLSIM_UTILITIES_CONVERTERS: "Converters",
|
NC.MAXWELLSIM_UTILITIES_CONVERTERS: 'Converters',
|
||||||
NC.MAXWELLSIM_UTILITIES_OPERATIONS: "Operations",
|
NC.MAXWELLSIM_UTILITIES_OPERATIONS: 'Operations',
|
||||||
|
|
||||||
# Viz/
|
# Viz/
|
||||||
NC.MAXWELLSIM_VIZ: "Viz",
|
NC.MAXWELLSIM_VIZ: 'Viz',
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import (
|
from ....utils.blender_type_enum import BlenderTypeEnum, wrap_values_in_MT
|
||||||
BlenderTypeEnum, wrap_values_in_MT
|
|
||||||
)
|
|
||||||
|
|
||||||
@wrap_values_in_MT
|
@wrap_values_in_MT
|
||||||
class NodeCategory(BlenderTypeEnum):
|
class NodeCategory(BlenderTypeEnum):
|
||||||
|
@ -58,9 +57,9 @@ class NodeCategory(BlenderTypeEnum):
|
||||||
def get_tree(cls):
|
def get_tree(cls):
|
||||||
## TODO: Refactor
|
## TODO: Refactor
|
||||||
syllable_categories = [
|
syllable_categories = [
|
||||||
str(node_category.value).split("_")
|
str(node_category.value).split('_')
|
||||||
for node_category in cls
|
for node_category in cls
|
||||||
if node_category.value != "MAXWELLSIM"
|
if node_category.value != 'MAXWELLSIM'
|
||||||
]
|
]
|
||||||
|
|
||||||
category_tree = {}
|
category_tree = {}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import (
|
from ....utils.blender_type_enum import (
|
||||||
BlenderTypeEnum, append_cls_name_to_values
|
BlenderTypeEnum,
|
||||||
|
append_cls_name_to_values,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@append_cls_name_to_values
|
@append_cls_name_to_values
|
||||||
class NodeType(BlenderTypeEnum):
|
class NodeType(BlenderTypeEnum):
|
||||||
KitchenSink = enum.auto()
|
KitchenSink = enum.auto()
|
||||||
|
@ -35,7 +37,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
## Inputs /
|
## Inputs /
|
||||||
InputFile = enum.auto()
|
InputFile = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Outputs
|
# Outputs
|
||||||
## Outputs / Viewers
|
## Outputs / Viewers
|
||||||
Viewer = enum.auto()
|
Viewer = enum.auto()
|
||||||
|
@ -46,7 +47,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
JSONFileExporter = enum.auto()
|
JSONFileExporter = enum.auto()
|
||||||
Tidy3DWebExporter = enum.auto()
|
Tidy3DWebExporter = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
## Sources / Temporal Shapes
|
## Sources / Temporal Shapes
|
||||||
GaussianPulseTemporalShape = enum.auto()
|
GaussianPulseTemporalShape = enum.auto()
|
||||||
|
@ -95,7 +95,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
SphereStructure = enum.auto()
|
SphereStructure = enum.auto()
|
||||||
CylinderStructure = enum.auto()
|
CylinderStructure = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Bounds
|
# Bounds
|
||||||
BoundConds = enum.auto()
|
BoundConds = enum.auto()
|
||||||
|
|
||||||
|
@ -108,7 +107,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
PeriodicBoundCond = enum.auto()
|
PeriodicBoundCond = enum.auto()
|
||||||
AbsorbingBoundCond = enum.auto()
|
AbsorbingBoundCond = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Monitors
|
# Monitors
|
||||||
EHFieldMonitor = enum.auto()
|
EHFieldMonitor = enum.auto()
|
||||||
FieldPowerFluxMonitor = enum.auto()
|
FieldPowerFluxMonitor = enum.auto()
|
||||||
|
@ -120,7 +118,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
ObservationAngleNearFieldProjectionMonitor = enum.auto()
|
ObservationAngleNearFieldProjectionMonitor = enum.auto()
|
||||||
KSpaceNearFieldProjectionMonitor = enum.auto()
|
KSpaceNearFieldProjectionMonitor = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Sims
|
# Sims
|
||||||
SimDomain = enum.auto()
|
SimDomain = enum.auto()
|
||||||
SimGrid = enum.auto()
|
SimGrid = enum.auto()
|
||||||
|
@ -134,7 +131,6 @@ class NodeType(BlenderTypeEnum):
|
||||||
## Sim /
|
## Sim /
|
||||||
FDTDSim = enum.auto()
|
FDTDSim = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
Combine = enum.auto()
|
Combine = enum.auto()
|
||||||
Separate = enum.auto()
|
Separate = enum.auto()
|
||||||
|
@ -146,7 +142,5 @@ class NodeType(BlenderTypeEnum):
|
||||||
## Utilities / Operations
|
## Utilities / Operations
|
||||||
ArrayOperation = enum.auto()
|
ArrayOperation = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Viz
|
# Viz
|
||||||
FDTDSimDataViz = enum.auto()
|
FDTDSimDataViz = enum.auto()
|
||||||
|
|
|
@ -10,16 +10,14 @@ class ManagedObj(typ.Protocol):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: ManagedObjName,
|
name: ManagedObjName,
|
||||||
):
|
): ...
|
||||||
...
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str: ...
|
def name(self) -> str: ...
|
||||||
@name.setter
|
@name.setter
|
||||||
def name(self, value: str): ...
|
def name(self, value: str): ...
|
||||||
|
|
||||||
def free(self):
|
def free(self): ...
|
||||||
...
|
|
||||||
|
|
||||||
def bl_select(self):
|
def bl_select(self):
|
||||||
"""If this is a managed Blender object, and the operation "select this in Blender" makes sense, then do so.
|
"""If this is a managed Blender object, and the operation "select this in Blender" makes sense, then do so.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import pydantic as pyd
|
||||||
from ..bl import PresetName, SocketName, BLEnumID
|
from ..bl import PresetName, SocketName, BLEnumID
|
||||||
from .managed_obj import ManagedObj
|
from .managed_obj import ManagedObj
|
||||||
|
|
||||||
|
|
||||||
class ManagedObjDef(pyd.BaseModel):
|
class ManagedObjDef(pyd.BaseModel):
|
||||||
mk: typ.Callable[[str], ManagedObj]
|
mk: typ.Callable[[str], ManagedObj]
|
||||||
name_prefix: str = ""
|
name_prefix: str = ''
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pydantic as pyd
|
||||||
|
|
||||||
from ..bl import PresetName, SocketName, BLEnumID
|
from ..bl import PresetName, SocketName, BLEnumID
|
||||||
|
|
||||||
|
|
||||||
class PresetDef(pyd.BaseModel):
|
class PresetDef(pyd.BaseModel):
|
||||||
label: PresetName
|
label: PresetName
|
||||||
description: str
|
description: str
|
||||||
|
|
|
@ -10,13 +10,11 @@ SOCKET_COLORS = {
|
||||||
ST.Bool: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey
|
ST.Bool: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey
|
||||||
ST.String: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey
|
ST.String: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey
|
||||||
ST.FilePath: (0.6, 0.6, 0.6, 1.0), # Medium Grey
|
ST.FilePath: (0.6, 0.6, 0.6, 1.0), # Medium Grey
|
||||||
|
|
||||||
# Number
|
# Number
|
||||||
ST.IntegerNumber: (0.5, 0.5, 1.0, 1.0), # Light Blue
|
ST.IntegerNumber: (0.5, 0.5, 1.0, 1.0), # Light Blue
|
||||||
ST.RationalNumber: (0.4, 0.4, 0.9, 1.0), # Medium Light Blue
|
ST.RationalNumber: (0.4, 0.4, 0.9, 1.0), # Medium Light Blue
|
||||||
ST.RealNumber: (0.3, 0.3, 0.8, 1.0), # Medium Blue
|
ST.RealNumber: (0.3, 0.3, 0.8, 1.0), # Medium Blue
|
||||||
ST.ComplexNumber: (0.2, 0.2, 0.7, 1.0), # Dark Blue
|
ST.ComplexNumber: (0.2, 0.2, 0.7, 1.0), # Dark Blue
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
ST.Integer2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
ST.Integer2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
||||||
ST.Real2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
ST.Real2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
||||||
|
@ -24,7 +22,6 @@ SOCKET_COLORS = {
|
||||||
ST.Integer3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
ST.Integer3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
||||||
ST.Real3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
ST.Real3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
||||||
ST.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
ST.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
||||||
|
|
||||||
# Physical
|
# Physical
|
||||||
ST.PhysicalUnitSystem: (1.0, 0.5, 0.5, 1.0), # Light Red
|
ST.PhysicalUnitSystem: (1.0, 0.5, 0.5, 1.0), # Light Red
|
||||||
ST.PhysicalTime: (1.0, 0.5, 0.5, 1.0), # Light Red
|
ST.PhysicalTime: (1.0, 0.5, 0.5, 1.0), # Light Red
|
||||||
|
@ -44,14 +41,12 @@ SOCKET_COLORS = {
|
||||||
ST.PhysicalForce3D: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange
|
ST.PhysicalForce3D: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange
|
||||||
ST.PhysicalPol: (0.5, 0.4, 0.2, 1.0), # Dark Orange
|
ST.PhysicalPol: (0.5, 0.4, 0.2, 1.0), # Dark Orange
|
||||||
ST.PhysicalFreq: (1.0, 0.7, 0.5, 1.0), # Light Peach
|
ST.PhysicalFreq: (1.0, 0.7, 0.5, 1.0), # Light Peach
|
||||||
|
|
||||||
# Blender
|
# Blender
|
||||||
ST.BlenderObject: (0.7, 0.5, 1.0, 1.0), # Light Purple
|
ST.BlenderObject: (0.7, 0.5, 1.0, 1.0), # Light Purple
|
||||||
ST.BlenderCollection: (0.6, 0.45, 0.9, 1.0), # Medium Light Purple
|
ST.BlenderCollection: (0.6, 0.45, 0.9, 1.0), # Medium Light Purple
|
||||||
ST.BlenderImage: (0.5, 0.4, 0.8, 1.0), # Medium Purple
|
ST.BlenderImage: (0.5, 0.4, 0.8, 1.0), # Medium Purple
|
||||||
ST.BlenderGeoNodes: (0.3, 0.3, 0.6, 1.0), # Dark Purple
|
ST.BlenderGeoNodes: (0.3, 0.3, 0.6, 1.0), # Dark Purple
|
||||||
ST.BlenderText: (0.5, 0.5, 0.75, 1.0), # Light Lavender
|
ST.BlenderText: (0.5, 0.5, 0.75, 1.0), # Light Lavender
|
||||||
|
|
||||||
# Maxwell
|
# Maxwell
|
||||||
ST.MaxwellSource: (1.0, 1.0, 0.5, 1.0), # Light Yellow
|
ST.MaxwellSource: (1.0, 1.0, 0.5, 1.0), # Light Yellow
|
||||||
ST.MaxwellTemporalShape: (0.9, 0.9, 0.45, 1.0), # Medium Light Yellow
|
ST.MaxwellTemporalShape: (0.9, 0.9, 0.45, 1.0), # Medium Light Yellow
|
||||||
|
@ -66,8 +61,6 @@ SOCKET_COLORS = {
|
||||||
ST.MaxwellSimGrid: (0.5, 0.4, 0.3, 1.0), # Dark Gold
|
ST.MaxwellSimGrid: (0.5, 0.4, 0.3, 1.0), # Dark Gold
|
||||||
ST.MaxwellSimGridAxis: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
ST.MaxwellSimGridAxis: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
||||||
ST.MaxwellSimDomain: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
ST.MaxwellSimDomain: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
||||||
|
|
||||||
# Tidy3D
|
# Tidy3D
|
||||||
ST.Tidy3DCloudTask: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
ST.Tidy3DCloudTask: (0.4, 0.3, 0.25, 1.0), # Darkest Gold
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,78 +1,62 @@
|
||||||
from .socket_types import SocketType as ST
|
from .socket_types import SocketType as ST
|
||||||
|
|
||||||
BL_SOCKET_DESCR_ANNOT_STRING = ":: "
|
BL_SOCKET_DESCR_ANNOT_STRING = ':: '
|
||||||
BL_SOCKET_DESCR_TYPE_MAP = {
|
BL_SOCKET_DESCR_TYPE_MAP = {
|
||||||
("Time", "NodeSocketFloat", 1): ST.PhysicalTime,
|
('Time', 'NodeSocketFloat', 1): ST.PhysicalTime,
|
||||||
|
('Angle', 'NodeSocketFloat', 1): ST.PhysicalAngle,
|
||||||
("Angle", "NodeSocketFloat", 1): ST.PhysicalAngle,
|
('SolidAngle', 'NodeSocketFloat', 1): ST.PhysicalSolidAngle,
|
||||||
("SolidAngle", "NodeSocketFloat", 1): ST.PhysicalSolidAngle,
|
('Rotation', 'NodeSocketVector', 2): ST.PhysicalRot2D,
|
||||||
|
('Rotation', 'NodeSocketVector', 3): ST.PhysicalRot3D,
|
||||||
("Rotation", "NodeSocketVector", 2): ST.PhysicalRot2D,
|
('Freq', 'NodeSocketFloat', 1): ST.PhysicalFreq,
|
||||||
("Rotation", "NodeSocketVector", 3): ST.PhysicalRot3D,
|
('AngFreq', 'NodeSocketFloat', 1): ST.PhysicalAngFreq,
|
||||||
|
|
||||||
("Freq", "NodeSocketFloat", 1): ST.PhysicalFreq,
|
|
||||||
("AngFreq", "NodeSocketFloat", 1): ST.PhysicalAngFreq,
|
|
||||||
|
|
||||||
## Cartesian
|
## Cartesian
|
||||||
("Length", "NodeSocketFloat", 1): ST.PhysicalLength,
|
('Length', 'NodeSocketFloat', 1): ST.PhysicalLength,
|
||||||
("Area", "NodeSocketFloat", 1): ST.PhysicalArea,
|
('Area', 'NodeSocketFloat', 1): ST.PhysicalArea,
|
||||||
("Volume", "NodeSocketFloat", 1): ST.PhysicalVolume,
|
('Volume', 'NodeSocketFloat', 1): ST.PhysicalVolume,
|
||||||
|
('Disp', 'NodeSocketVector', 2): ST.PhysicalDisp2D,
|
||||||
("Disp", "NodeSocketVector", 2): ST.PhysicalDisp2D,
|
('Disp', 'NodeSocketVector', 3): ST.PhysicalDisp3D,
|
||||||
("Disp", "NodeSocketVector", 3): ST.PhysicalDisp3D,
|
('Point', 'NodeSocketFloat', 1): ST.PhysicalPoint1D,
|
||||||
|
('Point', 'NodeSocketVector', 2): ST.PhysicalPoint2D,
|
||||||
("Point", "NodeSocketFloat", 1): ST.PhysicalPoint1D,
|
('Point', 'NodeSocketVector', 3): ST.PhysicalPoint3D,
|
||||||
("Point", "NodeSocketVector", 2): ST.PhysicalPoint2D,
|
('Size', 'NodeSocketVector', 2): ST.PhysicalSize2D,
|
||||||
("Point", "NodeSocketVector", 3): ST.PhysicalPoint3D,
|
('Size', 'NodeSocketVector', 3): ST.PhysicalSize3D,
|
||||||
|
|
||||||
("Size", "NodeSocketVector", 2): ST.PhysicalSize2D,
|
|
||||||
("Size", "NodeSocketVector", 3): ST.PhysicalSize3D,
|
|
||||||
|
|
||||||
## Mechanical
|
## Mechanical
|
||||||
("Mass", "NodeSocketFloat", 1): ST.PhysicalMass,
|
('Mass', 'NodeSocketFloat', 1): ST.PhysicalMass,
|
||||||
|
('Speed', 'NodeSocketFloat', 1): ST.PhysicalSpeed,
|
||||||
("Speed", "NodeSocketFloat", 1): ST.PhysicalSpeed,
|
('Vel', 'NodeSocketVector', 2): ST.PhysicalVel2D,
|
||||||
("Vel", "NodeSocketVector", 2): ST.PhysicalVel2D,
|
('Vel', 'NodeSocketVector', 3): ST.PhysicalVel3D,
|
||||||
("Vel", "NodeSocketVector", 3): ST.PhysicalVel3D,
|
('Accel', 'NodeSocketFloat', 1): ST.PhysicalAccelScalar,
|
||||||
("Accel", "NodeSocketFloat", 1): ST.PhysicalAccelScalar,
|
('Accel', 'NodeSocketVector', 2): ST.PhysicalAccel2D,
|
||||||
("Accel", "NodeSocketVector", 2): ST.PhysicalAccel2D,
|
('Accel', 'NodeSocketVector', 3): ST.PhysicalAccel3D,
|
||||||
("Accel", "NodeSocketVector", 3): ST.PhysicalAccel3D,
|
('Force', 'NodeSocketFloat', 1): ST.PhysicalForceScalar,
|
||||||
("Force", "NodeSocketFloat", 1): ST.PhysicalForceScalar,
|
('Force', 'NodeSocketVector', 2): ST.PhysicalForce2D,
|
||||||
("Force", "NodeSocketVector", 2): ST.PhysicalForce2D,
|
('Force', 'NodeSocketVector', 3): ST.PhysicalForce3D,
|
||||||
("Force", "NodeSocketVector", 3): ST.PhysicalForce3D,
|
('Pressure', 'NodeSocketFloat', 1): ST.PhysicalPressure,
|
||||||
("Pressure", "NodeSocketFloat", 1): ST.PhysicalPressure,
|
|
||||||
|
|
||||||
## Energetic
|
## Energetic
|
||||||
("Energy", "NodeSocketFloat", 1): ST.PhysicalEnergy,
|
('Energy', 'NodeSocketFloat', 1): ST.PhysicalEnergy,
|
||||||
("Power", "NodeSocketFloat", 1): ST.PhysicalPower,
|
('Power', 'NodeSocketFloat', 1): ST.PhysicalPower,
|
||||||
("Temp", "NodeSocketFloat", 1): ST.PhysicalTemp,
|
('Temp', 'NodeSocketFloat', 1): ST.PhysicalTemp,
|
||||||
|
|
||||||
## ELectrodynamical
|
## ELectrodynamical
|
||||||
("Curr", "NodeSocketFloat", 1): ST.PhysicalCurr,
|
('Curr', 'NodeSocketFloat', 1): ST.PhysicalCurr,
|
||||||
("CurrDens", "NodeSocketVector", 2): ST.PhysicalCurrDens2D,
|
('CurrDens', 'NodeSocketVector', 2): ST.PhysicalCurrDens2D,
|
||||||
("CurrDens", "NodeSocketVector", 3): ST.PhysicalCurrDens3D,
|
('CurrDens', 'NodeSocketVector', 3): ST.PhysicalCurrDens3D,
|
||||||
|
('Charge', 'NodeSocketFloat', 1): ST.PhysicalCharge,
|
||||||
("Charge", "NodeSocketFloat", 1): ST.PhysicalCharge,
|
('Voltage', 'NodeSocketFloat', 1): ST.PhysicalVoltage,
|
||||||
("Voltage", "NodeSocketFloat", 1): ST.PhysicalVoltage,
|
('Capacitance', 'NodeSocketFloat', 1): ST.PhysicalCapacitance,
|
||||||
("Capacitance", "NodeSocketFloat", 1): ST.PhysicalCapacitance,
|
('Resistance', 'NodeSocketFloat', 1): ST.PhysicalResistance,
|
||||||
("Resistance", "NodeSocketFloat", 1): ST.PhysicalResistance,
|
('Conductance', 'NodeSocketFloat', 1): ST.PhysicalConductance,
|
||||||
("Conductance", "NodeSocketFloat", 1): ST.PhysicalConductance,
|
('MagFlux', 'NodeSocketFloat', 1): ST.PhysicalMagFlux,
|
||||||
|
('MagFluxDens', 'NodeSocketFloat', 1): ST.PhysicalMagFluxDens,
|
||||||
("MagFlux", "NodeSocketFloat", 1): ST.PhysicalMagFlux,
|
('Inductance', 'NodeSocketFloat', 1): ST.PhysicalInductance,
|
||||||
("MagFluxDens", "NodeSocketFloat", 1): ST.PhysicalMagFluxDens,
|
('EField', 'NodeSocketFloat', 2): ST.PhysicalEField3D,
|
||||||
("Inductance", "NodeSocketFloat", 1): ST.PhysicalInductance,
|
('EField', 'NodeSocketFloat', 3): ST.PhysicalEField2D,
|
||||||
|
('HField', 'NodeSocketFloat', 2): ST.PhysicalHField3D,
|
||||||
("EField", "NodeSocketFloat", 2): ST.PhysicalEField3D,
|
('HField', 'NodeSocketFloat', 3): ST.PhysicalHField2D,
|
||||||
("EField", "NodeSocketFloat", 3): ST.PhysicalEField2D,
|
|
||||||
("HField", "NodeSocketFloat", 2): ST.PhysicalHField3D,
|
|
||||||
("HField", "NodeSocketFloat", 3): ST.PhysicalHField2D,
|
|
||||||
|
|
||||||
## Luminal
|
## Luminal
|
||||||
("LumIntensity", "NodeSocketFloat", 1): ST.PhysicalLumIntensity,
|
('LumIntensity', 'NodeSocketFloat', 1): ST.PhysicalLumIntensity,
|
||||||
("LumFlux", "NodeSocketFloat", 1): ST.PhysicalLumFlux,
|
('LumFlux', 'NodeSocketFloat', 1): ST.PhysicalLumFlux,
|
||||||
("Illuminance", "NodeSocketFloat", 1): ST.PhysicalIlluminance,
|
('Illuminance', 'NodeSocketFloat', 1): ST.PhysicalIlluminance,
|
||||||
|
|
||||||
## Optical
|
## Optical
|
||||||
("PolJones", "NodeSocketFloat", 2): ST.PhysicalPolJones,
|
('PolJones', 'NodeSocketFloat', 2): ST.PhysicalPolJones,
|
||||||
("Pol", "NodeSocketFloat", 4): ST.PhysicalPol,
|
('Pol', 'NodeSocketFloat', 4): ST.PhysicalPol,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,33 @@
|
||||||
from .socket_types import SocketType as ST
|
from .socket_types import SocketType as ST
|
||||||
|
|
||||||
BL_SOCKET_DIRECT_TYPE_MAP = {
|
BL_SOCKET_DIRECT_TYPE_MAP = {
|
||||||
("NodeSocketString", 1): ST.String,
|
('NodeSocketString', 1): ST.String,
|
||||||
("NodeSocketBool", 1): ST.Bool,
|
('NodeSocketBool', 1): ST.Bool,
|
||||||
("NodeSocketCollection", 1): ST.BlenderCollection,
|
('NodeSocketCollection', 1): ST.BlenderCollection,
|
||||||
("NodeSocketImage", 1): ST.BlenderImage,
|
('NodeSocketImage', 1): ST.BlenderImage,
|
||||||
("NodeSocketObject", 1): ST.BlenderObject,
|
('NodeSocketObject', 1): ST.BlenderObject,
|
||||||
|
('NodeSocketFloat', 1): ST.RealNumber,
|
||||||
("NodeSocketFloat", 1): ST.RealNumber,
|
# ("NodeSocketFloatAngle", 1): ST.PhysicalAngle,
|
||||||
#("NodeSocketFloatAngle", 1): ST.PhysicalAngle,
|
# ("NodeSocketFloatDistance", 1): ST.PhysicalLength,
|
||||||
#("NodeSocketFloatDistance", 1): ST.PhysicalLength,
|
('NodeSocketFloatFactor', 1): ST.RealNumber,
|
||||||
("NodeSocketFloatFactor", 1): ST.RealNumber,
|
('NodeSocketFloatPercentage', 1): ST.RealNumber,
|
||||||
("NodeSocketFloatPercentage", 1): ST.RealNumber,
|
# ("NodeSocketFloatTime", 1): ST.PhysicalTime,
|
||||||
#("NodeSocketFloatTime", 1): ST.PhysicalTime,
|
# ("NodeSocketFloatTimeAbsolute", 1): ST.PhysicalTime,
|
||||||
#("NodeSocketFloatTimeAbsolute", 1): ST.PhysicalTime,
|
('NodeSocketInt', 1): ST.IntegerNumber,
|
||||||
|
('NodeSocketIntFactor', 1): ST.IntegerNumber,
|
||||||
("NodeSocketInt", 1): ST.IntegerNumber,
|
('NodeSocketIntPercentage', 1): ST.IntegerNumber,
|
||||||
("NodeSocketIntFactor", 1): ST.IntegerNumber,
|
('NodeSocketIntUnsigned', 1): ST.IntegerNumber,
|
||||||
("NodeSocketIntPercentage", 1): ST.IntegerNumber,
|
('NodeSocketRotation', 2): ST.PhysicalRot2D,
|
||||||
("NodeSocketIntUnsigned", 1): ST.IntegerNumber,
|
('NodeSocketColor', 3): ST.Color,
|
||||||
|
('NodeSocketVector', 2): ST.Real2DVector,
|
||||||
("NodeSocketRotation", 2): ST.PhysicalRot2D,
|
('NodeSocketVector', 3): ST.Real3DVector,
|
||||||
("NodeSocketColor", 3): ST.Color,
|
# ("NodeSocketVectorAcceleration", 2): ST.PhysicalAccel2D,
|
||||||
("NodeSocketVector", 2): ST.Real2DVector,
|
# ("NodeSocketVectorAcceleration", 3): ST.PhysicalAccel3D,
|
||||||
("NodeSocketVector", 3): ST.Real3DVector,
|
# ("NodeSocketVectorDirection", 2): ST.Real2DVectorDir,
|
||||||
#("NodeSocketVectorAcceleration", 2): ST.PhysicalAccel2D,
|
# ("NodeSocketVectorDirection", 3): ST.Real3DVectorDir,
|
||||||
#("NodeSocketVectorAcceleration", 3): ST.PhysicalAccel3D,
|
('NodeSocketVectorEuler', 2): ST.PhysicalRot2D,
|
||||||
#("NodeSocketVectorDirection", 2): ST.Real2DVectorDir,
|
('NodeSocketVectorEuler', 3): ST.PhysicalRot3D,
|
||||||
#("NodeSocketVectorDirection", 3): ST.Real3DVectorDir,
|
# ("NodeSocketVectorTranslation", 3): ST.PhysicalDisp3D,
|
||||||
("NodeSocketVectorEuler", 2): ST.PhysicalRot2D,
|
# ("NodeSocketVectorVelocity", 3): ST.PhysicalVel3D,
|
||||||
("NodeSocketVectorEuler", 3): ST.PhysicalRot3D,
|
# ("NodeSocketVectorXYZ", 3): ST.PhysicalPoint3D,
|
||||||
#("NodeSocketVectorTranslation", 3): ST.PhysicalDisp3D,
|
|
||||||
#("NodeSocketVectorVelocity", 3): ST.PhysicalVel3D,
|
|
||||||
#("NodeSocketVectorXYZ", 3): ST.PhysicalPoint3D,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,67 +2,61 @@ from .socket_types import SocketType as ST
|
||||||
|
|
||||||
SOCKET_SHAPES = {
|
SOCKET_SHAPES = {
|
||||||
# Basic
|
# Basic
|
||||||
ST.Any: "CIRCLE",
|
ST.Any: 'CIRCLE',
|
||||||
ST.Bool: "CIRCLE",
|
ST.Bool: 'CIRCLE',
|
||||||
ST.String: "CIRCLE",
|
ST.String: 'CIRCLE',
|
||||||
ST.FilePath: "CIRCLE",
|
ST.FilePath: 'CIRCLE',
|
||||||
|
|
||||||
# Number
|
# Number
|
||||||
ST.IntegerNumber: "CIRCLE",
|
ST.IntegerNumber: 'CIRCLE',
|
||||||
ST.RationalNumber: "CIRCLE",
|
ST.RationalNumber: 'CIRCLE',
|
||||||
ST.RealNumber: "CIRCLE",
|
ST.RealNumber: 'CIRCLE',
|
||||||
ST.ComplexNumber: "CIRCLE",
|
ST.ComplexNumber: 'CIRCLE',
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
ST.Integer2DVector: "CIRCLE",
|
ST.Integer2DVector: 'CIRCLE',
|
||||||
ST.Real2DVector: "CIRCLE",
|
ST.Real2DVector: 'CIRCLE',
|
||||||
ST.Complex2DVector: "CIRCLE",
|
ST.Complex2DVector: 'CIRCLE',
|
||||||
ST.Integer3DVector: "CIRCLE",
|
ST.Integer3DVector: 'CIRCLE',
|
||||||
ST.Real3DVector: "CIRCLE",
|
ST.Real3DVector: 'CIRCLE',
|
||||||
ST.Complex3DVector: "CIRCLE",
|
ST.Complex3DVector: 'CIRCLE',
|
||||||
|
|
||||||
# Physical
|
# Physical
|
||||||
ST.PhysicalUnitSystem: "CIRCLE",
|
ST.PhysicalUnitSystem: 'CIRCLE',
|
||||||
ST.PhysicalTime: "CIRCLE",
|
ST.PhysicalTime: 'CIRCLE',
|
||||||
ST.PhysicalAngle: "CIRCLE",
|
ST.PhysicalAngle: 'CIRCLE',
|
||||||
ST.PhysicalLength: "CIRCLE",
|
ST.PhysicalLength: 'CIRCLE',
|
||||||
ST.PhysicalArea: "CIRCLE",
|
ST.PhysicalArea: 'CIRCLE',
|
||||||
ST.PhysicalVolume: "CIRCLE",
|
ST.PhysicalVolume: 'CIRCLE',
|
||||||
ST.PhysicalPoint2D: "CIRCLE",
|
ST.PhysicalPoint2D: 'CIRCLE',
|
||||||
ST.PhysicalPoint3D: "CIRCLE",
|
ST.PhysicalPoint3D: 'CIRCLE',
|
||||||
ST.PhysicalSize2D: "CIRCLE",
|
ST.PhysicalSize2D: 'CIRCLE',
|
||||||
ST.PhysicalSize3D: "CIRCLE",
|
ST.PhysicalSize3D: 'CIRCLE',
|
||||||
ST.PhysicalMass: "CIRCLE",
|
ST.PhysicalMass: 'CIRCLE',
|
||||||
ST.PhysicalSpeed: "CIRCLE",
|
ST.PhysicalSpeed: 'CIRCLE',
|
||||||
ST.PhysicalAccelScalar: "CIRCLE",
|
ST.PhysicalAccelScalar: 'CIRCLE',
|
||||||
ST.PhysicalForceScalar: "CIRCLE",
|
ST.PhysicalForceScalar: 'CIRCLE',
|
||||||
ST.PhysicalAccel3D: "CIRCLE",
|
ST.PhysicalAccel3D: 'CIRCLE',
|
||||||
ST.PhysicalForce3D: "CIRCLE",
|
ST.PhysicalForce3D: 'CIRCLE',
|
||||||
ST.PhysicalPol: "CIRCLE",
|
ST.PhysicalPol: 'CIRCLE',
|
||||||
ST.PhysicalFreq: "CIRCLE",
|
ST.PhysicalFreq: 'CIRCLE',
|
||||||
|
|
||||||
# Blender
|
# Blender
|
||||||
ST.BlenderObject: "DIAMOND",
|
ST.BlenderObject: 'DIAMOND',
|
||||||
ST.BlenderCollection: "DIAMOND",
|
ST.BlenderCollection: 'DIAMOND',
|
||||||
ST.BlenderImage: "DIAMOND",
|
ST.BlenderImage: 'DIAMOND',
|
||||||
ST.BlenderGeoNodes: "DIAMOND",
|
ST.BlenderGeoNodes: 'DIAMOND',
|
||||||
ST.BlenderText: "DIAMOND",
|
ST.BlenderText: 'DIAMOND',
|
||||||
|
|
||||||
# Maxwell
|
# Maxwell
|
||||||
ST.MaxwellSource: "CIRCLE",
|
ST.MaxwellSource: 'CIRCLE',
|
||||||
ST.MaxwellTemporalShape: "CIRCLE",
|
ST.MaxwellTemporalShape: 'CIRCLE',
|
||||||
ST.MaxwellMedium: "CIRCLE",
|
ST.MaxwellMedium: 'CIRCLE',
|
||||||
ST.MaxwellMediumNonLinearity: "CIRCLE",
|
ST.MaxwellMediumNonLinearity: 'CIRCLE',
|
||||||
ST.MaxwellStructure: "CIRCLE",
|
ST.MaxwellStructure: 'CIRCLE',
|
||||||
ST.MaxwellBoundConds: "CIRCLE",
|
ST.MaxwellBoundConds: 'CIRCLE',
|
||||||
ST.MaxwellBoundCond: "CIRCLE",
|
ST.MaxwellBoundCond: 'CIRCLE',
|
||||||
ST.MaxwellMonitor: "CIRCLE",
|
ST.MaxwellMonitor: 'CIRCLE',
|
||||||
ST.MaxwellFDTDSim: "CIRCLE",
|
ST.MaxwellFDTDSim: 'CIRCLE',
|
||||||
ST.MaxwellFDTDSimData: "CIRCLE",
|
ST.MaxwellFDTDSimData: 'CIRCLE',
|
||||||
ST.MaxwellSimGrid: "CIRCLE",
|
ST.MaxwellSimGrid: 'CIRCLE',
|
||||||
ST.MaxwellSimGridAxis: "CIRCLE",
|
ST.MaxwellSimGridAxis: 'CIRCLE',
|
||||||
ST.MaxwellSimDomain: "CIRCLE",
|
ST.MaxwellSimDomain: 'CIRCLE',
|
||||||
|
|
||||||
# Tidy3D
|
# Tidy3D
|
||||||
ST.Tidy3DCloudTask: "DIAMOND",
|
ST.Tidy3DCloudTask: 'DIAMOND',
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import (
|
from ....utils.blender_type_enum import (
|
||||||
BlenderTypeEnum, append_cls_name_to_values, wrap_values_in_MT
|
BlenderTypeEnum,
|
||||||
|
append_cls_name_to_values,
|
||||||
|
wrap_values_in_MT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@append_cls_name_to_values
|
@append_cls_name_to_values
|
||||||
class SocketType(BlenderTypeEnum):
|
class SocketType(BlenderTypeEnum):
|
||||||
# Base
|
# Base
|
||||||
|
|
|
@ -5,262 +5,255 @@ from .socket_types import SocketType as ST
|
||||||
|
|
||||||
SOCKET_UNITS = {
|
SOCKET_UNITS = {
|
||||||
ST.PhysicalTime: {
|
ST.PhysicalTime: {
|
||||||
"default": "PS",
|
'default': 'PS',
|
||||||
"values": {
|
'values': {
|
||||||
"FS": spux.femtosecond,
|
'FS': spux.femtosecond,
|
||||||
"PS": spu.picosecond,
|
'PS': spu.picosecond,
|
||||||
"NS": spu.nanosecond,
|
'NS': spu.nanosecond,
|
||||||
"MS": spu.microsecond,
|
'MS': spu.microsecond,
|
||||||
"MLSEC": spu.millisecond,
|
'MLSEC': spu.millisecond,
|
||||||
"SEC": spu.second,
|
'SEC': spu.second,
|
||||||
"MIN": spu.minute,
|
'MIN': spu.minute,
|
||||||
"HOUR": spu.hour,
|
'HOUR': spu.hour,
|
||||||
"DAY": spu.day,
|
'DAY': spu.day,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalAngle: {
|
ST.PhysicalAngle: {
|
||||||
"default": "RADIAN",
|
'default': 'RADIAN',
|
||||||
"values": {
|
'values': {
|
||||||
"RADIAN": spu.radian,
|
'RADIAN': spu.radian,
|
||||||
"DEGREE": spu.degree,
|
'DEGREE': spu.degree,
|
||||||
"STERAD": spu.steradian,
|
'STERAD': spu.steradian,
|
||||||
"ANGMIL": spu.angular_mil,
|
'ANGMIL': spu.angular_mil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalLength: {
|
ST.PhysicalLength: {
|
||||||
"default": "UM",
|
'default': 'UM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer,
|
'PM': spu.picometer,
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
"INCH": spu.inch,
|
'INCH': spu.inch,
|
||||||
"FOOT": spu.foot,
|
'FOOT': spu.foot,
|
||||||
"YARD": spu.yard,
|
'YARD': spu.yard,
|
||||||
"MILE": spu.mile,
|
'MILE': spu.mile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalArea: {
|
ST.PhysicalArea: {
|
||||||
"default": "UM_SQ",
|
'default': 'UM_SQ',
|
||||||
"values": {
|
'values': {
|
||||||
"PM_SQ": spu.picometer**2,
|
'PM_SQ': spu.picometer**2,
|
||||||
"A_SQ": spu.angstrom**2,
|
'A_SQ': spu.angstrom**2,
|
||||||
"NM_SQ": spu.nanometer**2,
|
'NM_SQ': spu.nanometer**2,
|
||||||
"UM_SQ": spu.micrometer**2,
|
'UM_SQ': spu.micrometer**2,
|
||||||
"MM_SQ": spu.millimeter**2,
|
'MM_SQ': spu.millimeter**2,
|
||||||
"CM_SQ": spu.centimeter**2,
|
'CM_SQ': spu.centimeter**2,
|
||||||
"M_SQ": spu.meter**2,
|
'M_SQ': spu.meter**2,
|
||||||
"INCH_SQ": spu.inch**2,
|
'INCH_SQ': spu.inch**2,
|
||||||
"FOOT_SQ": spu.foot**2,
|
'FOOT_SQ': spu.foot**2,
|
||||||
"YARD_SQ": spu.yard**2,
|
'YARD_SQ': spu.yard**2,
|
||||||
"MILE_SQ": spu.mile**2,
|
'MILE_SQ': spu.mile**2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalVolume: {
|
ST.PhysicalVolume: {
|
||||||
"default": "UM_CB",
|
'default': 'UM_CB',
|
||||||
"values": {
|
'values': {
|
||||||
"PM_CB": spu.picometer**3,
|
'PM_CB': spu.picometer**3,
|
||||||
"A_CB": spu.angstrom**3,
|
'A_CB': spu.angstrom**3,
|
||||||
"NM_CB": spu.nanometer**3,
|
'NM_CB': spu.nanometer**3,
|
||||||
"UM_CB": spu.micrometer**3,
|
'UM_CB': spu.micrometer**3,
|
||||||
"MM_CB": spu.millimeter**3,
|
'MM_CB': spu.millimeter**3,
|
||||||
"CM_CB": spu.centimeter**3,
|
'CM_CB': spu.centimeter**3,
|
||||||
"M_CB": spu.meter**3,
|
'M_CB': spu.meter**3,
|
||||||
"ML": spu.milliliter,
|
'ML': spu.milliliter,
|
||||||
"L": spu.liter,
|
'L': spu.liter,
|
||||||
"INCH_CB": spu.inch**3,
|
'INCH_CB': spu.inch**3,
|
||||||
"FOOT_CB": spu.foot**3,
|
'FOOT_CB': spu.foot**3,
|
||||||
"YARD_CB": spu.yard**3,
|
'YARD_CB': spu.yard**3,
|
||||||
"MILE_CB": spu.mile**3,
|
'MILE_CB': spu.mile**3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalPoint2D: {
|
ST.PhysicalPoint2D: {
|
||||||
"default": "UM",
|
'default': 'UM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer,
|
'PM': spu.picometer,
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
"INCH": spu.inch,
|
'INCH': spu.inch,
|
||||||
"FOOT": spu.foot,
|
'FOOT': spu.foot,
|
||||||
"YARD": spu.yard,
|
'YARD': spu.yard,
|
||||||
"MILE": spu.mile,
|
'MILE': spu.mile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalPoint3D: {
|
ST.PhysicalPoint3D: {
|
||||||
"default": "UM",
|
'default': 'UM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer,
|
'PM': spu.picometer,
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
"INCH": spu.inch,
|
'INCH': spu.inch,
|
||||||
"FOOT": spu.foot,
|
'FOOT': spu.foot,
|
||||||
"YARD": spu.yard,
|
'YARD': spu.yard,
|
||||||
"MILE": spu.mile,
|
'MILE': spu.mile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalSize2D: {
|
ST.PhysicalSize2D: {
|
||||||
"default": "UM",
|
'default': 'UM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer,
|
'PM': spu.picometer,
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
"INCH": spu.inch,
|
'INCH': spu.inch,
|
||||||
"FOOT": spu.foot,
|
'FOOT': spu.foot,
|
||||||
"YARD": spu.yard,
|
'YARD': spu.yard,
|
||||||
"MILE": spu.mile,
|
'MILE': spu.mile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalSize3D: {
|
ST.PhysicalSize3D: {
|
||||||
"default": "UM",
|
'default': 'UM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer,
|
'PM': spu.picometer,
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
"INCH": spu.inch,
|
'INCH': spu.inch,
|
||||||
"FOOT": spu.foot,
|
'FOOT': spu.foot,
|
||||||
"YARD": spu.yard,
|
'YARD': spu.yard,
|
||||||
"MILE": spu.mile,
|
'MILE': spu.mile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalMass: {
|
ST.PhysicalMass: {
|
||||||
"default": "UG",
|
'default': 'UG',
|
||||||
"values": {
|
'values': {
|
||||||
"E_REST": spu.electron_rest_mass,
|
'E_REST': spu.electron_rest_mass,
|
||||||
"DAL": spu.dalton,
|
'DAL': spu.dalton,
|
||||||
"UG": spu.microgram,
|
'UG': spu.microgram,
|
||||||
"MG": spu.milligram,
|
'MG': spu.milligram,
|
||||||
"G": spu.gram,
|
'G': spu.gram,
|
||||||
"KG": spu.kilogram,
|
'KG': spu.kilogram,
|
||||||
"TON": spu.metric_ton,
|
'TON': spu.metric_ton,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalSpeed: {
|
ST.PhysicalSpeed: {
|
||||||
"default": "UM_S",
|
'default': 'UM_S',
|
||||||
"values": {
|
'values': {
|
||||||
"PM_S": spu.picometer / spu.second,
|
'PM_S': spu.picometer / spu.second,
|
||||||
"NM_S": spu.nanometer / spu.second,
|
'NM_S': spu.nanometer / spu.second,
|
||||||
"UM_S": spu.micrometer / spu.second,
|
'UM_S': spu.micrometer / spu.second,
|
||||||
"MM_S": spu.millimeter / spu.second,
|
'MM_S': spu.millimeter / spu.second,
|
||||||
"M_S": spu.meter / spu.second,
|
'M_S': spu.meter / spu.second,
|
||||||
"KM_S": spu.kilometer / spu.second,
|
'KM_S': spu.kilometer / spu.second,
|
||||||
"KM_H": spu.kilometer / spu.hour,
|
'KM_H': spu.kilometer / spu.hour,
|
||||||
"FT_S": spu.feet / spu.second,
|
'FT_S': spu.feet / spu.second,
|
||||||
"MI_H": spu.mile / spu.hour,
|
'MI_H': spu.mile / spu.hour,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalAccelScalar: {
|
ST.PhysicalAccelScalar: {
|
||||||
"default": "UM_S_SQ",
|
'default': 'UM_S_SQ',
|
||||||
"values": {
|
'values': {
|
||||||
"PM_S_SQ": spu.picometer / spu.second**2,
|
'PM_S_SQ': spu.picometer / spu.second**2,
|
||||||
"NM_S_SQ": spu.nanometer / spu.second**2,
|
'NM_S_SQ': spu.nanometer / spu.second**2,
|
||||||
"UM_S_SQ": spu.micrometer / spu.second**2,
|
'UM_S_SQ': spu.micrometer / spu.second**2,
|
||||||
"MM_S_SQ": spu.millimeter / spu.second**2,
|
'MM_S_SQ': spu.millimeter / spu.second**2,
|
||||||
"M_S_SQ": spu.meter / spu.second**2,
|
'M_S_SQ': spu.meter / spu.second**2,
|
||||||
"KM_S_SQ": spu.kilometer / spu.second**2,
|
'KM_S_SQ': spu.kilometer / spu.second**2,
|
||||||
"FT_S_SQ": spu.feet / spu.second**2,
|
'FT_S_SQ': spu.feet / spu.second**2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalForceScalar: {
|
ST.PhysicalForceScalar: {
|
||||||
"default": "UNEWT",
|
'default': 'UNEWT',
|
||||||
"values": {
|
'values': {
|
||||||
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
'KG_M_S_SQ': spu.kg * spu.m / spu.second**2,
|
||||||
"NNEWT": spux.nanonewton,
|
'NNEWT': spux.nanonewton,
|
||||||
"UNEWT": spux.micronewton,
|
'UNEWT': spux.micronewton,
|
||||||
"MNEWT": spux.millinewton,
|
'MNEWT': spux.millinewton,
|
||||||
"NEWT": spu.newton,
|
'NEWT': spu.newton,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalAccel3D: {
|
ST.PhysicalAccel3D: {
|
||||||
"default": "UM_S_SQ",
|
'default': 'UM_S_SQ',
|
||||||
"values": {
|
'values': {
|
||||||
"PM_S_SQ": spu.picometer / spu.second**2,
|
'PM_S_SQ': spu.picometer / spu.second**2,
|
||||||
"NM_S_SQ": spu.nanometer / spu.second**2,
|
'NM_S_SQ': spu.nanometer / spu.second**2,
|
||||||
"UM_S_SQ": spu.micrometer / spu.second**2,
|
'UM_S_SQ': spu.micrometer / spu.second**2,
|
||||||
"MM_S_SQ": spu.millimeter / spu.second**2,
|
'MM_S_SQ': spu.millimeter / spu.second**2,
|
||||||
"M_S_SQ": spu.meter / spu.second**2,
|
'M_S_SQ': spu.meter / spu.second**2,
|
||||||
"KM_S_SQ": spu.kilometer / spu.second**2,
|
'KM_S_SQ': spu.kilometer / spu.second**2,
|
||||||
"FT_S_SQ": spu.feet / spu.second**2,
|
'FT_S_SQ': spu.feet / spu.second**2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalForce3D: {
|
ST.PhysicalForce3D: {
|
||||||
"default": "UNEWT",
|
'default': 'UNEWT',
|
||||||
"values": {
|
'values': {
|
||||||
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
'KG_M_S_SQ': spu.kg * spu.m / spu.second**2,
|
||||||
"NNEWT": spux.nanonewton,
|
'NNEWT': spux.nanonewton,
|
||||||
"UNEWT": spux.micronewton,
|
'UNEWT': spux.micronewton,
|
||||||
"MNEWT": spux.millinewton,
|
'MNEWT': spux.millinewton,
|
||||||
"NEWT": spu.newton,
|
'NEWT': spu.newton,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ST.PhysicalFreq: {
|
ST.PhysicalFreq: {
|
||||||
"default": "THZ",
|
'default': 'THZ',
|
||||||
"values": {
|
'values': {
|
||||||
"HZ": spu.hertz,
|
'HZ': spu.hertz,
|
||||||
"KHZ": spux.kilohertz,
|
'KHZ': spux.kilohertz,
|
||||||
"MHZ": spux.megahertz,
|
'MHZ': spux.megahertz,
|
||||||
"GHZ": spux.gigahertz,
|
'GHZ': spux.gigahertz,
|
||||||
"THZ": spux.terahertz,
|
'THZ': spux.terahertz,
|
||||||
"PHZ": spux.petahertz,
|
'PHZ': spux.petahertz,
|
||||||
"EHZ": spux.exahertz,
|
'EHZ': spux.exahertz,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalPol: {
|
ST.PhysicalPol: {
|
||||||
"default": "RADIAN",
|
'default': 'RADIAN',
|
||||||
"values": {
|
'values': {
|
||||||
"RADIAN": spu.radian,
|
'RADIAN': spu.radian,
|
||||||
"DEGREE": spu.degree,
|
'DEGREE': spu.degree,
|
||||||
"STERAD": spu.steradian,
|
'STERAD': spu.steradian,
|
||||||
"ANGMIL": spu.angular_mil,
|
'ANGMIL': spu.angular_mil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.MaxwellMedium: {
|
ST.MaxwellMedium: {
|
||||||
"default": "NM",
|
'default': 'NM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer, ## c(vac) = wl*freq
|
'PM': spu.picometer, ## c(vac) = wl*freq
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.MaxwellMonitor: {
|
ST.MaxwellMonitor: {
|
||||||
"default": "NM",
|
'default': 'NM',
|
||||||
"values": {
|
'values': {
|
||||||
"PM": spu.picometer, ## c(vac) = wl*freq
|
'PM': spu.picometer, ## c(vac) = wl*freq
|
||||||
"A": spu.angstrom,
|
'A': spu.angstrom,
|
||||||
"NM": spu.nanometer,
|
'NM': spu.nanometer,
|
||||||
"UM": spu.micrometer,
|
'UM': spu.micrometer,
|
||||||
"MM": spu.millimeter,
|
'MM': spu.millimeter,
|
||||||
"CM": spu.centimeter,
|
'CM': spu.centimeter,
|
||||||
"M": spu.meter,
|
'M': spu.meter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
from ....utils.blender_type_enum import (
|
from ....utils.blender_type_enum import (
|
||||||
BlenderTypeEnum, append_cls_name_to_values
|
BlenderTypeEnum,
|
||||||
|
append_cls_name_to_values,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@append_cls_name_to_values
|
@append_cls_name_to_values
|
||||||
class TreeType(BlenderTypeEnum):
|
class TreeType(BlenderTypeEnum):
|
||||||
MaxwellSim = enum.auto()
|
MaxwellSim = enum.auto()
|
||||||
|
|
|
@ -10,8 +10,9 @@ import bpy
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
|
||||||
AREA_TYPE = "IMAGE_EDITOR"
|
AREA_TYPE = 'IMAGE_EDITOR'
|
||||||
SPACE_TYPE = "IMAGE_EDITOR"
|
SPACE_TYPE = 'IMAGE_EDITOR'
|
||||||
|
|
||||||
|
|
||||||
class ManagedBLImage(ct.schemas.ManagedObj):
|
class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
managed_obj_type = ct.ManagedObjType.ManagedBLImage
|
managed_obj_type = ct.ManagedObjType.ManagedBLImage
|
||||||
|
@ -36,7 +37,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
|
|
||||||
# ...AND Desired Image Name is Taken
|
# ...AND Desired Image Name is Taken
|
||||||
else:
|
else:
|
||||||
msg = f"Desired name {value} for BL image is taken"
|
msg = f'Desired name {value} for BL image is taken'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# Object DOES Exist
|
# Object DOES Exist
|
||||||
|
@ -59,24 +60,21 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
self,
|
self,
|
||||||
width_px: int,
|
width_px: int,
|
||||||
height_px: int,
|
height_px: int,
|
||||||
color_model: typx.Literal["RGB", "RGBA"],
|
color_model: typx.Literal['RGB', 'RGBA'],
|
||||||
dtype: typx.Literal["uint8", "float32"],
|
dtype: typx.Literal['uint8', 'float32'],
|
||||||
):
|
):
|
||||||
"""Returns the managed blender image.
|
"""Returns the managed blender image.
|
||||||
|
|
||||||
If the requested image properties are different from the image's, then delete the old image make a new image with correct geometry.
|
If the requested image properties are different from the image's, then delete the old image make a new image with correct geometry.
|
||||||
"""
|
"""
|
||||||
channels = 4 if color_model == "RGBA" else 3
|
channels = 4 if color_model == 'RGBA' else 3
|
||||||
|
|
||||||
# Remove Image (if mismatch)
|
# Remove Image (if mismatch)
|
||||||
if (
|
if (bl_image := bpy.data.images.get(self.name)) and (
|
||||||
(bl_image := bpy.data.images.get(self.name))
|
|
||||||
and (
|
|
||||||
bl_image.size[0] != width_px
|
bl_image.size[0] != width_px
|
||||||
or bl_image.size[1] != height_px
|
or bl_image.size[1] != height_px
|
||||||
or bl_image.channels != channels
|
or bl_image.channels != channels
|
||||||
or bl_image.is_float ^ (dtype == "float32")
|
or bl_image.is_float ^ (dtype == 'float32')
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self.free()
|
self.free()
|
||||||
|
|
||||||
|
@ -99,9 +97,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
If none are valid, return None.
|
If none are valid, return None.
|
||||||
"""
|
"""
|
||||||
valid_areas = [
|
valid_areas = [
|
||||||
area
|
area for area in bpy.context.screen.areas if area.type == AREA_TYPE
|
||||||
for area in bpy.context.screen.areas
|
|
||||||
if area.type == AREA_TYPE
|
|
||||||
]
|
]
|
||||||
if valid_areas:
|
if valid_areas:
|
||||||
return valid_areas[0]
|
return valid_areas[0]
|
||||||
|
@ -111,7 +107,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
"""Returns the visible preview space in the visible preview area of
|
"""Returns the visible preview space in the visible preview area of
|
||||||
the Blender UI
|
the Blender UI
|
||||||
"""
|
"""
|
||||||
if (preview_area := self.preview_area):
|
if preview_area := self.preview_area:
|
||||||
return next(
|
return next(
|
||||||
space
|
space
|
||||||
for space in preview_area.spaces
|
for space in preview_area.spaces
|
||||||
|
@ -125,7 +121,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
"""Synchronizes the managed object to the preview, by manipulating
|
"""Synchronizes the managed object to the preview, by manipulating
|
||||||
relevant editors.
|
relevant editors.
|
||||||
"""
|
"""
|
||||||
if (bl_image := bpy.data.images.get(self.name)):
|
if bl_image := bpy.data.images.get(self.name):
|
||||||
self.preview_space.image = bl_image
|
self.preview_space.image = bl_image
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -142,7 +138,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
# Compute Image Geometry
|
# Compute Image Geometry
|
||||||
if (preview_area := self.preview_area):
|
if preview_area := self.preview_area:
|
||||||
# Retrieve DPI from Blender Preferences
|
# Retrieve DPI from Blender Preferences
|
||||||
_dpi = bpy.context.preferences.system.dpi
|
_dpi = bpy.context.preferences.system.dpi
|
||||||
|
|
||||||
|
@ -165,7 +161,7 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
height_px = int(_height_inches * _dpi)
|
height_px = int(_height_inches * _dpi)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msg = f"There must either be a preview area, or defined `width_inches`, `height_inches`, and `dpi`"
|
msg = f'There must either be a preview area, or defined `width_inches`, `height_inches`, and `dpi`'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# Compute Plot Dimensions
|
# Compute Plot Dimensions
|
||||||
|
@ -196,10 +192,9 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
plt.close(fig)
|
plt.close(fig)
|
||||||
|
|
||||||
# Optimized Write to Blender Image
|
# Optimized Write to Blender Image
|
||||||
bl_image = self.bl_image(cmp_width_px, cmp_height_px, "RGBA", "uint8")
|
bl_image = self.bl_image(cmp_width_px, cmp_height_px, 'RGBA', 'uint8')
|
||||||
bl_image.pixels.foreach_set(image_data.ravel())
|
bl_image.pixels.foreach_set(image_data.ravel())
|
||||||
bl_image.update()
|
bl_image.update()
|
||||||
|
|
||||||
if bl_select:
|
if bl_select:
|
||||||
self.bl_select()
|
self.bl_select()
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,14 @@ import bmesh
|
||||||
|
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
|
||||||
ModifierType = typx.Literal["NODES", "ARRAY"]
|
ModifierType = typx.Literal['NODES', 'ARRAY']
|
||||||
MODIFIER_NAMES = {
|
MODIFIER_NAMES = {
|
||||||
"NODES": "BLMaxwell_GeoNodes",
|
'NODES': 'BLMaxwell_GeoNodes',
|
||||||
"ARRAY": "BLMaxwell_Array",
|
'ARRAY': 'BLMaxwell_Array',
|
||||||
}
|
}
|
||||||
MANAGED_COLLECTION_NAME = "BLMaxwell"
|
MANAGED_COLLECTION_NAME = 'BLMaxwell'
|
||||||
PREVIEW_COLLECTION_NAME = "BLMaxwell Visible"
|
PREVIEW_COLLECTION_NAME = 'BLMaxwell Visible'
|
||||||
|
|
||||||
|
|
||||||
def bl_collection(
|
def bl_collection(
|
||||||
collection_name: str, view_layer_exclude: bool
|
collection_name: str, view_layer_exclude: bool
|
||||||
|
@ -33,13 +34,16 @@ def bl_collection(
|
||||||
collection = bpy.data.collections[collection_name]
|
collection = bpy.data.collections[collection_name]
|
||||||
|
|
||||||
## Ensure synced View Layer exclusion
|
## Ensure synced View Layer exclusion
|
||||||
if (layer_collection := bpy.context.view_layer.layer_collection.children[
|
if (
|
||||||
|
layer_collection := bpy.context.view_layer.layer_collection.children[
|
||||||
collection_name
|
collection_name
|
||||||
]).exclude != view_layer_exclude:
|
]
|
||||||
|
).exclude != view_layer_exclude:
|
||||||
layer_collection.exclude = view_layer_exclude
|
layer_collection.exclude = view_layer_exclude
|
||||||
|
|
||||||
return collection
|
return collection
|
||||||
|
|
||||||
|
|
||||||
class ManagedBLObject(ct.schemas.ManagedObj):
|
class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
managed_obj_type = ct.ManagedObjType.ManagedBLObject
|
managed_obj_type = ct.ManagedObjType.ManagedBLObject
|
||||||
_bl_object_name: str
|
_bl_object_name: str
|
||||||
|
@ -63,7 +67,7 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
|
|
||||||
# ...AND Desired Object Name is Taken
|
# ...AND Desired Object Name is Taken
|
||||||
else:
|
else:
|
||||||
msg = f"Desired name {value} for BL object is taken"
|
msg = f'Desired name {value} for BL object is taken'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# Object DOES Exist
|
# Object DOES Exist
|
||||||
|
@ -88,14 +92,14 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
|
|
||||||
# Delete the Underlying Datablock
|
# Delete the Underlying Datablock
|
||||||
## This automatically deletes the object too
|
## This automatically deletes the object too
|
||||||
if bl_object.type == "MESH":
|
if bl_object.type == 'MESH':
|
||||||
bpy.data.meshes.remove(bl_object.data)
|
bpy.data.meshes.remove(bl_object.data)
|
||||||
elif bl_object.type == "EMPTY":
|
elif bl_object.type == 'EMPTY':
|
||||||
bpy.data.meshes.remove(bl_object.data)
|
bpy.data.meshes.remove(bl_object.data)
|
||||||
elif bl_object.type == "VOLUME":
|
elif bl_object.type == 'VOLUME':
|
||||||
bpy.data.volumes.remove(bl_object.data)
|
bpy.data.volumes.remove(bl_object.data)
|
||||||
else:
|
else:
|
||||||
msg = f"Type of to-delete `bl_object`, {bl_object.type}, is not valid"
|
msg = f'Type of to-delete `bl_object`, {bl_object.type}, is not valid'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -103,37 +107,54 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
####################
|
####################
|
||||||
def show_preview(
|
def show_preview(
|
||||||
self,
|
self,
|
||||||
kind: typx.Literal["MESH", "EMPTY", "VOLUME"],
|
kind: typx.Literal['MESH', 'EMPTY', 'VOLUME'],
|
||||||
empty_display_type: typx.Literal[
|
empty_display_type: typx.Literal[
|
||||||
"PLAIN_AXES", "ARROWS", "SINGLE_ARROW", "CIRCLE", "CUBE",
|
'PLAIN_AXES',
|
||||||
"SPHERE", "CONE", "IMAGE",
|
'ARROWS',
|
||||||
] | None = None,
|
'SINGLE_ARROW',
|
||||||
|
'CIRCLE',
|
||||||
|
'CUBE',
|
||||||
|
'SPHERE',
|
||||||
|
'CONE',
|
||||||
|
'IMAGE',
|
||||||
|
]
|
||||||
|
| None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Moves the managed Blender object to the preview collection.
|
"""Moves the managed Blender object to the preview collection.
|
||||||
|
|
||||||
If it's already included, do nothing.
|
If it's already included, do nothing.
|
||||||
"""
|
"""
|
||||||
bl_object = self.bl_object(kind)
|
bl_object = self.bl_object(kind)
|
||||||
if bl_object.name not in (preview_collection := bl_collection(
|
if (
|
||||||
|
bl_object.name
|
||||||
|
not in (
|
||||||
|
preview_collection := bl_collection(
|
||||||
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
||||||
)).objects:
|
)
|
||||||
|
).objects
|
||||||
|
):
|
||||||
preview_collection.objects.link(bl_object)
|
preview_collection.objects.link(bl_object)
|
||||||
|
|
||||||
if kind == "EMPTY" and empty_display_type is not None:
|
if kind == 'EMPTY' and empty_display_type is not None:
|
||||||
bl_object.empty_display_type = empty_display_type
|
bl_object.empty_display_type = empty_display_type
|
||||||
|
|
||||||
def hide_preview(
|
def hide_preview(
|
||||||
self,
|
self,
|
||||||
kind: typx.Literal["MESH", "EMPTY", "VOLUME"],
|
kind: typx.Literal['MESH', 'EMPTY', 'VOLUME'],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Removes the managed Blender object from the preview collection.
|
"""Removes the managed Blender object from the preview collection.
|
||||||
|
|
||||||
If it's already removed, do nothing.
|
If it's already removed, do nothing.
|
||||||
"""
|
"""
|
||||||
bl_object = self.bl_object(kind)
|
bl_object = self.bl_object(kind)
|
||||||
if bl_object.name not in (preview_collection := bl_collection(
|
if (
|
||||||
|
bl_object.name
|
||||||
|
not in (
|
||||||
|
preview_collection := bl_collection(
|
||||||
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
||||||
)).objects:
|
)
|
||||||
|
).objects
|
||||||
|
):
|
||||||
preview_collection.objects.unlink(bl_object)
|
preview_collection.objects.unlink(bl_object)
|
||||||
|
|
||||||
def bl_select(self) -> None:
|
def bl_select(self) -> None:
|
||||||
|
@ -141,7 +162,7 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
outlined in the 3D viewport.
|
outlined in the 3D viewport.
|
||||||
"""
|
"""
|
||||||
if not (bl_object := bpy.data.objects.get(self.name)):
|
if not (bl_object := bpy.data.objects.get(self.name)):
|
||||||
msg = "Managed BLObject does not exist"
|
msg = 'Managed BLObject does not exist'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
@ -152,7 +173,7 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
####################
|
####################
|
||||||
def bl_object(
|
def bl_object(
|
||||||
self,
|
self,
|
||||||
kind: typx.Literal["MESH", "EMPTY", "VOLUME"],
|
kind: typx.Literal['MESH', 'EMPTY', 'VOLUME'],
|
||||||
):
|
):
|
||||||
"""Returns the managed blender object.
|
"""Returns the managed blender object.
|
||||||
|
|
||||||
|
@ -161,21 +182,22 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
"""
|
"""
|
||||||
# Remove Object (if mismatch)
|
# Remove Object (if mismatch)
|
||||||
if (
|
if (
|
||||||
(bl_object := bpy.data.objects.get(self.name))
|
bl_object := bpy.data.objects.get(self.name)
|
||||||
and bl_object.type != kind
|
) and bl_object.type != kind:
|
||||||
):
|
|
||||||
self.free()
|
self.free()
|
||||||
|
|
||||||
# Create Object w/Appropriate Data Block
|
# Create Object w/Appropriate Data Block
|
||||||
if not (bl_object := bpy.data.objects.get(self.name)):
|
if not (bl_object := bpy.data.objects.get(self.name)):
|
||||||
if kind == "MESH":
|
if kind == 'MESH':
|
||||||
bl_data = bpy.data.meshes.new(self.bl_mesh_name)
|
bl_data = bpy.data.meshes.new(self.bl_mesh_name)
|
||||||
elif kind == "EMPTY":
|
elif kind == 'EMPTY':
|
||||||
bl_data = None
|
bl_data = None
|
||||||
elif kind == "VOLUME":
|
elif kind == 'VOLUME':
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
else:
|
else:
|
||||||
msg = f"Requested `bl_object` type {bl_object.type} is not valid"
|
msg = (
|
||||||
|
f'Requested `bl_object` type {bl_object.type} is not valid'
|
||||||
|
)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
bl_object = bpy.data.objects.new(self.name, bl_data)
|
bl_object = bpy.data.objects.new(self.name, bl_data)
|
||||||
|
@ -195,12 +217,11 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
Raises an error if the object has no mesh data.
|
Raises an error if the object has no mesh data.
|
||||||
"""
|
"""
|
||||||
if (
|
if (
|
||||||
(bl_object := bpy.data.objects.get(self.name))
|
bl_object := bpy.data.objects.get(self.name)
|
||||||
and bl_object.type == "MESH"
|
) and bl_object.type == 'MESH':
|
||||||
):
|
|
||||||
return bl_object.data
|
return bl_object.data
|
||||||
|
|
||||||
msg = f"Requested MESH data from `bl_object` of type {bl_object.type}"
|
msg = f'Requested MESH data from `bl_object` of type {bl_object.type}'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
@ -210,9 +231,8 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
triangulate: bool = False,
|
triangulate: bool = False,
|
||||||
) -> bpy.types.Mesh:
|
) -> bpy.types.Mesh:
|
||||||
if (
|
if (
|
||||||
(bl_object := bpy.data.objects.get(self.name))
|
bl_object := bpy.data.objects.get(self.name)
|
||||||
and bl_object.type == "MESH"
|
) and bl_object.type == 'MESH':
|
||||||
):
|
|
||||||
bmesh_mesh = None
|
bmesh_mesh = None
|
||||||
try:
|
try:
|
||||||
bmesh_mesh = bmesh.new()
|
bmesh_mesh = bmesh.new()
|
||||||
|
@ -230,10 +250,11 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
yield bmesh_mesh
|
yield bmesh_mesh
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if bmesh_mesh: bmesh_mesh.free()
|
if bmesh_mesh:
|
||||||
|
bmesh_mesh.free()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msg = f"Requested BMesh from `bl_object` of type {bl_object.type}"
|
msg = f'Requested BMesh from `bl_object` of type {bl_object.type}'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -245,7 +266,7 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
## TODO: Must we?
|
## TODO: Must we?
|
||||||
|
|
||||||
# Compute Evaluted + Triangulated Mesh
|
# Compute Evaluted + Triangulated Mesh
|
||||||
_mesh = bpy.data.meshes.new(name="TemporaryMesh")
|
_mesh = bpy.data.meshes.new(name='TemporaryMesh')
|
||||||
with self.mesh_as_bmesh(evaluate=True, triangulate=True) as bmesh_mesh:
|
with self.mesh_as_bmesh(evaluate=True, triangulate=True) as bmesh_mesh:
|
||||||
bmesh_mesh.to_mesh(_mesh)
|
bmesh_mesh.to_mesh(_mesh)
|
||||||
|
|
||||||
|
@ -265,8 +286,8 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
bpy.data.meshes.remove(_mesh)
|
bpy.data.meshes.remove(_mesh)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"verts": verts,
|
'verts': verts,
|
||||||
"faces": faces,
|
'faces': faces,
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -299,11 +320,11 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
"""
|
"""
|
||||||
bl_modifier = self.bl_modifier(modifier_type)
|
bl_modifier = self.bl_modifier(modifier_type)
|
||||||
|
|
||||||
if modifier_type == "NODES":
|
if modifier_type == 'NODES':
|
||||||
return {
|
return {
|
||||||
"node_group": bl_modifier.node_group,
|
'node_group': bl_modifier.node_group,
|
||||||
}
|
}
|
||||||
elif modifier_type == "ARRAY":
|
elif modifier_type == 'ARRAY':
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def s_modifier_attrs(
|
def s_modifier_attrs(
|
||||||
|
@ -313,10 +334,10 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
):
|
):
|
||||||
bl_modifier = self.bl_modifier(modifier_type)
|
bl_modifier = self.bl_modifier(modifier_type)
|
||||||
|
|
||||||
if modifier_type == "NODES":
|
if modifier_type == 'NODES':
|
||||||
if bl_modifier.node_group != modifier_attrs["node_group"]:
|
if bl_modifier.node_group != modifier_attrs['node_group']:
|
||||||
bl_modifier.node_group = modifier_attrs["node_group"]
|
bl_modifier.node_group = modifier_attrs['node_group']
|
||||||
elif modifier_type == "ARRAY":
|
elif modifier_type == 'ARRAY':
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -337,27 +358,27 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
If the GeoNodes node group doesn't match, it is changed.
|
If the GeoNodes node group doesn't match, it is changed.
|
||||||
Only differing interface values are actually changed.
|
Only differing interface values are actually changed.
|
||||||
"""
|
"""
|
||||||
bl_object = self.bl_object("MESH")
|
bl_object = self.bl_object('MESH')
|
||||||
|
|
||||||
# Get (/make) a GeoModes Modifier
|
# Get (/make) a GeoModes Modifier
|
||||||
bl_modifier = self.bl_modifier("NODES")
|
bl_modifier = self.bl_modifier('NODES')
|
||||||
|
|
||||||
# Set GeoNodes Modifier Attributes (specifically, the 'node_group')
|
# Set GeoNodes Modifier Attributes (specifically, the 'node_group')
|
||||||
self.s_modifier_attrs("NODES", {"node_group": geonodes_node_group})
|
self.s_modifier_attrs('NODES', {'node_group': geonodes_node_group})
|
||||||
|
|
||||||
# Set GeoNodes Values
|
# Set GeoNodes Values
|
||||||
modifier_altered = False
|
modifier_altered = False
|
||||||
for interface_identifier, value in (
|
for (
|
||||||
geonodes_identifier_to_value.items()
|
interface_identifier,
|
||||||
):
|
value,
|
||||||
|
) in geonodes_identifier_to_value.items():
|
||||||
if bl_modifier[interface_identifier] != value:
|
if bl_modifier[interface_identifier] != value:
|
||||||
# Quickly Determine if IDPropertyArray is Equal
|
# Quickly Determine if IDPropertyArray is Equal
|
||||||
if hasattr(
|
if (
|
||||||
bl_modifier[interface_identifier],
|
hasattr(bl_modifier[interface_identifier], 'to_list')
|
||||||
"to_list"
|
and tuple(bl_modifier[interface_identifier].to_list())
|
||||||
) and tuple(
|
== value
|
||||||
bl_modifier[interface_identifier].to_list()
|
):
|
||||||
) == value:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Quickly Determine int/float Mismatch
|
# Quickly Determine int/float Mismatch
|
||||||
|
@ -375,9 +396,8 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
if modifier_altered:
|
if modifier_altered:
|
||||||
bl_object.data.update()
|
bl_object.data.update()
|
||||||
|
|
||||||
|
# @property
|
||||||
#@property
|
# def volume(self) -> bpy.types.Volume:
|
||||||
#def volume(self) -> bpy.types.Volume:
|
|
||||||
# """Returns the object's volume data.
|
# """Returns the object's volume data.
|
||||||
#
|
#
|
||||||
# Raises an error if the object has no volume data.
|
# Raises an error if the object has no volume data.
|
||||||
|
|
|
@ -1,37 +1,38 @@
|
||||||
#from . import kitchen_sink
|
# from . import kitchen_sink
|
||||||
|
|
||||||
from . import inputs
|
from . import inputs
|
||||||
from . import outputs
|
from . import outputs
|
||||||
from . import sources
|
from . import sources
|
||||||
from . import mediums
|
from . import mediums
|
||||||
from . import structures
|
from . import structures
|
||||||
#from . import bounds
|
|
||||||
|
# from . import bounds
|
||||||
from . import monitors
|
from . import monitors
|
||||||
from . import simulations
|
from . import simulations
|
||||||
from . import utilities
|
from . import utilities
|
||||||
from . import viz
|
from . import viz
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
#*kitchen_sink.BL_REGISTER,
|
# *kitchen_sink.BL_REGISTER,
|
||||||
*inputs.BL_REGISTER,
|
*inputs.BL_REGISTER,
|
||||||
*outputs.BL_REGISTER,
|
*outputs.BL_REGISTER,
|
||||||
*sources.BL_REGISTER,
|
*sources.BL_REGISTER,
|
||||||
*mediums.BL_REGISTER,
|
*mediums.BL_REGISTER,
|
||||||
*structures.BL_REGISTER,
|
*structures.BL_REGISTER,
|
||||||
# *bounds.BL_REGISTER,
|
# *bounds.BL_REGISTER,
|
||||||
*monitors.BL_REGISTER,
|
*monitors.BL_REGISTER,
|
||||||
*simulations.BL_REGISTER,
|
*simulations.BL_REGISTER,
|
||||||
*utilities.BL_REGISTER,
|
*utilities.BL_REGISTER,
|
||||||
*viz.BL_REGISTER,
|
*viz.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
#**kitchen_sink.BL_NODES,
|
# **kitchen_sink.BL_NODES,
|
||||||
**inputs.BL_NODES,
|
**inputs.BL_NODES,
|
||||||
**outputs.BL_NODES,
|
**outputs.BL_NODES,
|
||||||
**sources.BL_NODES,
|
**sources.BL_NODES,
|
||||||
**mediums.BL_NODES,
|
**mediums.BL_NODES,
|
||||||
**structures.BL_NODES,
|
**structures.BL_NODES,
|
||||||
# **bounds.BL_NODES,
|
# **bounds.BL_NODES,
|
||||||
**monitors.BL_NODES,
|
**monitors.BL_NODES,
|
||||||
**simulations.BL_NODES,
|
**simulations.BL_NODES,
|
||||||
**utilities.BL_NODES,
|
**utilities.BL_NODES,
|
||||||
|
|
|
@ -13,11 +13,14 @@ from .. import sockets
|
||||||
CACHE: dict[str, typ.Any] = {} ## By Instance UUID
|
CACHE: dict[str, typ.Any] = {} ## By Instance UUID
|
||||||
## NOTE: CACHE does not persist between file loads.
|
## NOTE: CACHE does not persist between file loads.
|
||||||
|
|
||||||
_DEFAULT_LOOSE_SOCKET_SER = json.dumps({
|
_DEFAULT_LOOSE_SOCKET_SER = json.dumps(
|
||||||
"socket_names": [],
|
{
|
||||||
"socket_def_names": [],
|
'socket_names': [],
|
||||||
"models": [],
|
'socket_def_names': [],
|
||||||
})
|
'models': [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MaxwellSimNode(bpy.types.Node):
|
class MaxwellSimNode(bpy.types.Node):
|
||||||
# Fundamentals
|
# Fundamentals
|
||||||
|
@ -25,14 +28,14 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
bl_idname: str
|
bl_idname: str
|
||||||
use_sim_node_name: bool = False
|
use_sim_node_name: bool = False
|
||||||
bl_label: str
|
bl_label: str
|
||||||
#draw_label(self) -> str: pass
|
# draw_label(self) -> str: pass
|
||||||
|
|
||||||
# Style
|
# Style
|
||||||
bl_description: str = ""
|
bl_description: str = ''
|
||||||
|
|
||||||
#bl_width_default: float = 0.0
|
# bl_width_default: float = 0.0
|
||||||
#bl_width_min: float = 0.0
|
# bl_width_min: float = 0.0
|
||||||
#bl_width_max: float = 0.0
|
# bl_width_max: float = 0.0
|
||||||
|
|
||||||
# Sockets
|
# Sockets
|
||||||
_output_socket_methods: dict
|
_output_socket_methods: dict
|
||||||
|
@ -55,35 +58,35 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
super().__init_subclass__(**kwargs)
|
super().__init_subclass__(**kwargs)
|
||||||
|
|
||||||
# Setup Blender ID for Node
|
# Setup Blender ID for Node
|
||||||
if not hasattr(cls, "node_type"):
|
if not hasattr(cls, 'node_type'):
|
||||||
msg = f"Node class {cls} does not define 'node_type', or it is does not have the type {ct.NodeType}"
|
msg = f"Node class {cls} does not define 'node_type', or it is does not have the type {ct.NodeType}"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
cls.bl_idname = str(cls.node_type.value)
|
cls.bl_idname = str(cls.node_type.value)
|
||||||
|
|
||||||
# Setup Instance ID for Node
|
# Setup Instance ID for Node
|
||||||
cls.__annotations__["instance_id"] = bpy.props.StringProperty(
|
cls.__annotations__['instance_id'] = bpy.props.StringProperty(
|
||||||
name="Instance ID",
|
name='Instance ID',
|
||||||
description="The instance ID of a particular MaxwellSimNode instance, used to index caches",
|
description='The instance ID of a particular MaxwellSimNode instance, used to index caches',
|
||||||
default="",
|
default='',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup Name Property for Node
|
# Setup Name Property for Node
|
||||||
cls.__annotations__["sim_node_name"] = bpy.props.StringProperty(
|
cls.__annotations__['sim_node_name'] = bpy.props.StringProperty(
|
||||||
name="Sim Node Name",
|
name='Sim Node Name',
|
||||||
description="The name of a particular MaxwellSimNode node, which can be used to help identify data managed by the node",
|
description='The name of a particular MaxwellSimNode node, which can be used to help identify data managed by the node',
|
||||||
default="",
|
default='',
|
||||||
update=(lambda self, context: self.sync_sim_node_name(context))
|
update=(lambda self, context: self.sync_sim_node_name(context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup Locked Property for Node
|
# Setup Locked Property for Node
|
||||||
cls.__annotations__["locked"] = bpy.props.BoolProperty(
|
cls.__annotations__['locked'] = bpy.props.BoolProperty(
|
||||||
name="Locked State",
|
name='Locked State',
|
||||||
description="The lock-state of a particular MaxwellSimNode instance, which determines the node's user editability",
|
description="The lock-state of a particular MaxwellSimNode instance, which determines the node's user editability",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup Blender Label for Node
|
# Setup Blender Label for Node
|
||||||
if not hasattr(cls, "bl_label"):
|
if not hasattr(cls, 'bl_label'):
|
||||||
msg = f"Node class {cls} does not define 'bl_label'"
|
msg = f"Node class {cls} does not define 'bl_label'"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
@ -91,42 +94,32 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
cls._output_socket_methods = {
|
cls._output_socket_methods = {
|
||||||
method._index_by: method
|
method._index_by: method
|
||||||
for attr_name in dir(cls)
|
for attr_name in dir(cls)
|
||||||
if hasattr(
|
if hasattr(method := getattr(cls, attr_name), '_callback_type')
|
||||||
method := getattr(cls, attr_name),
|
and method._callback_type == 'computes_output_socket'
|
||||||
"_callback_type"
|
|
||||||
) and method._callback_type == "computes_output_socket"
|
|
||||||
}
|
}
|
||||||
cls._on_value_changed_methods = {
|
cls._on_value_changed_methods = {
|
||||||
method
|
method
|
||||||
for attr_name in dir(cls)
|
for attr_name in dir(cls)
|
||||||
if hasattr(
|
if hasattr(method := getattr(cls, attr_name), '_callback_type')
|
||||||
method := getattr(cls, attr_name),
|
and method._callback_type == 'on_value_changed'
|
||||||
"_callback_type"
|
|
||||||
) and method._callback_type == "on_value_changed"
|
|
||||||
}
|
}
|
||||||
cls._on_show_preview = {
|
cls._on_show_preview = {
|
||||||
method
|
method
|
||||||
for attr_name in dir(cls)
|
for attr_name in dir(cls)
|
||||||
if hasattr(
|
if hasattr(method := getattr(cls, attr_name), '_callback_type')
|
||||||
method := getattr(cls, attr_name),
|
and method._callback_type == 'on_show_preview'
|
||||||
"_callback_type"
|
|
||||||
) and method._callback_type == "on_show_preview"
|
|
||||||
}
|
}
|
||||||
cls._on_show_plot = {
|
cls._on_show_plot = {
|
||||||
method
|
method
|
||||||
for attr_name in dir(cls)
|
for attr_name in dir(cls)
|
||||||
if hasattr(
|
if hasattr(method := getattr(cls, attr_name), '_callback_type')
|
||||||
method := getattr(cls, attr_name),
|
and method._callback_type == 'on_show_plot'
|
||||||
"_callback_type"
|
|
||||||
) and method._callback_type == "on_show_plot"
|
|
||||||
}
|
}
|
||||||
cls._on_init = {
|
cls._on_init = {
|
||||||
method
|
method
|
||||||
for attr_name in dir(cls)
|
for attr_name in dir(cls)
|
||||||
if hasattr(
|
if hasattr(method := getattr(cls, attr_name), '_callback_type')
|
||||||
method := getattr(cls, attr_name),
|
and method._callback_type == 'on_init'
|
||||||
"_callback_type"
|
|
||||||
) and method._callback_type == "on_init"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup Socket Set Dropdown
|
# Setup Socket Set Dropdown
|
||||||
|
@ -135,23 +128,22 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
else:
|
else:
|
||||||
## Add Active Socket Set Enum
|
## Add Active Socket Set Enum
|
||||||
socket_set_names = (
|
socket_set_names = (
|
||||||
(_input_socket_set_names := list(cls.input_socket_sets.keys()))
|
_input_socket_set_names := list(cls.input_socket_sets.keys())
|
||||||
+ [
|
) + [
|
||||||
output_socket_set_name
|
output_socket_set_name
|
||||||
for output_socket_set_name in cls.output_socket_sets.keys()
|
for output_socket_set_name in cls.output_socket_sets.keys()
|
||||||
if output_socket_set_name not in _input_socket_set_names
|
if output_socket_set_name not in _input_socket_set_names
|
||||||
]
|
]
|
||||||
)
|
|
||||||
socket_set_ids = [
|
socket_set_ids = [
|
||||||
socket_set_name.replace(" ", "_").upper()
|
socket_set_name.replace(' ', '_').upper()
|
||||||
for socket_set_name in socket_set_names
|
for socket_set_name in socket_set_names
|
||||||
]
|
]
|
||||||
## TODO: Better deriv. of sock.set. ID, ex. ( is currently invalid.
|
## TODO: Better deriv. of sock.set. ID, ex. ( is currently invalid.
|
||||||
|
|
||||||
## Add Active Socket Set Enum
|
## Add Active Socket Set Enum
|
||||||
cls.__annotations__["active_socket_set"] = bpy.props.EnumProperty(
|
cls.__annotations__['active_socket_set'] = bpy.props.EnumProperty(
|
||||||
name="Active Socket Set",
|
name='Active Socket Set',
|
||||||
description="The active socket set",
|
description='The active socket set',
|
||||||
items=[
|
items=[
|
||||||
(
|
(
|
||||||
socket_set_name,
|
socket_set_name,
|
||||||
|
@ -164,7 +156,9 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
default=socket_set_names[0],
|
default=socket_set_names[0],
|
||||||
update=lambda self, context: self.sync_active_socket_set(context),
|
update=lambda self, context: self.sync_active_socket_set(
|
||||||
|
context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup Preset Dropdown
|
# Setup Preset Dropdown
|
||||||
|
@ -172,9 +166,9 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
cls.active_preset = None
|
cls.active_preset = None
|
||||||
else:
|
else:
|
||||||
## TODO: Check that presets are represented in a socket that is guaranteed to be always available, specifically either a static socket or ALL static socket sets.
|
## TODO: Check that presets are represented in a socket that is guaranteed to be always available, specifically either a static socket or ALL static socket sets.
|
||||||
cls.__annotations__["active_preset"] = bpy.props.EnumProperty(
|
cls.__annotations__['active_preset'] = bpy.props.EnumProperty(
|
||||||
name="Active Preset",
|
name='Active Preset',
|
||||||
description="The active preset",
|
description='The active preset',
|
||||||
items=[
|
items=[
|
||||||
(
|
(
|
||||||
preset_name,
|
preset_name,
|
||||||
|
@ -184,9 +178,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
for preset_name, preset_def in cls.presets.items()
|
for preset_name, preset_def in cls.presets.items()
|
||||||
],
|
],
|
||||||
default=list(cls.presets.keys())[0],
|
default=list(cls.presets.keys())[0],
|
||||||
update=lambda self, context: (
|
update=lambda self, context: (self.sync_active_preset()()),
|
||||||
self.sync_active_preset()()
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -194,10 +186,10 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
####################
|
####################
|
||||||
def sync_active_socket_set(self, context):
|
def sync_active_socket_set(self, context):
|
||||||
self.sync_sockets()
|
self.sync_sockets()
|
||||||
self.sync_prop("active_socket_set", context)
|
self.sync_prop('active_socket_set', context)
|
||||||
|
|
||||||
def sync_sim_node_name(self, context):
|
def sync_sim_node_name(self, context):
|
||||||
if (mobjs := CACHE[self.instance_id].get("managed_objs")) is None:
|
if (mobjs := CACHE[self.instance_id].get('managed_objs')) is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
for mobj_id, mobj in mobjs.items():
|
for mobj_id, mobj in mobjs.items():
|
||||||
|
@ -226,61 +218,60 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
## - We sync our 'sim_node_name' with all managed objects.
|
## - We sync our 'sim_node_name' with all managed objects.
|
||||||
## - (There is also a class-defined 'name_prefix' to differentiate)
|
## - (There is also a class-defined 'name_prefix' to differentiate)
|
||||||
## - See the 'sim_node_name' w/its sync function.
|
## - See the 'sim_node_name' w/its sync function.
|
||||||
if CACHE[self.instance_id].get("managed_objs") is None:
|
if CACHE[self.instance_id].get('managed_objs') is None:
|
||||||
# Initialize the Managed Object Instance Cache
|
# Initialize the Managed Object Instance Cache
|
||||||
CACHE[self.instance_id]["managed_objs"] = {}
|
CACHE[self.instance_id]['managed_objs'] = {}
|
||||||
|
|
||||||
# Fill w/Managed Objects by Name Socket
|
# Fill w/Managed Objects by Name Socket
|
||||||
for mobj_id, mobj_def in self.managed_obj_defs.items():
|
for mobj_id, mobj_def in self.managed_obj_defs.items():
|
||||||
name = mobj_def.name_prefix + self.sim_node_name
|
name = mobj_def.name_prefix + self.sim_node_name
|
||||||
CACHE[self.instance_id]["managed_objs"][mobj_id] = (
|
CACHE[self.instance_id]['managed_objs'][mobj_id] = mobj_def.mk(
|
||||||
mobj_def.mk(name)
|
name
|
||||||
)
|
)
|
||||||
|
|
||||||
return CACHE[self.instance_id]["managed_objs"]
|
return CACHE[self.instance_id]['managed_objs']
|
||||||
|
|
||||||
return CACHE[self.instance_id]["managed_objs"]
|
return CACHE[self.instance_id]['managed_objs']
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Properties
|
# - Socket Properties
|
||||||
####################
|
####################
|
||||||
def active_bl_sockets(self, direc: typx.Literal["input", "output"]):
|
def active_bl_sockets(self, direc: typx.Literal['input', 'output']):
|
||||||
return self.inputs if direc == "input" else self.outputs
|
return self.inputs if direc == 'input' else self.outputs
|
||||||
|
|
||||||
def active_socket_set_sockets(
|
def active_socket_set_sockets(
|
||||||
self,
|
self,
|
||||||
direc: typx.Literal["input", "output"],
|
direc: typx.Literal['input', 'output'],
|
||||||
) -> dict:
|
) -> dict:
|
||||||
# No Active Socket Set: Return Nothing
|
# No Active Socket Set: Return Nothing
|
||||||
if not self.active_socket_set: return {}
|
if not self.active_socket_set:
|
||||||
|
return {}
|
||||||
|
|
||||||
# Retrieve Active Socket Set Sockets
|
# Retrieve Active Socket Set Sockets
|
||||||
socket_sets = (
|
socket_sets = (
|
||||||
self.input_socket_sets
|
self.input_socket_sets
|
||||||
if direc == "input" else self.output_socket_sets
|
if direc == 'input'
|
||||||
)
|
else self.output_socket_sets
|
||||||
active_socket_set_sockets = socket_sets.get(
|
|
||||||
self.active_socket_set
|
|
||||||
)
|
)
|
||||||
|
active_socket_set_sockets = socket_sets.get(self.active_socket_set)
|
||||||
|
|
||||||
# Return Active Socket Set Sockets (if any)
|
# Return Active Socket Set Sockets (if any)
|
||||||
if not active_socket_set_sockets: return {}
|
if not active_socket_set_sockets:
|
||||||
|
return {}
|
||||||
return active_socket_set_sockets
|
return active_socket_set_sockets
|
||||||
|
|
||||||
def active_sockets(self, direc: typx.Literal["input", "output"]):
|
def active_sockets(self, direc: typx.Literal['input', 'output']):
|
||||||
static_sockets = (
|
static_sockets = (
|
||||||
self.input_sockets
|
self.input_sockets if direc == 'input' else self.output_sockets
|
||||||
if direc == "input"
|
|
||||||
else self.output_sockets
|
|
||||||
)
|
)
|
||||||
socket_sets = (
|
socket_sets = (
|
||||||
self.input_socket_sets
|
self.input_socket_sets
|
||||||
if direc == "input"
|
if direc == 'input'
|
||||||
else self.output_socket_sets
|
else self.output_socket_sets
|
||||||
)
|
)
|
||||||
loose_sockets = (
|
loose_sockets = (
|
||||||
self.loose_input_sockets
|
self.loose_input_sockets
|
||||||
if direc == "input"
|
if direc == 'input'
|
||||||
else self.loose_output_sockets
|
else self.loose_output_sockets
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -296,42 +287,50 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
# Loose Sockets
|
# Loose Sockets
|
||||||
## Only Blender props persist as instance data
|
## Only Blender props persist as instance data
|
||||||
ser_loose_input_sockets: bpy.props.StringProperty(
|
ser_loose_input_sockets: bpy.props.StringProperty(
|
||||||
name="Serialized Loose Input Sockets",
|
name='Serialized Loose Input Sockets',
|
||||||
description="JSON-serialized representation of loose input sockets.",
|
description='JSON-serialized representation of loose input sockets.',
|
||||||
default=_DEFAULT_LOOSE_SOCKET_SER,
|
default=_DEFAULT_LOOSE_SOCKET_SER,
|
||||||
)
|
)
|
||||||
ser_loose_output_sockets: bpy.props.StringProperty(
|
ser_loose_output_sockets: bpy.props.StringProperty(
|
||||||
name="Serialized Loose Input Sockets",
|
name='Serialized Loose Input Sockets',
|
||||||
description="JSON-serialized representation of loose input sockets.",
|
description='JSON-serialized representation of loose input sockets.',
|
||||||
default=_DEFAULT_LOOSE_SOCKET_SER,
|
default=_DEFAULT_LOOSE_SOCKET_SER,
|
||||||
)
|
)
|
||||||
|
|
||||||
## Internal Serialization/Deserialization Methods (yuck)
|
## Internal Serialization/Deserialization Methods (yuck)
|
||||||
def _ser_loose_sockets(self, deser: dict[str, ct.schemas.SocketDef]) -> str:
|
def _ser_loose_sockets(
|
||||||
if not all(isinstance(model, pyd.BaseModel) for model in deser.values()):
|
self, deser: dict[str, ct.schemas.SocketDef]
|
||||||
msg = "Trying to deserialize loose sockets with invalid SocketDefs (they must be `pydantic` BaseModels)."
|
) -> str:
|
||||||
|
if not all(
|
||||||
|
isinstance(model, pyd.BaseModel) for model in deser.values()
|
||||||
|
):
|
||||||
|
msg = 'Trying to deserialize loose sockets with invalid SocketDefs (they must be `pydantic` BaseModels).'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
return json.dumps({
|
return json.dumps(
|
||||||
"socket_names": list(deser.keys()),
|
{
|
||||||
"socket_def_names": [
|
'socket_names': list(deser.keys()),
|
||||||
model.__class__.__name__
|
'socket_def_names': [
|
||||||
for model in deser.values()
|
model.__class__.__name__ for model in deser.values()
|
||||||
],
|
],
|
||||||
"models": [
|
'models': [
|
||||||
model.model_dump()
|
model.model_dump()
|
||||||
for model in deser.values()
|
for model in deser.values()
|
||||||
if isinstance(model, pyd.BaseModel)
|
if isinstance(model, pyd.BaseModel)
|
||||||
],
|
],
|
||||||
}) ## Big reliance on order-preservation of dicts here.)
|
}
|
||||||
def _deser_loose_sockets(self, ser: str) -> dict[str, ct.schemas.SocketDef]:
|
) ## Big reliance on order-preservation of dicts here.)
|
||||||
|
|
||||||
|
def _deser_loose_sockets(
|
||||||
|
self, ser: str
|
||||||
|
) -> dict[str, ct.schemas.SocketDef]:
|
||||||
semi_deser = json.loads(ser)
|
semi_deser = json.loads(ser)
|
||||||
return {
|
return {
|
||||||
socket_name: getattr(sockets, socket_def_name)(**model_kwargs)
|
socket_name: getattr(sockets, socket_def_name)(**model_kwargs)
|
||||||
for socket_name, socket_def_name, model_kwargs in zip(
|
for socket_name, socket_def_name, model_kwargs in zip(
|
||||||
semi_deser["socket_names"],
|
semi_deser['socket_names'],
|
||||||
semi_deser["socket_def_names"],
|
semi_deser['socket_def_names'],
|
||||||
semi_deser["models"],
|
semi_deser['models'],
|
||||||
)
|
)
|
||||||
if hasattr(sockets, socket_def_name)
|
if hasattr(sockets, socket_def_name)
|
||||||
}
|
}
|
||||||
|
@ -339,17 +338,22 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
@property
|
@property
|
||||||
def loose_input_sockets(self) -> dict[str, ct.schemas.SocketDef]:
|
def loose_input_sockets(self) -> dict[str, ct.schemas.SocketDef]:
|
||||||
return self._deser_loose_sockets(self.ser_loose_input_sockets)
|
return self._deser_loose_sockets(self.ser_loose_input_sockets)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def loose_output_sockets(self) -> dict[str, ct.schemas.SocketDef]:
|
def loose_output_sockets(self) -> dict[str, ct.schemas.SocketDef]:
|
||||||
return self._deser_loose_sockets(self.ser_loose_output_sockets)
|
return self._deser_loose_sockets(self.ser_loose_output_sockets)
|
||||||
|
|
||||||
## TODO: Some caching may play a role if this is all too slow.
|
## TODO: Some caching may play a role if this is all too slow.
|
||||||
|
|
||||||
@loose_input_sockets.setter
|
@loose_input_sockets.setter
|
||||||
def loose_input_sockets(
|
def loose_input_sockets(
|
||||||
self, value: dict[str, ct.schemas.SocketDef],
|
self,
|
||||||
|
value: dict[str, ct.schemas.SocketDef],
|
||||||
) -> None:
|
) -> None:
|
||||||
if not value: self.ser_loose_input_sockets = _DEFAULT_LOOSE_SOCKET_SER
|
if not value:
|
||||||
else: self.ser_loose_input_sockets = self._ser_loose_sockets(value)
|
self.ser_loose_input_sockets = _DEFAULT_LOOSE_SOCKET_SER
|
||||||
|
else:
|
||||||
|
self.ser_loose_input_sockets = self._ser_loose_sockets(value)
|
||||||
|
|
||||||
# Synchronize Sockets
|
# Synchronize Sockets
|
||||||
self.sync_sockets()
|
self.sync_sockets()
|
||||||
|
@ -357,10 +361,13 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
|
|
||||||
@loose_output_sockets.setter
|
@loose_output_sockets.setter
|
||||||
def loose_output_sockets(
|
def loose_output_sockets(
|
||||||
self, value: dict[str, ct.schemas.SocketDef],
|
self,
|
||||||
|
value: dict[str, ct.schemas.SocketDef],
|
||||||
) -> None:
|
) -> None:
|
||||||
if not value: self.ser_loose_output_sockets = _DEFAULT_LOOSE_SOCKET_SER
|
if not value:
|
||||||
else: self.ser_loose_output_sockets = self._ser_loose_sockets(value)
|
self.ser_loose_output_sockets = _DEFAULT_LOOSE_SOCKET_SER
|
||||||
|
else:
|
||||||
|
self.ser_loose_output_sockets = self._ser_loose_sockets(value)
|
||||||
|
|
||||||
# Synchronize Sockets
|
# Synchronize Sockets
|
||||||
self.sync_sockets()
|
self.sync_sockets()
|
||||||
|
@ -374,7 +381,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
|
|
||||||
**NOTE**: Socket names must be unique within direction, active socket set, and loose socket set.
|
**NOTE**: Socket names must be unique within direction, active socket set, and loose socket set.
|
||||||
"""
|
"""
|
||||||
for direc in ["input", "output"]:
|
for direc in ['input', 'output']:
|
||||||
sockets = self.active_sockets(direc)
|
sockets = self.active_sockets(direc)
|
||||||
bl_sockets = self.active_bl_sockets(direc)
|
bl_sockets = self.active_bl_sockets(direc)
|
||||||
|
|
||||||
|
@ -394,7 +401,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
|
|
||||||
Existing sockets within the given direction are not re-created.
|
Existing sockets within the given direction are not re-created.
|
||||||
"""
|
"""
|
||||||
for direc in ["input", "output"]:
|
for direc in ['input', 'output']:
|
||||||
sockets = self.active_sockets(direc)
|
sockets = self.active_sockets(direc)
|
||||||
bl_sockets = self.active_bl_sockets(direc)
|
bl_sockets = self.active_bl_sockets(direc)
|
||||||
|
|
||||||
|
@ -402,7 +409,8 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
created_sockets = {}
|
created_sockets = {}
|
||||||
for socket_name, socket_def in sockets.items():
|
for socket_name, socket_def in sockets.items():
|
||||||
# Skip Existing Sockets
|
# Skip Existing Sockets
|
||||||
if socket_name in bl_sockets: continue
|
if socket_name in bl_sockets:
|
||||||
|
continue
|
||||||
|
|
||||||
# Create BL Socket from Socket
|
# Create BL Socket from Socket
|
||||||
bl_socket = bl_sockets.new(
|
bl_socket = bl_sockets.new(
|
||||||
|
@ -440,12 +448,12 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
preset-defined input sockets.
|
preset-defined input sockets.
|
||||||
"""
|
"""
|
||||||
if not (preset_def := self.presets.get(self.active_preset)):
|
if not (preset_def := self.presets.get(self.active_preset)):
|
||||||
msg = f"Tried to apply active preset, but the active preset ({self.active_preset}) is not in presets ({self.presets})"
|
msg = f'Tried to apply active preset, but the active preset ({self.active_preset}) is not in presets ({self.presets})'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
for socket_name, socket_value in preset_def.values.items():
|
for socket_name, socket_value in preset_def.values.items():
|
||||||
if not (bl_socket := self.inputs.get(socket_name)):
|
if not (bl_socket := self.inputs.get(socket_name)):
|
||||||
msg = f"Tried to set preset socket/value pair ({socket_name}={socket_value}), but socket is not in active input sockets ({self.inputs})"
|
msg = f'Tried to set preset socket/value pair ({socket_name}={socket_value}), but socket is not in active input sockets ({self.inputs})'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
bl_socket.value = socket_value
|
bl_socket.value = socket_value
|
||||||
|
@ -459,20 +467,21 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
layout: bpy.types.UILayout,
|
layout: bpy.types.UILayout,
|
||||||
) -> None:
|
) -> None:
|
||||||
if self.locked: layout.enabled = False
|
if self.locked:
|
||||||
|
layout.enabled = False
|
||||||
|
|
||||||
if self.active_preset:
|
if self.active_preset:
|
||||||
layout.prop(self, "active_preset", text="")
|
layout.prop(self, 'active_preset', text='')
|
||||||
|
|
||||||
if self.active_socket_set:
|
if self.active_socket_set:
|
||||||
layout.prop(self, "active_socket_set", text="")
|
layout.prop(self, 'active_socket_set', text='')
|
||||||
|
|
||||||
# Draw Name
|
# Draw Name
|
||||||
col = layout.column(align=False)
|
col = layout.column(align=False)
|
||||||
if self.use_sim_node_name:
|
if self.use_sim_node_name:
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.label(text="", icon="FILE_TEXT")
|
row.label(text='', icon='FILE_TEXT')
|
||||||
row.prop(self, "sim_node_name", text="")
|
row.prop(self, 'sim_node_name', text='')
|
||||||
|
|
||||||
# Draw Name
|
# Draw Name
|
||||||
self.draw_props(context, col)
|
self.draw_props(context, col)
|
||||||
|
@ -480,15 +489,23 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
self.draw_info(context, col)
|
self.draw_info(context, col)
|
||||||
|
|
||||||
## TODO: Managed Operators instead of this shit
|
## TODO: Managed Operators instead of this shit
|
||||||
def draw_props(self, context, layout): pass
|
def draw_props(self, context, layout):
|
||||||
def draw_operators(self, context, layout): pass
|
pass
|
||||||
def draw_info(self, context, layout): pass
|
|
||||||
|
def draw_operators(self, context, layout):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw_info(self, context, layout):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw_buttons_ext(self, context, layout):
|
||||||
|
pass
|
||||||
|
|
||||||
def draw_buttons_ext(self, context, layout): pass
|
|
||||||
## TODO: Side panel buttons for fanciness.
|
## TODO: Side panel buttons for fanciness.
|
||||||
|
|
||||||
def draw_plot_settings(self, context, layout):
|
def draw_plot_settings(self, context, layout):
|
||||||
if self.locked: layout.enabled = False
|
if self.locked:
|
||||||
|
layout.enabled = False
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Data Flow
|
# - Data Flow
|
||||||
|
@ -507,8 +524,8 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
"""
|
"""
|
||||||
if not (bl_socket := self.inputs.get(input_socket_name)):
|
if not (bl_socket := self.inputs.get(input_socket_name)):
|
||||||
return None
|
return None
|
||||||
#msg = f"Input socket name {input_socket_name} is not an active input sockets."
|
# msg = f"Input socket name {input_socket_name} is not an active input sockets."
|
||||||
#raise ValueError(msg)
|
# raise ValueError(msg)
|
||||||
|
|
||||||
return bl_socket.compute_data(kind=kind)
|
return bl_socket.compute_data(kind=kind)
|
||||||
|
|
||||||
|
@ -535,7 +552,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
(output_socket_name, kind)
|
(output_socket_name, kind)
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
msg = f"No output method for ({output_socket_name}, {str(kind.value)}"
|
msg = f'No output method for ({output_socket_name}, {str(kind.value)}'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
return output_socket_method(self)
|
return output_socket_method(self)
|
||||||
|
@ -544,17 +561,22 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
# - Action Chain
|
# - Action Chain
|
||||||
####################
|
####################
|
||||||
def sync_prop(self, prop_name: str, context: bpy.types.Context):
|
def sync_prop(self, prop_name: str, context: bpy.types.Context):
|
||||||
"""Called when a property has been updated.
|
"""Called when a property has been updated."""
|
||||||
"""
|
|
||||||
if not hasattr(self, prop_name):
|
if not hasattr(self, prop_name):
|
||||||
msg = f"Property {prop_name} not defined on socket {self}"
|
msg = f'Property {prop_name} not defined on socket {self}'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.trigger_action("value_changed", prop_name=prop_name)
|
self.trigger_action('value_changed', prop_name=prop_name)
|
||||||
|
|
||||||
def trigger_action(
|
def trigger_action(
|
||||||
self,
|
self,
|
||||||
action: typx.Literal["enable_lock", "disable_lock", "value_changed", "show_preview", "show_plot"],
|
action: typx.Literal[
|
||||||
|
'enable_lock',
|
||||||
|
'disable_lock',
|
||||||
|
'value_changed',
|
||||||
|
'show_preview',
|
||||||
|
'show_plot',
|
||||||
|
],
|
||||||
socket_name: ct.SocketName | None = None,
|
socket_name: ct.SocketName | None = None,
|
||||||
prop_name: ct.SocketName | None = None,
|
prop_name: ct.SocketName | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -564,63 +586,69 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
output socket method that implicitly depends on this input socket.
|
output socket method that implicitly depends on this input socket.
|
||||||
"""
|
"""
|
||||||
# Forwards Chains
|
# Forwards Chains
|
||||||
if action == "value_changed":
|
if action == 'value_changed':
|
||||||
# Run User Callbacks
|
# Run User Callbacks
|
||||||
## Careful with these, they run BEFORE propagation...
|
## Careful with these, they run BEFORE propagation...
|
||||||
## ...because later-chain methods may rely on the results of this.
|
## ...because later-chain methods may rely on the results of this.
|
||||||
for method in self._on_value_changed_methods:
|
for method in self._on_value_changed_methods:
|
||||||
if (
|
if (
|
||||||
|
(
|
||||||
socket_name
|
socket_name
|
||||||
and socket_name in method._extra_data.get("changed_sockets")
|
and socket_name
|
||||||
) or (
|
in method._extra_data.get('changed_sockets')
|
||||||
|
)
|
||||||
|
or (
|
||||||
prop_name
|
prop_name
|
||||||
and prop_name in method._extra_data.get("changed_props")
|
and prop_name
|
||||||
) or (
|
in method._extra_data.get('changed_props')
|
||||||
|
)
|
||||||
|
or (
|
||||||
socket_name
|
socket_name
|
||||||
and method._extra_data["changed_loose_input"]
|
and method._extra_data['changed_loose_input']
|
||||||
and socket_name in self.loose_input_sockets
|
and socket_name in self.loose_input_sockets
|
||||||
|
)
|
||||||
):
|
):
|
||||||
method(self)
|
method(self)
|
||||||
|
|
||||||
# Propagate via Output Sockets
|
# Propagate via Output Sockets
|
||||||
for bl_socket in self.active_bl_sockets("output"):
|
for bl_socket in self.active_bl_sockets('output'):
|
||||||
bl_socket.trigger_action(action)
|
bl_socket.trigger_action(action)
|
||||||
|
|
||||||
# Backwards Chains
|
# Backwards Chains
|
||||||
elif action == "enable_lock":
|
elif action == 'enable_lock':
|
||||||
self.locked = True
|
self.locked = True
|
||||||
|
|
||||||
## Propagate via Input Sockets
|
## Propagate via Input Sockets
|
||||||
for bl_socket in self.active_bl_sockets("input"):
|
for bl_socket in self.active_bl_sockets('input'):
|
||||||
bl_socket.trigger_action(action)
|
bl_socket.trigger_action(action)
|
||||||
|
|
||||||
elif action == "disable_lock":
|
elif action == 'disable_lock':
|
||||||
self.locked = False
|
self.locked = False
|
||||||
|
|
||||||
## Propagate via Input Sockets
|
## Propagate via Input Sockets
|
||||||
for bl_socket in self.active_bl_sockets("input"):
|
for bl_socket in self.active_bl_sockets('input'):
|
||||||
bl_socket.trigger_action(action)
|
bl_socket.trigger_action(action)
|
||||||
|
|
||||||
elif action == "show_preview":
|
elif action == 'show_preview':
|
||||||
# Run User Callbacks
|
# Run User Callbacks
|
||||||
for method in self._on_show_preview:
|
for method in self._on_show_preview:
|
||||||
method(self)
|
method(self)
|
||||||
|
|
||||||
## Propagate via Input Sockets
|
## Propagate via Input Sockets
|
||||||
for bl_socket in self.active_bl_sockets("input"):
|
for bl_socket in self.active_bl_sockets('input'):
|
||||||
bl_socket.trigger_action(action)
|
bl_socket.trigger_action(action)
|
||||||
|
|
||||||
elif action == "show_plot":
|
elif action == 'show_plot':
|
||||||
# Run User Callbacks
|
# Run User Callbacks
|
||||||
## These shouldn't change any data, BUT...
|
## These shouldn't change any data, BUT...
|
||||||
## ...because they can stop propagation, they should go first.
|
## ...because they can stop propagation, they should go first.
|
||||||
for method in self._on_show_plot:
|
for method in self._on_show_plot:
|
||||||
method(self)
|
method(self)
|
||||||
if method._extra_data["stop_propagation"]:
|
if method._extra_data['stop_propagation']:
|
||||||
return
|
return
|
||||||
|
|
||||||
## Propagate via Input Sockets
|
## Propagate via Input Sockets
|
||||||
for bl_socket in self.active_bl_sockets("input"):
|
for bl_socket in self.active_bl_sockets('input'):
|
||||||
bl_socket.trigger_action(action)
|
bl_socket.trigger_action(action)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -636,8 +664,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
return node_tree.bl_idname == ct.TreeType.MaxwellSim.value
|
return node_tree.bl_idname == ct.TreeType.MaxwellSim.value
|
||||||
|
|
||||||
def init(self, context: bpy.types.Context):
|
def init(self, context: bpy.types.Context):
|
||||||
"""Run (by Blender) on node creation.
|
"""Run (by Blender) on node creation."""
|
||||||
"""
|
|
||||||
global CACHE
|
global CACHE
|
||||||
|
|
||||||
# Initialize Cache and Instance ID
|
# Initialize Cache and Instance ID
|
||||||
|
@ -652,7 +679,8 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
self.sync_sockets()
|
self.sync_sockets()
|
||||||
|
|
||||||
# Apply Default Preset
|
# Apply Default Preset
|
||||||
if self.active_preset: self.sync_active_preset()
|
if self.active_preset:
|
||||||
|
self.sync_active_preset()
|
||||||
|
|
||||||
# Callbacks
|
# Callbacks
|
||||||
for method in self._on_init:
|
for method in self._on_init:
|
||||||
|
@ -662,8 +690,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def free(self) -> None:
|
def free(self) -> None:
|
||||||
"""Run (by Blender) when deleting the node.
|
"""Run (by Blender) when deleting the node."""
|
||||||
"""
|
|
||||||
global CACHE
|
global CACHE
|
||||||
if not CACHE.get(self.instance_id):
|
if not CACHE.get(self.instance_id):
|
||||||
CACHE[self.instance_id] = {}
|
CACHE[self.instance_id] = {}
|
||||||
|
@ -679,7 +706,7 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
bl_socket.is_linked and bl_socket.locked
|
bl_socket.is_linked and bl_socket.locked
|
||||||
for bl_socket in self.inputs.values()
|
for bl_socket in self.inputs.values()
|
||||||
):
|
):
|
||||||
self.trigger_action("disable_lock")
|
self.trigger_action('disable_lock')
|
||||||
|
|
||||||
# Free Managed Objects
|
# Free Managed Objects
|
||||||
for managed_obj in self.managed_objs.values():
|
for managed_obj in self.managed_objs.values():
|
||||||
|
@ -696,18 +723,16 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
del CACHE[self.instance_id]
|
del CACHE[self.instance_id]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def chain_event_decorator(
|
def chain_event_decorator(
|
||||||
callback_type: typ.Literal[
|
callback_type: typ.Literal[
|
||||||
"computes_output_socket",
|
'computes_output_socket',
|
||||||
"on_value_changed",
|
'on_value_changed',
|
||||||
"on_show_preview",
|
'on_show_preview',
|
||||||
"on_show_plot",
|
'on_show_plot',
|
||||||
"on_init",
|
'on_init',
|
||||||
],
|
],
|
||||||
index_by: typ.Any | None = None,
|
index_by: typ.Any | None = None,
|
||||||
extra_data: dict[str, typ.Any] | None = None,
|
extra_data: dict[str, typ.Any] | None = None,
|
||||||
|
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
input_sockets: set[str] = set(), ## For now, presume
|
input_sockets: set[str] = set(), ## For now, presume
|
||||||
output_sockets: set[str] = set(), ## For now, presume
|
output_sockets: set[str] = set(), ## For now, presume
|
||||||
|
@ -715,8 +740,7 @@ def chain_event_decorator(
|
||||||
loose_output_sockets: bool = False,
|
loose_output_sockets: bool = False,
|
||||||
props: set[str] = set(),
|
props: set[str] = set(),
|
||||||
managed_objs: set[str] = set(),
|
managed_objs: set[str] = set(),
|
||||||
|
req_params: set[str] = set(),
|
||||||
req_params: set[str] = set()
|
|
||||||
):
|
):
|
||||||
def decorator(method: typ.Callable) -> typ.Callable:
|
def decorator(method: typ.Callable) -> typ.Callable:
|
||||||
# Check Function Signature Validity
|
# Check Function Signature Validity
|
||||||
|
@ -724,11 +748,11 @@ def chain_event_decorator(
|
||||||
|
|
||||||
## Too Little
|
## Too Little
|
||||||
if func_sig != req_params and func_sig.issubset(req_params):
|
if func_sig != req_params and func_sig.issubset(req_params):
|
||||||
msg = f"Decorated method {method.__name__} is missing arguments {req_params - func_sig}"
|
msg = f'Decorated method {method.__name__} is missing arguments {req_params - func_sig}'
|
||||||
|
|
||||||
## Too Much
|
## Too Much
|
||||||
if func_sig != req_params and func_sig.issuperset(req_params):
|
if func_sig != req_params and func_sig.issuperset(req_params):
|
||||||
msg = f"Decorated method {method.__name__} has superfluous arguments {func_sig - req_params}"
|
msg = f'Decorated method {method.__name__} has superfluous arguments {func_sig - req_params}'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
## Just Right :)
|
## Just Right :)
|
||||||
|
@ -743,7 +767,9 @@ def chain_event_decorator(
|
||||||
## Add Input Sockets
|
## Add Input Sockets
|
||||||
if input_sockets:
|
if input_sockets:
|
||||||
_input_sockets = {
|
_input_sockets = {
|
||||||
input_socket_name: node._compute_input(input_socket_name, kind)
|
input_socket_name: node._compute_input(
|
||||||
|
input_socket_name, kind
|
||||||
|
)
|
||||||
for input_socket_name in input_sockets
|
for input_socket_name in input_sockets
|
||||||
}
|
}
|
||||||
method_kw_args |= dict(input_sockets=_input_sockets)
|
method_kw_args |= dict(input_sockets=_input_sockets)
|
||||||
|
@ -751,7 +777,9 @@ def chain_event_decorator(
|
||||||
## Add Output Sockets
|
## Add Output Sockets
|
||||||
if output_sockets:
|
if output_sockets:
|
||||||
_output_sockets = {
|
_output_sockets = {
|
||||||
output_socket_name: node.compute_output(output_socket_name, kind)
|
output_socket_name: node.compute_output(
|
||||||
|
output_socket_name, kind
|
||||||
|
)
|
||||||
for output_socket_name in output_sockets
|
for output_socket_name in output_sockets
|
||||||
}
|
}
|
||||||
method_kw_args |= dict(output_sockets=_output_sockets)
|
method_kw_args |= dict(output_sockets=_output_sockets)
|
||||||
|
@ -759,7 +787,9 @@ def chain_event_decorator(
|
||||||
## Add Loose Sockets
|
## Add Loose Sockets
|
||||||
if loose_input_sockets:
|
if loose_input_sockets:
|
||||||
_loose_input_sockets = {
|
_loose_input_sockets = {
|
||||||
input_socket_name: node._compute_input(input_socket_name, kind)
|
input_socket_name: node._compute_input(
|
||||||
|
input_socket_name, kind
|
||||||
|
)
|
||||||
for input_socket_name in node.loose_input_sockets
|
for input_socket_name in node.loose_input_sockets
|
||||||
}
|
}
|
||||||
method_kw_args |= dict(
|
method_kw_args |= dict(
|
||||||
|
@ -767,7 +797,9 @@ def chain_event_decorator(
|
||||||
)
|
)
|
||||||
if loose_output_sockets:
|
if loose_output_sockets:
|
||||||
_loose_output_sockets = {
|
_loose_output_sockets = {
|
||||||
output_socket_name: node.compute_output(output_socket_name, kind)
|
output_socket_name: node.compute_output(
|
||||||
|
output_socket_name, kind
|
||||||
|
)
|
||||||
for output_socket_name in node.loose_output_sockets
|
for output_socket_name in node.loose_output_sockets
|
||||||
}
|
}
|
||||||
method_kw_args |= dict(
|
method_kw_args |= dict(
|
||||||
|
@ -777,8 +809,7 @@ def chain_event_decorator(
|
||||||
## Add Props
|
## Add Props
|
||||||
if props:
|
if props:
|
||||||
_props = {
|
_props = {
|
||||||
prop_name: getattr(node, prop_name)
|
prop_name: getattr(node, prop_name) for prop_name in props
|
||||||
for prop_name in props
|
|
||||||
}
|
}
|
||||||
method_kw_args |= dict(props=_props)
|
method_kw_args |= dict(props=_props)
|
||||||
|
|
||||||
|
@ -804,6 +835,7 @@ def chain_event_decorator(
|
||||||
decorated._extra_data = extra_data
|
decorated._extra_data = extra_data
|
||||||
|
|
||||||
return decorated
|
return decorated
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,16 +873,15 @@ def computes_output_socket(
|
||||||
and returns a new output-socket-computing method, now annotated
|
and returns a new output-socket-computing method, now annotated
|
||||||
and discoverable by the `MaxwellSimTreeNode`.
|
and discoverable by the `MaxwellSimTreeNode`.
|
||||||
"""
|
"""
|
||||||
req_params = {"self"} | (
|
req_params = (
|
||||||
{"input_sockets"} if input_sockets else set()
|
{'self'}
|
||||||
) | (
|
| ({'input_sockets'} if input_sockets else set())
|
||||||
{"props"} if props else set()
|
| ({'props'} if props else set())
|
||||||
) | (
|
| ({'managed_objs'} if managed_objs else set())
|
||||||
{"managed_objs"} if managed_objs else set()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="computes_output_socket",
|
callback_type='computes_output_socket',
|
||||||
index_by=(output_socket_name, kind),
|
index_by=(output_socket_name, kind),
|
||||||
kind=kind,
|
kind=kind,
|
||||||
input_sockets=input_sockets,
|
input_sockets=input_sockets,
|
||||||
|
@ -860,7 +891,6 @@ def computes_output_socket(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Decorator: On Show Preview
|
# - Decorator: On Show Preview
|
||||||
####################
|
####################
|
||||||
|
@ -868,40 +898,42 @@ def on_value_changed(
|
||||||
socket_name: set[ct.SocketName] | ct.SocketName | None = None,
|
socket_name: set[ct.SocketName] | ct.SocketName | None = None,
|
||||||
prop_name: set[str] | str | None = None,
|
prop_name: set[str] | str | None = None,
|
||||||
any_loose_input_socket: bool = False,
|
any_loose_input_socket: bool = False,
|
||||||
|
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
input_sockets: set[str] = set(),
|
input_sockets: set[str] = set(),
|
||||||
props: set[str] = set(),
|
props: set[str] = set(),
|
||||||
managed_objs: set[str] = set(),
|
managed_objs: set[str] = set(),
|
||||||
):
|
):
|
||||||
if sum([
|
if (
|
||||||
|
sum(
|
||||||
|
[
|
||||||
int(socket_name is not None),
|
int(socket_name is not None),
|
||||||
int(prop_name is not None),
|
int(prop_name is not None),
|
||||||
int(any_loose_input_socket),
|
int(any_loose_input_socket),
|
||||||
]) > 1:
|
]
|
||||||
msg = "Define only one of socket_name, prop_name or any_loose_input_socket"
|
)
|
||||||
|
> 1
|
||||||
|
):
|
||||||
|
msg = 'Define only one of socket_name, prop_name or any_loose_input_socket'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
req_params = {"self"} | (
|
req_params = (
|
||||||
{"input_sockets"} if input_sockets else set()
|
{'self'}
|
||||||
) | (
|
| ({'input_sockets'} if input_sockets else set())
|
||||||
{"loose_input_sockets"} if any_loose_input_socket else set()
|
| ({'loose_input_sockets'} if any_loose_input_socket else set())
|
||||||
) | (
|
| ({'props'} if props else set())
|
||||||
{"props"} if props else set()
|
| ({'managed_objs'} if managed_objs else set())
|
||||||
) | (
|
|
||||||
{"managed_objs"} if managed_objs else set()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="on_value_changed",
|
callback_type='on_value_changed',
|
||||||
extra_data={
|
extra_data={
|
||||||
"changed_sockets": (
|
'changed_sockets': (
|
||||||
socket_name if isinstance(socket_name, set) else {socket_name}
|
socket_name if isinstance(socket_name, set) else {socket_name}
|
||||||
),
|
),
|
||||||
"changed_props": (
|
'changed_props': (
|
||||||
prop_name if isinstance(prop_name, set) else {prop_name}
|
prop_name if isinstance(prop_name, set) else {prop_name}
|
||||||
),
|
),
|
||||||
"changed_loose_input": any_loose_input_socket,
|
'changed_loose_input': any_loose_input_socket,
|
||||||
},
|
},
|
||||||
kind=kind,
|
kind=kind,
|
||||||
input_sockets=input_sockets,
|
input_sockets=input_sockets,
|
||||||
|
@ -911,6 +943,7 @@ def on_value_changed(
|
||||||
req_params=req_params,
|
req_params=req_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
input_sockets: set[str] = set(), ## For now, presume only same kind
|
input_sockets: set[str] = set(), ## For now, presume only same kind
|
||||||
|
@ -918,18 +951,16 @@ def on_show_preview(
|
||||||
props: set[str] = set(),
|
props: set[str] = set(),
|
||||||
managed_objs: set[str] = set(),
|
managed_objs: set[str] = set(),
|
||||||
):
|
):
|
||||||
req_params = {"self"} | (
|
req_params = (
|
||||||
{"input_sockets"} if input_sockets else set()
|
{'self'}
|
||||||
) | (
|
| ({'input_sockets'} if input_sockets else set())
|
||||||
{"output_sockets"} if output_sockets else set()
|
| ({'output_sockets'} if output_sockets else set())
|
||||||
) | (
|
| ({'props'} if props else set())
|
||||||
{"props"} if props else set()
|
| ({'managed_objs'} if managed_objs else set())
|
||||||
) | (
|
|
||||||
{"managed_objs"} if managed_objs else set()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="on_show_preview",
|
callback_type='on_show_preview',
|
||||||
kind=kind,
|
kind=kind,
|
||||||
input_sockets=input_sockets,
|
input_sockets=input_sockets,
|
||||||
output_sockets=output_sockets,
|
output_sockets=output_sockets,
|
||||||
|
@ -938,6 +969,7 @@ def on_show_preview(
|
||||||
req_params=req_params,
|
req_params=req_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
input_sockets: set[str] = set(),
|
input_sockets: set[str] = set(),
|
||||||
|
@ -946,20 +978,18 @@ def on_show_plot(
|
||||||
managed_objs: set[str] = set(),
|
managed_objs: set[str] = set(),
|
||||||
stop_propagation: bool = False,
|
stop_propagation: bool = False,
|
||||||
):
|
):
|
||||||
req_params = {"self"} | (
|
req_params = (
|
||||||
{"input_sockets"} if input_sockets else set()
|
{'self'}
|
||||||
) | (
|
| ({'input_sockets'} if input_sockets else set())
|
||||||
{"output_sockets"} if output_sockets else set()
|
| ({'output_sockets'} if output_sockets else set())
|
||||||
) | (
|
| ({'props'} if props else set())
|
||||||
{"props"} if props else set()
|
| ({'managed_objs'} if managed_objs else set())
|
||||||
) | (
|
|
||||||
{"managed_objs"} if managed_objs else set()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="on_show_plot",
|
callback_type='on_show_plot',
|
||||||
extra_data={
|
extra_data={
|
||||||
"stop_propagation": stop_propagation,
|
'stop_propagation': stop_propagation,
|
||||||
},
|
},
|
||||||
kind=kind,
|
kind=kind,
|
||||||
input_sockets=input_sockets,
|
input_sockets=input_sockets,
|
||||||
|
@ -969,6 +999,7 @@ def on_show_plot(
|
||||||
req_params=req_params,
|
req_params=req_params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def on_init(
|
def on_init(
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
input_sockets: set[str] = set(),
|
input_sockets: set[str] = set(),
|
||||||
|
@ -976,18 +1007,16 @@ def on_init(
|
||||||
props: set[str] = set(),
|
props: set[str] = set(),
|
||||||
managed_objs: set[str] = set(),
|
managed_objs: set[str] = set(),
|
||||||
):
|
):
|
||||||
req_params = {"self"} | (
|
req_params = (
|
||||||
{"input_sockets"} if input_sockets else set()
|
{'self'}
|
||||||
) | (
|
| ({'input_sockets'} if input_sockets else set())
|
||||||
{"output_sockets"} if output_sockets else set()
|
| ({'output_sockets'} if output_sockets else set())
|
||||||
) | (
|
| ({'props'} if props else set())
|
||||||
{"props"} if props else set()
|
| ({'managed_objs'} if managed_objs else set())
|
||||||
) | (
|
|
||||||
{"managed_objs"} if managed_objs else set()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="on_init",
|
callback_type='on_init',
|
||||||
kind=kind,
|
kind=kind,
|
||||||
input_sockets=input_sockets,
|
input_sockets=input_sockets,
|
||||||
output_sockets=output_sockets,
|
output_sockets=output_sockets,
|
||||||
|
|
|
@ -6,40 +6,40 @@ from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class BoundCondsNode(base.MaxwellSimNode):
|
class BoundCondsNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.BoundConds
|
node_type = ct.NodeType.BoundConds
|
||||||
bl_label = "Bound Box"
|
bl_label = 'Bound Box'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"+X": sockets.MaxwellBoundCondSocketDef(),
|
'+X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
"-X": sockets.MaxwellBoundCondSocketDef(),
|
'-X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
"+Y": sockets.MaxwellBoundCondSocketDef(),
|
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
"-Y": sockets.MaxwellBoundCondSocketDef(),
|
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
"+Z": sockets.MaxwellBoundCondSocketDef(),
|
'+Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
"-Z": sockets.MaxwellBoundCondSocketDef(),
|
'-Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"BCs": sockets.MaxwellBoundCondsSocketDef(),
|
'BCs': sockets.MaxwellBoundCondsSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"BCs",
|
'BCs', input_sockets={'+X', '-X', '+Y', '-Y', '+Z', '-Z'}
|
||||||
input_sockets={"+X", "-X", "+Y", "-Y", "+Z", "-Z"}
|
|
||||||
)
|
)
|
||||||
def compute_simulation(self, input_sockets) -> td.BoundarySpec:
|
def compute_simulation(self, input_sockets) -> td.BoundarySpec:
|
||||||
x_pos = input_sockets["+X"]
|
x_pos = input_sockets['+X']
|
||||||
x_neg = input_sockets["-X"]
|
x_neg = input_sockets['-X']
|
||||||
y_pos = input_sockets["+Y"]
|
y_pos = input_sockets['+Y']
|
||||||
y_neg = input_sockets["-Y"]
|
y_neg = input_sockets['-Y']
|
||||||
z_pos = input_sockets["+Z"]
|
z_pos = input_sockets['+Z']
|
||||||
z_neg = input_sockets["-Z"]
|
z_neg = input_sockets['-Z']
|
||||||
|
|
||||||
return td.BoundarySpec(
|
return td.BoundarySpec(
|
||||||
x=td.Boundary(
|
x=td.Boundary(
|
||||||
|
@ -57,15 +57,10 @@ class BoundCondsNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
BoundCondsNode,
|
BoundCondsNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.BoundConds: (ct.NodeCategory.MAXWELLSIM_BOUNDS)}
|
||||||
ct.NodeType.BoundConds: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_BOUNDS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ BL_REGISTER = [
|
||||||
*pml_bound_face.BL_REGISTER,
|
*pml_bound_face.BL_REGISTER,
|
||||||
*pec_bound_face.BL_REGISTER,
|
*pec_bound_face.BL_REGISTER,
|
||||||
*pmc_bound_face.BL_REGISTER,
|
*pmc_bound_face.BL_REGISTER,
|
||||||
|
|
||||||
*bloch_bound_face.BL_REGISTER,
|
*bloch_bound_face.BL_REGISTER,
|
||||||
*periodic_bound_face.BL_REGISTER,
|
*periodic_bound_face.BL_REGISTER,
|
||||||
*absorbing_bound_face.BL_REGISTER,
|
*absorbing_bound_face.BL_REGISTER,
|
||||||
|
@ -19,7 +18,6 @@ BL_NODES = {
|
||||||
**pml_bound_face.BL_NODES,
|
**pml_bound_face.BL_NODES,
|
||||||
**pec_bound_face.BL_NODES,
|
**pec_bound_face.BL_NODES,
|
||||||
**pmc_bound_face.BL_NODES,
|
**pmc_bound_face.BL_NODES,
|
||||||
|
|
||||||
**bloch_bound_face.BL_NODES,
|
**bloch_bound_face.BL_NODES,
|
||||||
**periodic_bound_face.BL_NODES,
|
**periodic_bound_face.BL_NODES,
|
||||||
**absorbing_bound_face.BL_NODES,
|
**absorbing_bound_face.BL_NODES,
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
from . import wave_constant
|
from . import wave_constant
|
||||||
#from . import unit_system
|
# from . import unit_system
|
||||||
|
|
||||||
from . import constants
|
from . import constants
|
||||||
|
|
||||||
from . import web_importers
|
from . import web_importers
|
||||||
#from . import file_importers
|
# from . import file_importers
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*wave_constant.BL_REGISTER,
|
*wave_constant.BL_REGISTER,
|
||||||
# *unit_system.BL_REGISTER,
|
# *unit_system.BL_REGISTER,
|
||||||
|
|
||||||
*constants.BL_REGISTER,
|
*constants.BL_REGISTER,
|
||||||
|
|
||||||
*web_importers.BL_REGISTER,
|
*web_importers.BL_REGISTER,
|
||||||
# *file_importers.BL_REGISTER,
|
# *file_importers.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**wave_constant.BL_NODES,
|
**wave_constant.BL_NODES,
|
||||||
# **unit_system.BL_NODES,
|
# **unit_system.BL_NODES,
|
||||||
|
|
||||||
**constants.BL_NODES,
|
**constants.BL_NODES,
|
||||||
|
|
||||||
**web_importers.BL_NODES,
|
**web_importers.BL_NODES,
|
||||||
# *file_importers.BL_REGISTER,
|
# *file_importers.BL_REGISTER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#from . import scientific_constant
|
# from . import scientific_constant
|
||||||
from . import number_constant
|
from . import number_constant
|
||||||
#from . import physical_constant
|
|
||||||
|
# from . import physical_constant
|
||||||
from . import blender_constant
|
from . import blender_constant
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
# *scientific_constant.BL_REGISTER,
|
# *scientific_constant.BL_REGISTER,
|
||||||
*number_constant.BL_REGISTER,
|
*number_constant.BL_REGISTER,
|
||||||
# *physical_constant.BL_REGISTER,
|
# *physical_constant.BL_REGISTER,
|
||||||
*blender_constant.BL_REGISTER,
|
*blender_constant.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
# **scientific_constant.BL_NODES,
|
# **scientific_constant.BL_NODES,
|
||||||
**number_constant.BL_NODES,
|
**number_constant.BL_NODES,
|
||||||
# **physical_constant.BL_NODES,
|
# **physical_constant.BL_NODES,
|
||||||
**blender_constant.BL_NODES,
|
**blender_constant.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,25 +4,26 @@ from .... import contracts as ct
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class BlenderConstantNode(base.MaxwellSimNode):
|
class BlenderConstantNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.BlenderConstant
|
node_type = ct.NodeType.BlenderConstant
|
||||||
bl_label = "Blender Constant"
|
bl_label = 'Blender Constant'
|
||||||
|
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Object": {
|
'Object': {
|
||||||
"Value": sockets.BlenderObjectSocketDef(),
|
'Value': sockets.BlenderObjectSocketDef(),
|
||||||
},
|
},
|
||||||
"Collection": {
|
'Collection': {
|
||||||
"Value": sockets.BlenderCollectionSocketDef(),
|
'Value': sockets.BlenderCollectionSocketDef(),
|
||||||
},
|
},
|
||||||
"Text": {
|
'Text': {
|
||||||
"Value": sockets.BlenderTextSocketDef(),
|
'Value': sockets.BlenderTextSocketDef(),
|
||||||
},
|
},
|
||||||
"Image": {
|
'Image': {
|
||||||
"Value": sockets.BlenderImageSocketDef(),
|
'Value': sockets.BlenderImageSocketDef(),
|
||||||
},
|
},
|
||||||
"GeoNode Tree": {
|
'GeoNode Tree': {
|
||||||
"Value": sockets.BlenderGeoNodesSocketDef(),
|
'Value': sockets.BlenderGeoNodesSocketDef(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
output_socket_sets = input_socket_sets
|
output_socket_sets = input_socket_sets
|
||||||
|
@ -30,13 +31,9 @@ class BlenderConstantNode(base.MaxwellSimNode):
|
||||||
####################
|
####################
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket('Value', input_sockets={'Value'})
|
||||||
"Value",
|
|
||||||
input_sockets={"Value"}
|
|
||||||
)
|
|
||||||
def compute_value(self, input_sockets) -> typ.Any:
|
def compute_value(self, input_sockets) -> typ.Any:
|
||||||
return input_sockets["Value"]
|
return input_sockets['Value']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -46,7 +43,5 @@ BL_REGISTER = [
|
||||||
BlenderConstantNode,
|
BlenderConstantNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
ct.NodeType.BlenderConstant: (
|
ct.NodeType.BlenderConstant: (ct.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS)
|
||||||
ct.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,22 +7,23 @@ from .... import contracts as ct
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class NumberConstantNode(base.MaxwellSimNode):
|
class NumberConstantNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.NumberConstant
|
node_type = ct.NodeType.NumberConstant
|
||||||
bl_label = "Numerical Constant"
|
bl_label = 'Numerical Constant'
|
||||||
|
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Integer": {
|
'Integer': {
|
||||||
"Value": sockets.IntegerNumberSocketDef(),
|
'Value': sockets.IntegerNumberSocketDef(),
|
||||||
},
|
},
|
||||||
"Rational": {
|
'Rational': {
|
||||||
"Value": sockets.RationalNumberSocketDef(),
|
'Value': sockets.RationalNumberSocketDef(),
|
||||||
},
|
},
|
||||||
"Real": {
|
'Real': {
|
||||||
"Value": sockets.RealNumberSocketDef(),
|
'Value': sockets.RealNumberSocketDef(),
|
||||||
},
|
},
|
||||||
"Complex": {
|
'Complex': {
|
||||||
"Value": sockets.ComplexNumberSocketDef(),
|
'Value': sockets.ComplexNumberSocketDef(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
output_socket_sets = input_socket_sets
|
output_socket_sets = input_socket_sets
|
||||||
|
@ -30,13 +31,9 @@ class NumberConstantNode(base.MaxwellSimNode):
|
||||||
####################
|
####################
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket('Value', input_sockets={'Value'})
|
||||||
"Value",
|
|
||||||
input_sockets={"Value"}
|
|
||||||
)
|
|
||||||
def compute_value(self, input_sockets) -> typ.Any:
|
def compute_value(self, input_sockets) -> typ.Any:
|
||||||
return input_sockets["Value"]
|
return input_sockets['Value']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -46,7 +43,5 @@ BL_REGISTER = [
|
||||||
NumberConstantNode,
|
NumberConstantNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
ct.NodeType.NumberConstant: (
|
ct.NodeType.NumberConstant: (ct.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS)
|
||||||
ct.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,47 +5,48 @@ from .... import contracts
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class PhysicalConstantNode(base.MaxwellSimTreeNode):
|
class PhysicalConstantNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.PhysicalConstant
|
node_type = contracts.NodeType.PhysicalConstant
|
||||||
|
|
||||||
bl_label = "Physical Constant"
|
bl_label = 'Physical Constant'
|
||||||
#bl_icon = constants.ICON_SIM_INPUT
|
# bl_icon = constants.ICON_SIM_INPUT
|
||||||
|
|
||||||
input_sockets = {}
|
input_sockets = {}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"time": {
|
'time': {
|
||||||
"value": sockets.PhysicalTimeSocketDef(
|
'value': sockets.PhysicalTimeSocketDef(
|
||||||
label="Time",
|
label='Time',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"angle": {
|
'angle': {
|
||||||
"value": sockets.PhysicalAngleSocketDef(
|
'value': sockets.PhysicalAngleSocketDef(
|
||||||
label="Angle",
|
label='Angle',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"length": {
|
'length': {
|
||||||
"value": sockets.PhysicalLengthSocketDef(
|
'value': sockets.PhysicalLengthSocketDef(
|
||||||
label="Length",
|
label='Length',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"area": {
|
'area': {
|
||||||
"value": sockets.PhysicalAreaSocketDef(
|
'value': sockets.PhysicalAreaSocketDef(
|
||||||
label="Area",
|
label='Area',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"volume": {
|
'volume': {
|
||||||
"value": sockets.PhysicalVolumeSocketDef(
|
'value': sockets.PhysicalVolumeSocketDef(
|
||||||
label="Volume",
|
label='Volume',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"point_3d": {
|
'point_3d': {
|
||||||
"value": sockets.PhysicalPoint3DSocketDef(
|
'value': sockets.PhysicalPoint3DSocketDef(
|
||||||
label="3D Point",
|
label='3D Point',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"size_3d": {
|
'size_3d': {
|
||||||
"value": sockets.PhysicalSize3DSocketDef(
|
'value': sockets.PhysicalSize3DSocketDef(
|
||||||
label="3D Size",
|
label='3D Size',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
## I got bored so maybe the rest later
|
## I got bored so maybe the rest later
|
||||||
|
@ -56,10 +57,9 @@ class PhysicalConstantNode(base.MaxwellSimTreeNode):
|
||||||
####################
|
####################
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("value")
|
@base.computes_output_socket('value')
|
||||||
def compute_value(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
def compute_value(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
return self.compute_input("value")
|
return self.compute_input('value')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -5,29 +5,29 @@ from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class PhysicalUnitSystemNode(base.MaxwellSimNode):
|
class PhysicalUnitSystemNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.UnitSystem
|
node_type = ct.NodeType.UnitSystem
|
||||||
bl_label = "Unit System"
|
bl_label = 'Unit System'
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Unit System": sockets.PhysicalUnitSystemSocketDef(
|
'Unit System': sockets.PhysicalUnitSystemSocketDef(
|
||||||
show_by_default=True,
|
show_by_default=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Unit System": sockets.PhysicalUnitSystemSocketDef(),
|
'Unit System': sockets.PhysicalUnitSystemSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Unit System",
|
'Unit System',
|
||||||
input_sockets = {"Unit System"},
|
input_sockets={'Unit System'},
|
||||||
)
|
)
|
||||||
def compute_value(self, input_sockets) -> dict:
|
def compute_value(self, input_sockets) -> dict:
|
||||||
return input_sockets["Unit System"]
|
return input_sockets['Unit System']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -36,8 +36,4 @@ class PhysicalUnitSystemNode(base.MaxwellSimNode):
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
PhysicalUnitSystemNode,
|
PhysicalUnitSystemNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.UnitSystem: (ct.NodeCategory.MAXWELLSIM_INPUTS)}
|
||||||
ct.NodeType.UnitSystem: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_INPUTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,39 +8,36 @@ from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
VAC_SPEED_OF_LIGHT = (
|
VAC_SPEED_OF_LIGHT = sc.constants.speed_of_light * spu.meter / spu.second
|
||||||
sc.constants.speed_of_light
|
|
||||||
* spu.meter/spu.second
|
|
||||||
)
|
|
||||||
|
|
||||||
class WaveConstantNode(base.MaxwellSimNode):
|
class WaveConstantNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.WaveConstant
|
node_type = ct.NodeType.WaveConstant
|
||||||
|
|
||||||
bl_label = "Wave Constant"
|
bl_label = 'Wave Constant'
|
||||||
|
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
# Single
|
# Single
|
||||||
"Vacuum WL": {
|
'Vacuum WL': {
|
||||||
"WL": sockets.PhysicalLengthSocketDef(
|
'WL': sockets.PhysicalLengthSocketDef(
|
||||||
default_value=500*spu.nm,
|
default_value=500 * spu.nm,
|
||||||
default_unit=spu.nm,
|
default_unit=spu.nm,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Frequency": {
|
'Frequency': {
|
||||||
"Freq": sockets.PhysicalFreqSocketDef(
|
'Freq': sockets.PhysicalFreqSocketDef(
|
||||||
default_value=500*spux.THz,
|
default_value=500 * spux.THz,
|
||||||
default_unit=spux.THz,
|
default_unit=spux.THz,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
# Listy
|
# Listy
|
||||||
"Vacuum WLs": {
|
'Vacuum WLs': {
|
||||||
"WLs": sockets.PhysicalLengthSocketDef(
|
'WLs': sockets.PhysicalLengthSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Frequencies": {
|
'Frequencies': {
|
||||||
"Freqs": sockets.PhysicalFreqSocketDef(
|
'Freqs': sockets.PhysicalFreqSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -50,47 +47,47 @@ class WaveConstantNode(base.MaxwellSimNode):
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"WL",
|
'WL',
|
||||||
input_sockets={"WL", "Freq"},
|
input_sockets={'WL', 'Freq'},
|
||||||
)
|
)
|
||||||
def compute_vac_wl(self, input_sockets: dict) -> sp.Expr:
|
def compute_vac_wl(self, input_sockets: dict) -> sp.Expr:
|
||||||
if (vac_wl := input_sockets["WL"]) is not None:
|
if (vac_wl := input_sockets['WL']) is not None:
|
||||||
return vac_wl
|
return vac_wl
|
||||||
|
|
||||||
elif (freq := input_sockets["Freq"]) is not None:
|
elif (freq := input_sockets['Freq']) is not None:
|
||||||
return spu.convert_to(
|
return spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / freq,
|
VAC_SPEED_OF_LIGHT / freq,
|
||||||
spu.meter,
|
spu.meter,
|
||||||
)
|
)
|
||||||
|
|
||||||
raise RuntimeError("Vac WL and Freq are both None")
|
raise RuntimeError('Vac WL and Freq are both None')
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Freq",
|
'Freq',
|
||||||
input_sockets={"WL", "Freq"},
|
input_sockets={'WL', 'Freq'},
|
||||||
)
|
)
|
||||||
def compute_freq(self, input_sockets: dict) -> sp.Expr:
|
def compute_freq(self, input_sockets: dict) -> sp.Expr:
|
||||||
if (vac_wl := input_sockets["WL"]) is not None:
|
if (vac_wl := input_sockets['WL']) is not None:
|
||||||
return spu.convert_to(
|
return spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / vac_wl,
|
VAC_SPEED_OF_LIGHT / vac_wl,
|
||||||
spu.hertz,
|
spu.hertz,
|
||||||
)
|
)
|
||||||
elif (freq := input_sockets["Freq"]) is not None:
|
elif (freq := input_sockets['Freq']) is not None:
|
||||||
return freq
|
return freq
|
||||||
|
|
||||||
raise RuntimeError("Vac WL and Freq are both None")
|
raise RuntimeError('Vac WL and Freq are both None')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Listy Callbacks
|
# - Listy Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"WLs",
|
'WLs',
|
||||||
input_sockets={"WLs", "Freqs"},
|
input_sockets={'WLs', 'Freqs'},
|
||||||
)
|
)
|
||||||
def compute_vac_wls(self, input_sockets: dict) -> sp.Expr:
|
def compute_vac_wls(self, input_sockets: dict) -> sp.Expr:
|
||||||
if (vac_wls := input_sockets["WLs"]) is not None:
|
if (vac_wls := input_sockets['WLs']) is not None:
|
||||||
return vac_wls
|
return vac_wls
|
||||||
elif (freqs := input_sockets["Freqs"]) is not None:
|
elif (freqs := input_sockets['Freqs']) is not None:
|
||||||
return [
|
return [
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / freq,
|
VAC_SPEED_OF_LIGHT / freq,
|
||||||
|
@ -99,14 +96,14 @@ class WaveConstantNode(base.MaxwellSimNode):
|
||||||
for freq in freqs
|
for freq in freqs
|
||||||
][::-1]
|
][::-1]
|
||||||
|
|
||||||
raise RuntimeError("Vac WLs and Freqs are both None")
|
raise RuntimeError('Vac WLs and Freqs are both None')
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Freqs",
|
'Freqs',
|
||||||
input_sockets={"WLs", "Freqs"},
|
input_sockets={'WLs', 'Freqs'},
|
||||||
)
|
)
|
||||||
def compute_freqs(self, input_sockets: dict) -> sp.Expr:
|
def compute_freqs(self, input_sockets: dict) -> sp.Expr:
|
||||||
if (vac_wls := input_sockets["WLs"]) is not None:
|
if (vac_wls := input_sockets['WLs']) is not None:
|
||||||
return [
|
return [
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / vac_wl,
|
VAC_SPEED_OF_LIGHT / vac_wl,
|
||||||
|
@ -114,33 +111,32 @@ class WaveConstantNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
for vac_wl in vac_wls
|
for vac_wl in vac_wls
|
||||||
][::-1]
|
][::-1]
|
||||||
elif (freqs := input_sockets["Freqs"]) is not None:
|
elif (freqs := input_sockets['Freqs']) is not None:
|
||||||
return freqs
|
return freqs
|
||||||
|
|
||||||
raise RuntimeError("Vac WLs and Freqs are both None")
|
raise RuntimeError('Vac WLs and Freqs are both None')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
prop_name="active_socket_set",
|
prop_name='active_socket_set', props={'active_socket_set'}
|
||||||
props={"active_socket_set"}
|
|
||||||
)
|
)
|
||||||
def on_value_changed__active_socket_set(self, props: dict):
|
def on_value_changed__active_socket_set(self, props: dict):
|
||||||
# Singular: Normal Output Sockets
|
# Singular: Normal Output Sockets
|
||||||
if props["active_socket_set"] in {"Vacuum WL", "Frequency"}:
|
if props['active_socket_set'] in {'Vacuum WL', 'Frequency'}:
|
||||||
self.loose_output_sockets = {}
|
self.loose_output_sockets = {}
|
||||||
self.loose_output_sockets = {
|
self.loose_output_sockets = {
|
||||||
"Freq": sockets.PhysicalFreqSocketDef(),
|
'Freq': sockets.PhysicalFreqSocketDef(),
|
||||||
"WL": sockets.PhysicalLengthSocketDef(),
|
'WL': sockets.PhysicalLengthSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Plural: Listy Output Sockets
|
# Plural: Listy Output Sockets
|
||||||
elif props["active_socket_set"] in {"Vacuum WLs", "Frequencies"}:
|
elif props['active_socket_set'] in {'Vacuum WLs', 'Frequencies'}:
|
||||||
self.loose_output_sockets = {}
|
self.loose_output_sockets = {}
|
||||||
self.loose_output_sockets = {
|
self.loose_output_sockets = {
|
||||||
"Freqs": sockets.PhysicalFreqSocketDef(is_list=True),
|
'Freqs': sockets.PhysicalFreqSocketDef(is_list=True),
|
||||||
"WLs": sockets.PhysicalLengthSocketDef(is_list=True),
|
'WLs': sockets.PhysicalLengthSocketDef(is_list=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -158,8 +154,4 @@ class WaveConstantNode(base.MaxwellSimNode):
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
WaveConstantNode,
|
WaveConstantNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.WaveConstant: (ct.NodeCategory.MAXWELLSIM_INPUTS)}
|
||||||
ct.NodeType.WaveConstant: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_INPUTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,49 +17,50 @@ from ... import base
|
||||||
|
|
||||||
CACHE = {}
|
CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node
|
# - Node
|
||||||
####################
|
####################
|
||||||
class Tidy3DWebImporterNode(base.MaxwellSimNode):
|
class Tidy3DWebImporterNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.Tidy3DWebImporter
|
node_type = ct.NodeType.Tidy3DWebImporter
|
||||||
bl_label = "Tidy3DWebImporter"
|
bl_label = 'Tidy3DWebImporter'
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Cloud Task": sockets.Tidy3DCloudTaskSocketDef(
|
'Cloud Task': sockets.Tidy3DCloudTaskSocketDef(
|
||||||
should_exist=True,
|
should_exist=True,
|
||||||
),
|
),
|
||||||
"Cache Path": sockets.FilePathSocketDef(
|
'Cache Path': sockets.FilePathSocketDef(
|
||||||
default_path=Path("loaded_simulation.hdf5")
|
default_path=Path('loaded_simulation.hdf5')
|
||||||
)
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Methods
|
# - Output Methods
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"FDTD Sim Data",
|
'FDTD Sim Data',
|
||||||
input_sockets={"Cloud Task", "Cache Path"},
|
input_sockets={'Cloud Task', 'Cache Path'},
|
||||||
)
|
)
|
||||||
def compute_fdtd_sim_data(self, input_sockets: dict) -> str:
|
def compute_fdtd_sim_data(self, input_sockets: dict) -> str:
|
||||||
global CACHE
|
global CACHE
|
||||||
if not CACHE.get(self.instance_id):
|
if not CACHE.get(self.instance_id):
|
||||||
CACHE[self.instance_id] = {"fdtd_sim_data": None}
|
CACHE[self.instance_id] = {'fdtd_sim_data': None}
|
||||||
|
|
||||||
if CACHE[self.instance_id]["fdtd_sim_data"] is not None:
|
if CACHE[self.instance_id]['fdtd_sim_data'] is not None:
|
||||||
return CACHE[self.instance_id]["fdtd_sim_data"]
|
return CACHE[self.instance_id]['fdtd_sim_data']
|
||||||
|
|
||||||
if not (
|
if not (
|
||||||
(cloud_task := input_sockets["Cloud Task"]) is not None
|
(cloud_task := input_sockets['Cloud Task']) is not None
|
||||||
and isinstance(cloud_task, tdcloud.CloudTask)
|
and isinstance(cloud_task, tdcloud.CloudTask)
|
||||||
and cloud_task.status == "success"
|
and cloud_task.status == 'success'
|
||||||
):
|
):
|
||||||
msg ="Won't attempt getting SimData"
|
msg = "Won't attempt getting SimData"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
# Load the Simulation
|
# Load the Simulation
|
||||||
cache_path = input_sockets["Cache Path"]
|
cache_path = input_sockets['Cache Path']
|
||||||
if cache_path is None:
|
if cache_path is None:
|
||||||
print("CACHE PATH IS NONE WHY")
|
print('CACHE PATH IS NONE WHY')
|
||||||
return ## I guess?
|
return ## I guess?
|
||||||
if cache_path.is_file():
|
if cache_path.is_file():
|
||||||
sim_data = td.SimulationData.from_file(str(cache_path))
|
sim_data = td.SimulationData.from_file(str(cache_path))
|
||||||
|
@ -70,26 +71,25 @@ class Tidy3DWebImporterNode(base.MaxwellSimNode):
|
||||||
path=str(cache_path),
|
path=str(cache_path),
|
||||||
)
|
)
|
||||||
|
|
||||||
CACHE[self.instance_id]["fdtd_sim_data"] = sim_data
|
CACHE[self.instance_id]['fdtd_sim_data'] = sim_data
|
||||||
return sim_data
|
return sim_data
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"FDTD Sim",
|
'FDTD Sim',
|
||||||
input_sockets={"Cloud Task"},
|
input_sockets={'Cloud Task'},
|
||||||
)
|
)
|
||||||
def compute_fdtd_sim(self, input_sockets: dict) -> str:
|
def compute_fdtd_sim(self, input_sockets: dict) -> str:
|
||||||
if not isinstance(
|
if not isinstance(
|
||||||
cloud_task := input_sockets["Cloud Task"],
|
cloud_task := input_sockets['Cloud Task'], tdcloud.CloudTask
|
||||||
tdcloud.CloudTask
|
|
||||||
):
|
):
|
||||||
msg ="Input cloud task does not exist"
|
msg = 'Input cloud task does not exist'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
# Load the Simulation
|
# Load the Simulation
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
_path_tmp = Path(f.name)
|
_path_tmp = Path(f.name)
|
||||||
_path_tmp.rename(f.name + ".json")
|
_path_tmp.rename(f.name + '.json')
|
||||||
path_tmp = Path(f.name + ".json")
|
path_tmp = Path(f.name + '.json')
|
||||||
|
|
||||||
sim = td_web.api.webapi.load_simulation(
|
sim = td_web.api.webapi.load_simulation(
|
||||||
cloud_task.task_id,
|
cloud_task.task_id,
|
||||||
|
@ -103,18 +103,17 @@ class Tidy3DWebImporterNode(base.MaxwellSimNode):
|
||||||
# - Update
|
# - Update
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="Cloud Task",
|
socket_name='Cloud Task', input_sockets={'Cloud Task'}
|
||||||
input_sockets={"Cloud Task"}
|
|
||||||
)
|
)
|
||||||
def on_value_changed__cloud_task(self, input_sockets: dict):
|
def on_value_changed__cloud_task(self, input_sockets: dict):
|
||||||
if (
|
if (
|
||||||
(cloud_task := input_sockets["Cloud Task"]) is not None
|
(cloud_task := input_sockets['Cloud Task']) is not None
|
||||||
and isinstance(cloud_task, tdcloud.CloudTask)
|
and isinstance(cloud_task, tdcloud.CloudTask)
|
||||||
and cloud_task.status == "success"
|
and cloud_task.status == 'success'
|
||||||
):
|
):
|
||||||
self.loose_output_sockets = {
|
self.loose_output_sockets = {
|
||||||
"FDTD Sim Data": sockets.MaxwellFDTDSimDataSocketDef(),
|
'FDTD Sim Data': sockets.MaxwellFDTDSimDataSocketDef(),
|
||||||
"FDTD Sim": sockets.MaxwellFDTDSimSocketDef(),
|
'FDTD Sim': sockets.MaxwellFDTDSimSocketDef(),
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -8,95 +8,91 @@ from .. import contracts as ct
|
||||||
from .. import sockets
|
from .. import sockets
|
||||||
from . import base
|
from . import base
|
||||||
|
|
||||||
|
|
||||||
class KitchenSinkNode(base.MaxwellSimNode):
|
class KitchenSinkNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.KitchenSink
|
node_type = ct.NodeType.KitchenSink
|
||||||
|
|
||||||
bl_label = "Kitchen Sink"
|
bl_label = 'Kitchen Sink'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Static Data": sockets.AnySocketDef(),
|
'Static Data': sockets.AnySocketDef(),
|
||||||
}
|
}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Basic": {
|
'Basic': {
|
||||||
"Any": sockets.AnySocketDef(),
|
'Any': sockets.AnySocketDef(),
|
||||||
"Bool": sockets.BoolSocketDef(),
|
'Bool': sockets.BoolSocketDef(),
|
||||||
"FilePath": sockets.FilePathSocketDef(),
|
'FilePath': sockets.FilePathSocketDef(),
|
||||||
"Text": sockets.TextSocketDef(),
|
'Text': sockets.TextSocketDef(),
|
||||||
},
|
},
|
||||||
"Number": {
|
'Number': {
|
||||||
"Integer": sockets.IntegerNumberSocketDef(),
|
'Integer': sockets.IntegerNumberSocketDef(),
|
||||||
"Rational": sockets.RationalNumberSocketDef(),
|
'Rational': sockets.RationalNumberSocketDef(),
|
||||||
"Real": sockets.RealNumberSocketDef(),
|
'Real': sockets.RealNumberSocketDef(),
|
||||||
"Complex": sockets.ComplexNumberSocketDef(),
|
'Complex': sockets.ComplexNumberSocketDef(),
|
||||||
},
|
},
|
||||||
"Vector": {
|
'Vector': {
|
||||||
"Real 2D": sockets.Real2DVectorSocketDef(),
|
'Real 2D': sockets.Real2DVectorSocketDef(),
|
||||||
"Real 3D": sockets.Real3DVectorSocketDef(
|
'Real 3D': sockets.Real3DVectorSocketDef(
|
||||||
default_value=sp.Matrix([0.0, 0.0, 0.0])
|
default_value=sp.Matrix([0.0, 0.0, 0.0])
|
||||||
),
|
),
|
||||||
"Complex 2D": sockets.Complex2DVectorSocketDef(),
|
'Complex 2D': sockets.Complex2DVectorSocketDef(),
|
||||||
"Complex 3D": sockets.Complex3DVectorSocketDef(),
|
'Complex 3D': sockets.Complex3DVectorSocketDef(),
|
||||||
},
|
},
|
||||||
"Physical": {
|
'Physical': {
|
||||||
"Time": sockets.PhysicalTimeSocketDef(),
|
'Time': sockets.PhysicalTimeSocketDef(),
|
||||||
#"physical_point_2d": sockets.PhysicalPoint2DSocketDef(),
|
# "physical_point_2d": sockets.PhysicalPoint2DSocketDef(),
|
||||||
"Angle": sockets.PhysicalAngleSocketDef(),
|
'Angle': sockets.PhysicalAngleSocketDef(),
|
||||||
"Length": sockets.PhysicalLengthSocketDef(),
|
'Length': sockets.PhysicalLengthSocketDef(),
|
||||||
"Area": sockets.PhysicalAreaSocketDef(),
|
'Area': sockets.PhysicalAreaSocketDef(),
|
||||||
"Volume": sockets.PhysicalVolumeSocketDef(),
|
'Volume': sockets.PhysicalVolumeSocketDef(),
|
||||||
"Point 3D": sockets.PhysicalPoint3DSocketDef(),
|
'Point 3D': sockets.PhysicalPoint3DSocketDef(),
|
||||||
##"physical_size_2d": sockets.PhysicalSize2DSocketDef(),
|
##"physical_size_2d": sockets.PhysicalSize2DSocketDef(),
|
||||||
"Size 3D": sockets.PhysicalSize3DSocketDef(),
|
'Size 3D': sockets.PhysicalSize3DSocketDef(),
|
||||||
"Mass": sockets.PhysicalMassSocketDef(),
|
'Mass': sockets.PhysicalMassSocketDef(),
|
||||||
"Speed": sockets.PhysicalSpeedSocketDef(),
|
'Speed': sockets.PhysicalSpeedSocketDef(),
|
||||||
"Accel Scalar": sockets.PhysicalAccelScalarSocketDef(),
|
'Accel Scalar': sockets.PhysicalAccelScalarSocketDef(),
|
||||||
"Force Scalar": sockets.PhysicalForceScalarSocketDef(),
|
'Force Scalar': sockets.PhysicalForceScalarSocketDef(),
|
||||||
#"physical_accel_3dvector": sockets.PhysicalAccel3DVectorSocketDef(),
|
# "physical_accel_3dvector": sockets.PhysicalAccel3DVectorSocketDef(),
|
||||||
##"physical_force_3dvector": sockets.PhysicalForce3DVectorSocketDef(),
|
##"physical_force_3dvector": sockets.PhysicalForce3DVectorSocketDef(),
|
||||||
"Pol": sockets.PhysicalPolSocketDef(),
|
'Pol': sockets.PhysicalPolSocketDef(),
|
||||||
"Freq": sockets.PhysicalFreqSocketDef(),
|
'Freq': sockets.PhysicalFreqSocketDef(),
|
||||||
},
|
},
|
||||||
"Blender": {
|
'Blender': {
|
||||||
"Object": sockets.BlenderObjectSocketDef(),
|
'Object': sockets.BlenderObjectSocketDef(),
|
||||||
"Collection": sockets.BlenderCollectionSocketDef(),
|
'Collection': sockets.BlenderCollectionSocketDef(),
|
||||||
"Image": sockets.BlenderImageSocketDef(),
|
'Image': sockets.BlenderImageSocketDef(),
|
||||||
"GeoNodes": sockets.BlenderGeoNodesSocketDef(),
|
'GeoNodes': sockets.BlenderGeoNodesSocketDef(),
|
||||||
"Text": sockets.BlenderTextSocketDef(),
|
'Text': sockets.BlenderTextSocketDef(),
|
||||||
},
|
},
|
||||||
"Maxwell": {
|
'Maxwell': {
|
||||||
"Source": sockets.MaxwellSourceSocketDef(),
|
'Source': sockets.MaxwellSourceSocketDef(),
|
||||||
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
"Medium": sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
"Medium Non-Linearity": sockets.MaxwellMediumNonLinearitySocketDef(),
|
'Medium Non-Linearity': sockets.MaxwellMediumNonLinearitySocketDef(),
|
||||||
"Structure": sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
"Bound Box": sockets.MaxwellBoundBoxSocketDef(),
|
'Bound Box': sockets.MaxwellBoundBoxSocketDef(),
|
||||||
"Bound Face": sockets.MaxwellBoundFaceSocketDef(),
|
'Bound Face': sockets.MaxwellBoundFaceSocketDef(),
|
||||||
"Monitor": sockets.MaxwellMonitorSocketDef(),
|
'Monitor': sockets.MaxwellMonitorSocketDef(),
|
||||||
"FDTD Sim": sockets.MaxwellFDTDSimSocketDef(),
|
'FDTD Sim': sockets.MaxwellFDTDSimSocketDef(),
|
||||||
"Sim Grid": sockets.MaxwellSimGridSocketDef(),
|
'Sim Grid': sockets.MaxwellSimGridSocketDef(),
|
||||||
"Sim Grid Axis": sockets.MaxwellSimGridAxisSocketDef(),
|
'Sim Grid Axis': sockets.MaxwellSimGridAxisSocketDef(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Static Data": sockets.AnySocketDef(),
|
'Static Data': sockets.AnySocketDef(),
|
||||||
}
|
}
|
||||||
output_socket_sets = input_socket_sets
|
output_socket_sets = input_socket_sets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
KitchenSinkNode,
|
KitchenSinkNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.KitchenSink: (ct.NodeCategory.MAXWELLSIM_INPUTS)}
|
||||||
ct.NodeType.KitchenSink: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_INPUTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,47 +1,45 @@
|
||||||
from . import library_medium
|
from . import library_medium
|
||||||
|
|
||||||
#from . import pec_medium
|
# from . import pec_medium
|
||||||
#from . import isotropic_medium
|
# from . import isotropic_medium
|
||||||
#from . import anisotropic_medium
|
# from . import anisotropic_medium
|
||||||
#
|
#
|
||||||
#from . import triple_sellmeier_medium
|
# from . import triple_sellmeier_medium
|
||||||
#from . import sellmeier_medium
|
# from . import sellmeier_medium
|
||||||
#from . import pole_residue_medium
|
# from . import pole_residue_medium
|
||||||
#from . import drude_medium
|
# from . import drude_medium
|
||||||
#from . import drude_lorentz_medium
|
# from . import drude_lorentz_medium
|
||||||
#from . import debye_medium
|
# from . import debye_medium
|
||||||
#
|
#
|
||||||
#from . import non_linearities
|
# from . import non_linearities
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*library_medium.BL_REGISTER,
|
*library_medium.BL_REGISTER,
|
||||||
|
# *pec_medium.BL_REGISTER,
|
||||||
# *pec_medium.BL_REGISTER,
|
# *isotropic_medium.BL_REGISTER,
|
||||||
# *isotropic_medium.BL_REGISTER,
|
# *anisotropic_medium.BL_REGISTER,
|
||||||
# *anisotropic_medium.BL_REGISTER,
|
#
|
||||||
#
|
# *triple_sellmeier_medium.BL_REGISTER,
|
||||||
# *triple_sellmeier_medium.BL_REGISTER,
|
# *sellmeier_medium.BL_REGISTER,
|
||||||
# *sellmeier_medium.BL_REGISTER,
|
# *pole_residue_medium.BL_REGISTER,
|
||||||
# *pole_residue_medium.BL_REGISTER,
|
# *drude_medium.BL_REGISTER,
|
||||||
# *drude_medium.BL_REGISTER,
|
# *drude_lorentz_medium.BL_REGISTER,
|
||||||
# *drude_lorentz_medium.BL_REGISTER,
|
# *debye_medium.BL_REGISTER,
|
||||||
# *debye_medium.BL_REGISTER,
|
#
|
||||||
#
|
# *non_linearities.BL_REGISTER,
|
||||||
# *non_linearities.BL_REGISTER,
|
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**library_medium.BL_NODES,
|
**library_medium.BL_NODES,
|
||||||
|
# **pec_medium.BL_NODES,
|
||||||
# **pec_medium.BL_NODES,
|
# **isotropic_medium.BL_NODES,
|
||||||
# **isotropic_medium.BL_NODES,
|
# **anisotropic_medium.BL_NODES,
|
||||||
# **anisotropic_medium.BL_NODES,
|
#
|
||||||
#
|
# **triple_sellmeier_medium.BL_NODES,
|
||||||
# **triple_sellmeier_medium.BL_NODES,
|
# **sellmeier_medium.BL_NODES,
|
||||||
# **sellmeier_medium.BL_NODES,
|
# **pole_residue_medium.BL_NODES,
|
||||||
# **pole_residue_medium.BL_NODES,
|
# **drude_medium.BL_NODES,
|
||||||
# **drude_medium.BL_NODES,
|
# **drude_lorentz_medium.BL_NODES,
|
||||||
# **drude_lorentz_medium.BL_NODES,
|
# **debye_medium.BL_NODES,
|
||||||
# **debye_medium.BL_NODES,
|
#
|
||||||
#
|
# **non_linearities.BL_NODES,
|
||||||
# **non_linearities.BL_NODES,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -6,67 +6,72 @@ from ... import contracts
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class DrudeLorentzMediumNode(base.MaxwellSimTreeNode):
|
class DrudeLorentzMediumNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.DrudeLorentzMedium
|
node_type = contracts.NodeType.DrudeLorentzMedium
|
||||||
|
|
||||||
bl_label = "Drude-Lorentz Medium"
|
bl_label = 'Drude-Lorentz Medium'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = (
|
||||||
"eps_inf": sockets.RealNumberSocketDef(
|
{
|
||||||
label=f"εr_∞",
|
'eps_inf': sockets.RealNumberSocketDef(
|
||||||
|
label=f'εr_∞',
|
||||||
),
|
),
|
||||||
} | {
|
}
|
||||||
f"del_eps{i}": sockets.RealNumberSocketDef(
|
| {
|
||||||
label=f"Δεr_{i}",
|
f'del_eps{i}': sockets.RealNumberSocketDef(
|
||||||
)
|
label=f'Δεr_{i}',
|
||||||
for i in [1, 2, 3]
|
|
||||||
} | {
|
|
||||||
f"f{i}": sockets.PhysicalFreqSocketDef(
|
|
||||||
label=f"f_{i}",
|
|
||||||
)
|
|
||||||
for i in [1, 2, 3]
|
|
||||||
} | {
|
|
||||||
f"delta{i}": sockets.PhysicalFreqSocketDef(
|
|
||||||
label=f"δ_{i}",
|
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
for i in [1, 2, 3]
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
f'f{i}': sockets.PhysicalFreqSocketDef(
|
||||||
|
label=f'f_{i}',
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
f'delta{i}': sockets.PhysicalFreqSocketDef(
|
||||||
|
label=f'δ_{i}',
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
}
|
||||||
|
)
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"medium": sockets.MaxwellMediumSocketDef(
|
'medium': sockets.MaxwellMediumSocketDef(label='Medium'),
|
||||||
label="Medium"
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("medium")
|
@base.computes_output_socket('medium')
|
||||||
def compute_medium(self: contracts.NodeTypeProtocol) -> td.Sellmeier:
|
def compute_medium(self: contracts.NodeTypeProtocol) -> td.Sellmeier:
|
||||||
## Retrieval
|
## Retrieval
|
||||||
return td.Lorentz(
|
return td.Lorentz(
|
||||||
eps_inf=self.compute_input(f"eps_inf"),
|
eps_inf=self.compute_input(f'eps_inf'),
|
||||||
coeffs = [
|
coeffs=[
|
||||||
(
|
(
|
||||||
self.compute_input(f"del_eps{i}"),
|
self.compute_input(f'del_eps{i}'),
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
self.compute_input(f"f{i}"),
|
self.compute_input(f'f{i}'),
|
||||||
spu.hertz,
|
spu.hertz,
|
||||||
) / spu.hertz,
|
)
|
||||||
|
/ spu.hertz,
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
self.compute_input(f"delta{i}"),
|
self.compute_input(f'delta{i}'),
|
||||||
spu.hertz,
|
spu.hertz,
|
||||||
) / spu.hertz,
|
)
|
||||||
|
/ spu.hertz,
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
for i in [1, 2, 3]
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -14,27 +14,25 @@ from ... import sockets
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
VAC_SPEED_OF_LIGHT = (
|
VAC_SPEED_OF_LIGHT = sc.constants.speed_of_light * spu.meter / spu.second
|
||||||
sc.constants.speed_of_light
|
|
||||||
* spu.meter/spu.second
|
|
||||||
)
|
|
||||||
|
|
||||||
class LibraryMediumNode(base.MaxwellSimNode):
|
class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.LibraryMedium
|
node_type = ct.NodeType.LibraryMedium
|
||||||
bl_label = "Library Medium"
|
bl_label = 'Library Medium'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {}
|
input_sockets = {}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Medium": sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"nk_plot": ct.schemas.ManagedObjDef(
|
'nk_plot': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
mk=lambda name: managed_objs.ManagedBLImage(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,25 +40,27 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
material: bpy.props.EnumProperty(
|
material: bpy.props.EnumProperty(
|
||||||
name="",
|
name='',
|
||||||
description="",
|
description='',
|
||||||
#icon="NODE_MATERIAL",
|
# icon="NODE_MATERIAL",
|
||||||
items=[
|
items=[
|
||||||
(
|
(
|
||||||
mat_key,
|
mat_key,
|
||||||
td.material_library[mat_key].name,
|
td.material_library[mat_key].name,
|
||||||
", ".join([
|
', '.join(
|
||||||
|
[
|
||||||
ref.journal
|
ref.journal
|
||||||
for ref in td.material_library[mat_key].variants[
|
for ref in td.material_library[mat_key]
|
||||||
td.material_library[mat_key].default
|
.variants[td.material_library[mat_key].default]
|
||||||
].reference
|
.reference
|
||||||
])
|
]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
for mat_key in td.material_library
|
for mat_key in td.material_library
|
||||||
if mat_key != "graphene" ## For some reason, it's unique...
|
if mat_key != 'graphene' ## For some reason, it's unique...
|
||||||
],
|
],
|
||||||
default="Au",
|
default='Au',
|
||||||
update=(lambda self, context: self.sync_prop("material", context)),
|
update=(lambda self, context: self.sync_prop('material', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -71,12 +71,12 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
val * spu.hertz,
|
val * spu.hertz,
|
||||||
spuex.terahertz,
|
spuex.terahertz,
|
||||||
) / spuex.terahertz
|
)
|
||||||
|
/ spuex.terahertz
|
||||||
for val in mat.medium.frequency_range
|
for val in mat.medium.frequency_range
|
||||||
]
|
]
|
||||||
return sp.pretty(
|
return sp.pretty(
|
||||||
[freq_range[0].n(4), freq_range[1].n(4)],
|
[freq_range[0].n(4), freq_range[1].n(4)], use_unicode=True
|
||||||
use_unicode=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -87,38 +87,38 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / (val * spu.hertz),
|
VAC_SPEED_OF_LIGHT / (val * spu.hertz),
|
||||||
spu.nanometer,
|
spu.nanometer,
|
||||||
) / spu.nanometer
|
)
|
||||||
|
/ spu.nanometer
|
||||||
for val in reversed(mat.medium.frequency_range)
|
for val in reversed(mat.medium.frequency_range)
|
||||||
]
|
]
|
||||||
return sp.pretty(
|
return sp.pretty(
|
||||||
[nm_range[0].n(4), nm_range[1].n(4)],
|
[nm_range[0].n(4), nm_range[1].n(4)], use_unicode=True
|
||||||
use_unicode=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
layout.prop(self, "material", text="")
|
layout.prop(self, 'material', text='')
|
||||||
|
|
||||||
def draw_info(self, context, col):
|
def draw_info(self, context, col):
|
||||||
# UI Drawing
|
# UI Drawing
|
||||||
split = col.split(factor=0.23, align=True)
|
split = col.split(factor=0.23, align=True)
|
||||||
|
|
||||||
_col = split.column(align=True)
|
_col = split.column(align=True)
|
||||||
_col.alignment = "LEFT"
|
_col.alignment = 'LEFT'
|
||||||
_col.label(text="nm")
|
_col.label(text='nm')
|
||||||
_col.label(text="THz")
|
_col.label(text='THz')
|
||||||
|
|
||||||
_col = split.column(align=True)
|
_col = split.column(align=True)
|
||||||
_col.alignment = "RIGHT"
|
_col.alignment = 'RIGHT'
|
||||||
_col.label(text=self.nm_range_str)
|
_col.label(text=self.nm_range_str)
|
||||||
_col.label(text=self.freq_range_str)
|
_col.label(text=self.freq_range_str)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Sockets
|
# - Output Sockets
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("Medium")
|
@base.computes_output_socket('Medium')
|
||||||
def compute_vac_wl(self) -> sp.Expr:
|
def compute_vac_wl(self) -> sp.Expr:
|
||||||
return td.material_library[self.material].medium
|
return td.material_library[self.material].medium
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
# - Event Callbacks
|
# - Event Callbacks
|
||||||
####################
|
####################
|
||||||
@base.on_show_plot(
|
@base.on_show_plot(
|
||||||
managed_objs={"nk_plot"},
|
managed_objs={'nk_plot'},
|
||||||
props={"material"},
|
props={'material'},
|
||||||
stop_propagation=True, ## Plot only the first plottable node
|
stop_propagation=True, ## Plot only the first plottable node
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
|
@ -135,28 +135,26 @@ class LibraryMediumNode(base.MaxwellSimNode):
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
props: dict[str, typ.Any],
|
props: dict[str, typ.Any],
|
||||||
):
|
):
|
||||||
medium = td.material_library[props["material"]].medium
|
medium = td.material_library[props['material']].medium
|
||||||
freq_range = [
|
freq_range = [
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
val * spu.hertz,
|
val * spu.hertz,
|
||||||
spuex.terahertz,
|
spuex.terahertz,
|
||||||
) / spu.hertz
|
)
|
||||||
|
/ spu.hertz
|
||||||
for val in medium.frequency_range
|
for val in medium.frequency_range
|
||||||
]
|
]
|
||||||
|
|
||||||
managed_objs["nk_plot"].mpl_plot_to_image(
|
managed_objs['nk_plot'].mpl_plot_to_image(
|
||||||
lambda ax: medium.plot(medium.frequency_range, ax=ax),
|
lambda ax: medium.plot(medium.frequency_range, ax=ax),
|
||||||
bl_select=True,
|
bl_select=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
LibraryMediumNode,
|
LibraryMediumNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.LibraryMedium: (ct.NodeCategory.MAXWELLSIM_MEDIUMS)}
|
||||||
ct.NodeType.LibraryMedium: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_MEDIUMS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -6,86 +6,86 @@ from ... import contracts
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class TripleSellmeierMediumNode(base.MaxwellSimTreeNode):
|
class TripleSellmeierMediumNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.TripleSellmeierMedium
|
node_type = contracts.NodeType.TripleSellmeierMedium
|
||||||
|
|
||||||
bl_label = "Three-Parameter Sellmeier Medium"
|
bl_label = 'Three-Parameter Sellmeier Medium'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
f"B{i}": sockets.RealNumberSocketDef(
|
f'B{i}': sockets.RealNumberSocketDef(
|
||||||
label=f"B{i}",
|
label=f'B{i}',
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
for i in [1, 2, 3]
|
||||||
} | {
|
} | {
|
||||||
f"C{i}": sockets.PhysicalAreaSocketDef(
|
f'C{i}': sockets.PhysicalAreaSocketDef(
|
||||||
label=f"C{i}",
|
label=f'C{i}', default_unit=spu.um**2
|
||||||
default_unit=spu.um**2
|
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
for i in [1, 2, 3]
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"medium": sockets.MaxwellMediumSocketDef(
|
'medium': sockets.MaxwellMediumSocketDef(label='Medium'),
|
||||||
label="Medium"
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Presets
|
# - Presets
|
||||||
####################
|
####################
|
||||||
presets = {
|
presets = {
|
||||||
"BK7": contracts.PresetDef(
|
'BK7': contracts.PresetDef(
|
||||||
label="BK7 Glass",
|
label='BK7 Glass',
|
||||||
description="Borosilicate crown glass (known as BK7)",
|
description='Borosilicate crown glass (known as BK7)',
|
||||||
values={
|
values={
|
||||||
"B1": 1.03961212,
|
'B1': 1.03961212,
|
||||||
"B2": 0.231792344,
|
'B2': 0.231792344,
|
||||||
"B3": 1.01046945,
|
'B3': 1.01046945,
|
||||||
"C1": 6.00069867e-3 * spu.um**2,
|
'C1': 6.00069867e-3 * spu.um**2,
|
||||||
"C2": 2.00179144e-2 * spu.um**2,
|
'C2': 2.00179144e-2 * spu.um**2,
|
||||||
"C3": 103.560653 * spu.um**2,
|
'C3': 103.560653 * spu.um**2,
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
"FUSED_SILICA": contracts.PresetDef(
|
'FUSED_SILICA': contracts.PresetDef(
|
||||||
label="Fused Silica",
|
label='Fused Silica',
|
||||||
description="Fused silica aka. SiO2",
|
description='Fused silica aka. SiO2',
|
||||||
values={
|
values={
|
||||||
"B1": 0.696166300,
|
'B1': 0.696166300,
|
||||||
"B2": 0.407942600,
|
'B2': 0.407942600,
|
||||||
"B3": 0.897479400,
|
'B3': 0.897479400,
|
||||||
"C1": 4.67914826e-3 * spu.um**2,
|
'C1': 4.67914826e-3 * spu.um**2,
|
||||||
"C2": 1.35120631e-2 * spu.um**2,
|
'C2': 1.35120631e-2 * spu.um**2,
|
||||||
"C3": 97.9340025 * spu.um**2,
|
'C3': 97.9340025 * spu.um**2,
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("medium")
|
@base.computes_output_socket('medium')
|
||||||
def compute_medium(self: contracts.NodeTypeProtocol) -> td.Sellmeier:
|
def compute_medium(self: contracts.NodeTypeProtocol) -> td.Sellmeier:
|
||||||
## Retrieval
|
## Retrieval
|
||||||
#B1 = self.compute_input("B1")
|
# B1 = self.compute_input("B1")
|
||||||
#C1_with_units = self.compute_input("C1")
|
# C1_with_units = self.compute_input("C1")
|
||||||
#
|
#
|
||||||
## Processing
|
## Processing
|
||||||
#C1 = spu.convert_to(C1_with_units, spu.um**2) / spu.um**2
|
# C1 = spu.convert_to(C1_with_units, spu.um**2) / spu.um**2
|
||||||
|
|
||||||
return td.Sellmeier(coeffs = [
|
return td.Sellmeier(
|
||||||
|
coeffs=[
|
||||||
(
|
(
|
||||||
self.compute_input(f"B{i}"),
|
self.compute_input(f'B{i}'),
|
||||||
spu.convert_to(
|
spu.convert_to(
|
||||||
self.compute_input(f"C{i}"),
|
self.compute_input(f'C{i}'),
|
||||||
spu.um**2,
|
spu.um**2,
|
||||||
) / spu.um**2
|
)
|
||||||
|
/ spu.um**2,
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
for i in [1, 2, 3]
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
from . import eh_field_monitor
|
from . import eh_field_monitor
|
||||||
from . import field_power_flux_monitor
|
from . import field_power_flux_monitor
|
||||||
#from . import epsilon_tensor_monitor
|
# from . import epsilon_tensor_monitor
|
||||||
#from . import diffraction_monitor
|
# from . import diffraction_monitor
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*eh_field_monitor.BL_REGISTER,
|
*eh_field_monitor.BL_REGISTER,
|
||||||
*field_power_flux_monitor.BL_REGISTER,
|
*field_power_flux_monitor.BL_REGISTER,
|
||||||
# *epsilon_tensor_monitor.BL_REGISTER,
|
# *epsilon_tensor_monitor.BL_REGISTER,
|
||||||
# *diffraction_monitor.BL_REGISTER,
|
# *diffraction_monitor.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**eh_field_monitor.BL_NODES,
|
**eh_field_monitor.BL_NODES,
|
||||||
**field_power_flux_monitor.BL_NODES,
|
**field_power_flux_monitor.BL_NODES,
|
||||||
# **epsilon_tensor_monitor.BL_NODES,
|
# **epsilon_tensor_monitor.BL_NODES,
|
||||||
# **diffraction_monitor.BL_NODES,
|
# **diffraction_monitor.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -15,47 +15,48 @@ from ... import sockets
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
GEONODES_MONITOR_BOX = "monitor_box"
|
GEONODES_MONITOR_BOX = 'monitor_box'
|
||||||
|
|
||||||
|
|
||||||
class EHFieldMonitorNode(base.MaxwellSimNode):
|
class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.EHFieldMonitor
|
node_type = ct.NodeType.EHFieldMonitor
|
||||||
bl_label = "E/H Field Monitor"
|
bl_label = 'E/H Field Monitor'
|
||||||
use_sim_node_name = True
|
use_sim_node_name = True
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Size": sockets.PhysicalSize3DSocketDef(),
|
'Size': sockets.PhysicalSize3DSocketDef(),
|
||||||
"Samples/Space": sockets.Integer3DVectorSocketDef(
|
'Samples/Space': sockets.Integer3DVectorSocketDef(
|
||||||
default_value=sp.Matrix([10, 10, 10])
|
default_value=sp.Matrix([10, 10, 10])
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Freq Domain": {
|
'Freq Domain': {
|
||||||
"Freqs": sockets.PhysicalFreqSocketDef(
|
'Freqs': sockets.PhysicalFreqSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Time Domain": {
|
'Time Domain': {
|
||||||
"Rec Start": sockets.PhysicalTimeSocketDef(),
|
'Rec Start': sockets.PhysicalTimeSocketDef(),
|
||||||
"Rec Stop": sockets.PhysicalTimeSocketDef(
|
'Rec Stop': sockets.PhysicalTimeSocketDef(
|
||||||
default_value=200*spux.fs
|
default_value=200 * spux.fs
|
||||||
),
|
),
|
||||||
"Samples/Time": sockets.IntegerNumberSocketDef(
|
'Samples/Time': sockets.IntegerNumberSocketDef(
|
||||||
default_value=100,
|
default_value=100,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Monitor": sockets.MaxwellMonitorSocketDef(),
|
'Monitor': sockets.MaxwellMonitorSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"monitor_box": ct.schemas.ManagedObjDef(
|
'monitor_box': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,29 +77,36 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
# - Output Sockets
|
# - Output Sockets
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Monitor",
|
'Monitor',
|
||||||
input_sockets={
|
input_sockets={
|
||||||
"Rec Start", "Rec Stop", "Center", "Size", "Samples/Space",
|
'Rec Start',
|
||||||
"Samples/Time", "Freqs",
|
'Rec Stop',
|
||||||
|
'Center',
|
||||||
|
'Size',
|
||||||
|
'Samples/Space',
|
||||||
|
'Samples/Time',
|
||||||
|
'Freqs',
|
||||||
},
|
},
|
||||||
props={"active_socket_set", "sim_node_name"}
|
props={'active_socket_set', 'sim_node_name'},
|
||||||
)
|
)
|
||||||
def compute_monitor(self, input_sockets: dict, props: dict) -> td.FieldTimeMonitor:
|
def compute_monitor(
|
||||||
_center = input_sockets["Center"]
|
self, input_sockets: dict, props: dict
|
||||||
_size = input_sockets["Size"]
|
) -> td.FieldTimeMonitor:
|
||||||
_samples_space = input_sockets["Samples/Space"]
|
_center = input_sockets['Center']
|
||||||
|
_size = input_sockets['Size']
|
||||||
|
_samples_space = input_sockets['Samples/Space']
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
samples_space = tuple(_samples_space)
|
samples_space = tuple(_samples_space)
|
||||||
|
|
||||||
if props["active_socket_set"] == "Freq Domain":
|
if props['active_socket_set'] == 'Freq Domain':
|
||||||
freqs = input_sockets["Freqs"]
|
freqs = input_sockets['Freqs']
|
||||||
|
|
||||||
return td.FieldMonitor(
|
return td.FieldMonitor(
|
||||||
center=center,
|
center=center,
|
||||||
size=size,
|
size=size,
|
||||||
name=props["sim_node_name"],
|
name=props['sim_node_name'],
|
||||||
interval_space=samples_space,
|
interval_space=samples_space,
|
||||||
freqs=[
|
freqs=[
|
||||||
float(spu.convert_to(freq, spu.hertz) / spu.hertz)
|
float(spu.convert_to(freq, spu.hertz) / spu.hertz)
|
||||||
|
@ -106,9 +114,9 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
else: ## Time Domain
|
else: ## Time Domain
|
||||||
_rec_start = input_sockets["Rec Start"]
|
_rec_start = input_sockets['Rec Start']
|
||||||
_rec_stop = input_sockets["Rec Stop"]
|
_rec_stop = input_sockets['Rec Stop']
|
||||||
samples_time = input_sockets["Samples/Time"]
|
samples_time = input_sockets['Samples/Time']
|
||||||
|
|
||||||
rec_start = spu.convert_to(_rec_start, spu.second) / spu.second
|
rec_start = spu.convert_to(_rec_start, spu.second) / spu.second
|
||||||
rec_stop = spu.convert_to(_rec_stop, spu.second) / spu.second
|
rec_stop = spu.convert_to(_rec_stop, spu.second) / spu.second
|
||||||
|
@ -116,7 +124,7 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
return td.FieldTimeMonitor(
|
return td.FieldTimeMonitor(
|
||||||
center=center,
|
center=center,
|
||||||
size=size,
|
size=size,
|
||||||
name=props["sim_node_name"],
|
name=props['sim_node_name'],
|
||||||
start=rec_start,
|
start=rec_start,
|
||||||
stop=rec_stop,
|
stop=rec_stop,
|
||||||
interval=samples_time,
|
interval=samples_time,
|
||||||
|
@ -127,70 +135,65 @@ class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
# - Preview - Changes to Input Sockets
|
# - Preview - Changes to Input Sockets
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Size"},
|
socket_name={'Center', 'Size'},
|
||||||
input_sockets={"Center", "Size"},
|
input_sockets={'Center', 'Size'},
|
||||||
managed_objs={"monitor_box"},
|
managed_objs={'monitor_box'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_size(
|
def on_value_changed__center_size(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets['Size']
|
||||||
size = tuple([
|
size = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_size, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_MONITOR_BOX]
|
geo_nodes = bpy.data.node_groups[GEONODES_MONITOR_BOX]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["monitor_box"].sync_geonodes_modifier(
|
managed_objs['monitor_box'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Size"].identifier: size,
|
geonodes_interface['Size'].identifier: size,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["monitor_box"].bl_object("MESH").location = center
|
managed_objs['monitor_box'].bl_object('MESH').location = center
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Preview - Show Preview
|
# - Preview - Show Preview
|
||||||
####################
|
####################
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"monitor_box"},
|
managed_objs={'monitor_box'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["monitor_box"].show_preview("MESH")
|
managed_objs['monitor_box'].show_preview('MESH')
|
||||||
self.on_value_changed__center_size()
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
EHFieldMonitorNode,
|
EHFieldMonitorNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.EHFieldMonitor: (ct.NodeCategory.MAXWELLSIM_MONITORS)}
|
||||||
ct.NodeType.EHFieldMonitor: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_MONITORS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -15,48 +15,49 @@ from ... import sockets
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
GEONODES_MONITOR_BOX = "monitor_flux_box"
|
GEONODES_MONITOR_BOX = 'monitor_flux_box'
|
||||||
|
|
||||||
|
|
||||||
class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.FieldPowerFluxMonitor
|
node_type = ct.NodeType.FieldPowerFluxMonitor
|
||||||
bl_label = "Field Power Flux Monitor"
|
bl_label = 'Field Power Flux Monitor'
|
||||||
use_sim_node_name = True
|
use_sim_node_name = True
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Size": sockets.PhysicalSize3DSocketDef(),
|
'Size': sockets.PhysicalSize3DSocketDef(),
|
||||||
"Samples/Space": sockets.Integer3DVectorSocketDef(
|
'Samples/Space': sockets.Integer3DVectorSocketDef(
|
||||||
default_value=sp.Matrix([10, 10, 10])
|
default_value=sp.Matrix([10, 10, 10])
|
||||||
),
|
),
|
||||||
"Direction": sockets.BoolSocketDef(),
|
'Direction': sockets.BoolSocketDef(),
|
||||||
}
|
}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Freq Domain": {
|
'Freq Domain': {
|
||||||
"Freqs": sockets.PhysicalFreqSocketDef(
|
'Freqs': sockets.PhysicalFreqSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Time Domain": {
|
'Time Domain': {
|
||||||
"Rec Start": sockets.PhysicalTimeSocketDef(),
|
'Rec Start': sockets.PhysicalTimeSocketDef(),
|
||||||
"Rec Stop": sockets.PhysicalTimeSocketDef(
|
'Rec Stop': sockets.PhysicalTimeSocketDef(
|
||||||
default_value=200*spux.fs
|
default_value=200 * spux.fs
|
||||||
),
|
),
|
||||||
"Samples/Time": sockets.IntegerNumberSocketDef(
|
'Samples/Time': sockets.IntegerNumberSocketDef(
|
||||||
default_value=100,
|
default_value=100,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Monitor": sockets.MaxwellMonitorSocketDef(),
|
'Monitor': sockets.MaxwellMonitorSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"monitor_box": ct.schemas.ManagedObjDef(
|
'monitor_box': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,31 +78,39 @@ class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
# - Output Sockets
|
# - Output Sockets
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Monitor",
|
'Monitor',
|
||||||
input_sockets={
|
input_sockets={
|
||||||
"Rec Start", "Rec Stop", "Center", "Size", "Samples/Space",
|
'Rec Start',
|
||||||
"Samples/Time", "Freqs", "Direction",
|
'Rec Stop',
|
||||||
|
'Center',
|
||||||
|
'Size',
|
||||||
|
'Samples/Space',
|
||||||
|
'Samples/Time',
|
||||||
|
'Freqs',
|
||||||
|
'Direction',
|
||||||
},
|
},
|
||||||
props={"active_socket_set", "sim_node_name"}
|
props={'active_socket_set', 'sim_node_name'},
|
||||||
)
|
)
|
||||||
def compute_monitor(self, input_sockets: dict, props: dict) -> td.FieldTimeMonitor:
|
def compute_monitor(
|
||||||
_center = input_sockets["Center"]
|
self, input_sockets: dict, props: dict
|
||||||
_size = input_sockets["Size"]
|
) -> td.FieldTimeMonitor:
|
||||||
_samples_space = input_sockets["Samples/Space"]
|
_center = input_sockets['Center']
|
||||||
|
_size = input_sockets['Size']
|
||||||
|
_samples_space = input_sockets['Samples/Space']
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
samples_space = tuple(_samples_space)
|
samples_space = tuple(_samples_space)
|
||||||
|
|
||||||
direction = "+" if input_sockets["Direction"] else "-"
|
direction = '+' if input_sockets['Direction'] else '-'
|
||||||
|
|
||||||
if props["active_socket_set"] == "Freq Domain":
|
if props['active_socket_set'] == 'Freq Domain':
|
||||||
freqs = input_sockets["Freqs"]
|
freqs = input_sockets['Freqs']
|
||||||
|
|
||||||
return td.FluxMonitor(
|
return td.FluxMonitor(
|
||||||
center=center,
|
center=center,
|
||||||
size=size,
|
size=size,
|
||||||
name=props["sim_node_name"],
|
name=props['sim_node_name'],
|
||||||
interval_space=samples_space,
|
interval_space=samples_space,
|
||||||
freqs=[
|
freqs=[
|
||||||
float(spu.convert_to(freq, spu.hertz) / spu.hertz)
|
float(spu.convert_to(freq, spu.hertz) / spu.hertz)
|
||||||
|
@ -110,9 +119,9 @@ class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
normal_dir=direction,
|
normal_dir=direction,
|
||||||
)
|
)
|
||||||
else: ## Time Domain
|
else: ## Time Domain
|
||||||
_rec_start = input_sockets["Rec Start"]
|
_rec_start = input_sockets['Rec Start']
|
||||||
_rec_stop = input_sockets["Rec Stop"]
|
_rec_stop = input_sockets['Rec Stop']
|
||||||
samples_time = input_sockets["Samples/Time"]
|
samples_time = input_sockets['Samples/Time']
|
||||||
|
|
||||||
rec_start = spu.convert_to(_rec_start, spu.second) / spu.second
|
rec_start = spu.convert_to(_rec_start, spu.second) / spu.second
|
||||||
rec_stop = spu.convert_to(_rec_stop, spu.second) / spu.second
|
rec_stop = spu.convert_to(_rec_stop, spu.second) / spu.second
|
||||||
|
@ -120,7 +129,7 @@ class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
return td.FieldTimeMonitor(
|
return td.FieldTimeMonitor(
|
||||||
center=center,
|
center=center,
|
||||||
size=size,
|
size=size,
|
||||||
name=props["sim_node_name"],
|
name=props['sim_node_name'],
|
||||||
start=rec_start,
|
start=rec_start,
|
||||||
stop=rec_stop,
|
stop=rec_stop,
|
||||||
interval=samples_time,
|
interval=samples_time,
|
||||||
|
@ -131,63 +140,64 @@ class FieldPowerFluxMonitorNode(base.MaxwellSimNode):
|
||||||
# - Preview - Changes to Input Sockets
|
# - Preview - Changes to Input Sockets
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Size"},
|
socket_name={'Center', 'Size'},
|
||||||
input_sockets={"Center", "Size", "Direction"},
|
input_sockets={'Center', 'Size', 'Direction'},
|
||||||
managed_objs={"monitor_box"},
|
managed_objs={'monitor_box'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_size(
|
def on_value_changed__center_size(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets['Size']
|
||||||
size = tuple([
|
size = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_size, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_MONITOR_BOX]
|
geo_nodes = bpy.data.node_groups[GEONODES_MONITOR_BOX]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["monitor_box"].sync_geonodes_modifier(
|
managed_objs['monitor_box'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Size"].identifier: size,
|
geonodes_interface['Size'].identifier: size,
|
||||||
geonodes_interface["Direction"].identifier: input_sockets["Direction"],
|
geonodes_interface['Direction'].identifier: input_sockets[
|
||||||
|
'Direction'
|
||||||
|
],
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["monitor_box"].bl_object("MESH").location = center
|
managed_objs['monitor_box'].bl_object('MESH').location = center
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Preview - Show Preview
|
# - Preview - Show Preview
|
||||||
####################
|
####################
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"monitor_box"},
|
managed_objs={'monitor_box'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["monitor_box"].show_preview("MESH")
|
managed_objs['monitor_box'].show_preview('MESH')
|
||||||
self.on_value_changed__center_size()
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
@ -195,7 +205,5 @@ BL_REGISTER = [
|
||||||
FieldPowerFluxMonitorNode,
|
FieldPowerFluxMonitorNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
ct.NodeType.FieldPowerFluxMonitor: (
|
ct.NodeType.FieldPowerFluxMonitor: (ct.NodeCategory.MAXWELLSIM_MONITORS)
|
||||||
ct.NodeCategory.MAXWELLSIM_MONITORS
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,12 @@ from .... import contracts as ct
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Operators
|
# - Operators
|
||||||
####################
|
####################
|
||||||
class JSONFileExporterSaveJSON(bpy.types.Operator):
|
class JSONFileExporterSaveJSON(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.json_file_exporter_save_json"
|
bl_idname = 'blender_maxwell.json_file_exporter_save_json'
|
||||||
bl_label = "Save the JSON of what's linked into a JSONFileExporterNode."
|
bl_label = "Save the JSON of what's linked into a JSONFileExporterNode."
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -27,26 +28,27 @@ class JSONFileExporterSaveJSON(bpy.types.Operator):
|
||||||
node.export_data_as_json()
|
node.export_data_as_json()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node
|
# - Node
|
||||||
####################
|
####################
|
||||||
class JSONFileExporterNode(base.MaxwellSimNode):
|
class JSONFileExporterNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.JSONFileExporter
|
node_type = ct.NodeType.JSONFileExporter
|
||||||
|
|
||||||
bl_label = "JSON File Exporter"
|
bl_label = 'JSON File Exporter'
|
||||||
#bl_icon = constants.ICON_SIM_INPUT
|
# bl_icon = constants.ICON_SIM_INPUT
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Data": sockets.AnySocketDef(),
|
'Data': sockets.AnySocketDef(),
|
||||||
"JSON Path": sockets.FilePathSocketDef(
|
'JSON Path': sockets.FilePathSocketDef(
|
||||||
default_path=Path("simulation.json")
|
default_path=Path('simulation.json')
|
||||||
),
|
),
|
||||||
"JSON Indent": sockets.IntegerNumberSocketDef(
|
'JSON Indent': sockets.IntegerNumberSocketDef(
|
||||||
default_value=4,
|
default_value=4,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"JSON String": sockets.StringSocketDef(),
|
'JSON String': sockets.StringSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -57,31 +59,33 @@ class JSONFileExporterNode(base.MaxwellSimNode):
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
layout: bpy.types.UILayout,
|
layout: bpy.types.UILayout,
|
||||||
) -> None:
|
) -> None:
|
||||||
layout.operator(JSONFileExporterSaveJSON.bl_idname, text="Save JSON")
|
layout.operator(JSONFileExporterSaveJSON.bl_idname, text='Save JSON')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Methods
|
# - Methods
|
||||||
####################
|
####################
|
||||||
def export_data_as_json(self) -> None:
|
def export_data_as_json(self) -> None:
|
||||||
if (json_str := self.compute_output("JSON String")):
|
if json_str := self.compute_output('JSON String'):
|
||||||
data_dict = json.loads(json_str)
|
data_dict = json.loads(json_str)
|
||||||
with self._compute_input("JSON Path").open("w") as f:
|
with self._compute_input('JSON Path').open('w') as f:
|
||||||
indent = self._compute_input("JSON Indent")
|
indent = self._compute_input('JSON Indent')
|
||||||
json.dump(data_dict, f, ensure_ascii=False, indent=indent)
|
json.dump(data_dict, f, ensure_ascii=False, indent=indent)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Sockets
|
# - Output Sockets
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"JSON String",
|
'JSON String',
|
||||||
input_sockets={"Data"},
|
input_sockets={'Data'},
|
||||||
)
|
)
|
||||||
def compute_json_string(self, input_sockets: dict[str, typ.Any]) -> str | None:
|
def compute_json_string(
|
||||||
if not (data := input_sockets["Data"]):
|
self, input_sockets: dict[str, typ.Any]
|
||||||
|
) -> str | None:
|
||||||
|
if not (data := input_sockets['Data']):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Tidy3D Objects: Call .json()
|
# Tidy3D Objects: Call .json()
|
||||||
if hasattr(data, "json"):
|
if hasattr(data, 'json'):
|
||||||
return data.json()
|
return data.json()
|
||||||
|
|
||||||
# Pydantic Models: Call .model_dump_json()
|
# Pydantic Models: Call .model_dump_json()
|
||||||
|
|
|
@ -16,25 +16,25 @@ from .... import contracts as ct
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Web Uploader / Loader / Runner / Releaser
|
# - Web Uploader / Loader / Runner / Releaser
|
||||||
####################
|
####################
|
||||||
class UploadSimulation(bpy.types.Operator):
|
class UploadSimulation(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.nodes__upload_simulation"
|
bl_idname = 'blender_maxwell.nodes__upload_simulation'
|
||||||
bl_label = "Upload Tidy3D Simulation"
|
bl_label = 'Upload Tidy3D Simulation'
|
||||||
bl_description = "Upload the attached (locked) simulation, such that it is ready to run on the Tidy3D cloud"
|
bl_description = 'Upload the attached (locked) simulation, such that it is ready to run on the Tidy3D cloud'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (
|
return (
|
||||||
hasattr(context, "node")
|
hasattr(context, 'node')
|
||||||
and hasattr(context.node, "node_type")
|
and hasattr(context.node, 'node_type')
|
||||||
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
||||||
|
|
||||||
and context.node.lock_tree
|
and context.node.lock_tree
|
||||||
and tdcloud.IS_AUTHENTICATED
|
and tdcloud.IS_AUTHENTICATED
|
||||||
and not context.node.tracked_task_id
|
and not context.node.tracked_task_id
|
||||||
and context.node.inputs["FDTD Sim"].is_linked
|
and context.node.inputs['FDTD Sim'].is_linked
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
@ -42,24 +42,27 @@ class UploadSimulation(bpy.types.Operator):
|
||||||
node.upload_sim()
|
node.upload_sim()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class RunSimulation(bpy.types.Operator):
|
class RunSimulation(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.nodes__run_simulation"
|
bl_idname = 'blender_maxwell.nodes__run_simulation'
|
||||||
bl_label = "Run Tracked Tidy3D Sim"
|
bl_label = 'Run Tracked Tidy3D Sim'
|
||||||
bl_description = "Run the currently tracked simulation task"
|
bl_description = 'Run the currently tracked simulation task'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (
|
return (
|
||||||
hasattr(context, "node")
|
hasattr(context, 'node')
|
||||||
and hasattr(context.node, "node_type")
|
and hasattr(context.node, 'node_type')
|
||||||
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
||||||
|
|
||||||
and tdcloud.IS_AUTHENTICATED
|
and tdcloud.IS_AUTHENTICATED
|
||||||
and context.node.tracked_task_id
|
and context.node.tracked_task_id
|
||||||
and (task_info := tdcloud.TidyCloudTasks.task_info(
|
and (
|
||||||
|
task_info := tdcloud.TidyCloudTasks.task_info(
|
||||||
context.node.tracked_task_id
|
context.node.tracked_task_id
|
||||||
)) is not None
|
)
|
||||||
and task_info.status == "draft"
|
)
|
||||||
|
is not None
|
||||||
|
and task_info.status == 'draft'
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
@ -67,18 +70,18 @@ class RunSimulation(bpy.types.Operator):
|
||||||
node.run_tracked_task()
|
node.run_tracked_task()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ReloadTrackedTask(bpy.types.Operator):
|
class ReloadTrackedTask(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.nodes__reload_tracked_task"
|
bl_idname = 'blender_maxwell.nodes__reload_tracked_task'
|
||||||
bl_label = "Reload Tracked Tidy3D Cloud Task"
|
bl_label = 'Reload Tracked Tidy3D Cloud Task'
|
||||||
bl_description = "Reload the currently tracked simulation task"
|
bl_description = 'Reload the currently tracked simulation task'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (
|
return (
|
||||||
hasattr(context, "node")
|
hasattr(context, 'node')
|
||||||
and hasattr(context.node, "node_type")
|
and hasattr(context.node, 'node_type')
|
||||||
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
||||||
|
|
||||||
and tdcloud.IS_AUTHENTICATED
|
and tdcloud.IS_AUTHENTICATED
|
||||||
and context.node.tracked_task_id
|
and context.node.tracked_task_id
|
||||||
)
|
)
|
||||||
|
@ -94,18 +97,18 @@ class ReloadTrackedTask(bpy.types.Operator):
|
||||||
cloud_task = tdcloud.TidyCloudTasks.update_task(cloud_task)
|
cloud_task = tdcloud.TidyCloudTasks.update_task(cloud_task)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class EstCostTrackedTask(bpy.types.Operator):
|
class EstCostTrackedTask(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.nodes__est_cost_tracked_task"
|
bl_idname = 'blender_maxwell.nodes__est_cost_tracked_task'
|
||||||
bl_label = "Est Cost of Tracked Tidy3D Cloud Task"
|
bl_label = 'Est Cost of Tracked Tidy3D Cloud Task'
|
||||||
bl_description = "Reload the currently tracked simulation task"
|
bl_description = 'Reload the currently tracked simulation task'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (
|
return (
|
||||||
hasattr(context, "node")
|
hasattr(context, 'node')
|
||||||
and hasattr(context.node, "node_type")
|
and hasattr(context.node, 'node_type')
|
||||||
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
||||||
|
|
||||||
and tdcloud.IS_AUTHENTICATED
|
and tdcloud.IS_AUTHENTICATED
|
||||||
and context.node.tracked_task_id
|
and context.node.tracked_task_id
|
||||||
)
|
)
|
||||||
|
@ -113,47 +116,50 @@ class EstCostTrackedTask(bpy.types.Operator):
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
node = context.node
|
node = context.node
|
||||||
if (
|
if (
|
||||||
task_info := tdcloud.TidyCloudTasks.task_info(context.node.tracked_task_id)
|
task_info := tdcloud.TidyCloudTasks.task_info(
|
||||||
|
context.node.tracked_task_id
|
||||||
|
)
|
||||||
) is None:
|
) is None:
|
||||||
msg = "Tried to estimate cost of tracked task, but it doesn't exist"
|
msg = (
|
||||||
|
"Tried to estimate cost of tracked task, but it doesn't exist"
|
||||||
|
)
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
node.cache_est_cost = task_info.cost_est()
|
node.cache_est_cost = task_info.cost_est()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ReleaseTrackedTask(bpy.types.Operator):
|
class ReleaseTrackedTask(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.nodes__release_tracked_task"
|
bl_idname = 'blender_maxwell.nodes__release_tracked_task'
|
||||||
bl_label = "Release Tracked Tidy3D Cloud Task"
|
bl_label = 'Release Tracked Tidy3D Cloud Task'
|
||||||
bl_description = "Release the currently tracked simulation task"
|
bl_description = 'Release the currently tracked simulation task'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (
|
return (
|
||||||
hasattr(context, "node")
|
hasattr(context, 'node')
|
||||||
and hasattr(context.node, "node_type")
|
and hasattr(context.node, 'node_type')
|
||||||
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
and context.node.node_type == ct.NodeType.Tidy3DWebExporter
|
||||||
|
# and tdcloud.IS_AUTHENTICATED
|
||||||
#and tdcloud.IS_AUTHENTICATED
|
|
||||||
and context.node.tracked_task_id
|
and context.node.tracked_task_id
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
node = context.node
|
node = context.node
|
||||||
node.tracked_task_id = ""
|
node.tracked_task_id = ''
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node
|
# - Node
|
||||||
####################
|
####################
|
||||||
class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.Tidy3DWebExporter
|
node_type = ct.NodeType.Tidy3DWebExporter
|
||||||
bl_label = "Tidy3D Web Exporter"
|
bl_label = 'Tidy3D Web Exporter'
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"FDTD Sim": sockets.MaxwellFDTDSimSocketDef(),
|
'FDTD Sim': sockets.MaxwellFDTDSimSocketDef(),
|
||||||
"Cloud Task": sockets.Tidy3DCloudTaskSocketDef(
|
'Cloud Task': sockets.Tidy3DCloudTaskSocketDef(
|
||||||
should_exist=False,
|
should_exist=False,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -162,27 +168,27 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
lock_tree: bpy.props.BoolProperty(
|
lock_tree: bpy.props.BoolProperty(
|
||||||
name="Whether to lock the attached tree",
|
name='Whether to lock the attached tree',
|
||||||
description="Whether or not to lock the attached tree",
|
description='Whether or not to lock the attached tree',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_lock_tree(context),
|
update=lambda self, context: self.sync_lock_tree(context),
|
||||||
)
|
)
|
||||||
tracked_task_id: bpy.props.StringProperty(
|
tracked_task_id: bpy.props.StringProperty(
|
||||||
name="Tracked Task ID",
|
name='Tracked Task ID',
|
||||||
description="The currently tracked task ID",
|
description='The currently tracked task ID',
|
||||||
default="",
|
default='',
|
||||||
update=lambda self, context: self.sync_tracked_task_id(context),
|
update=lambda self, context: self.sync_tracked_task_id(context),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
cache_total_monitor_data: bpy.props.FloatProperty(
|
cache_total_monitor_data: bpy.props.FloatProperty(
|
||||||
name="(Cached) Total Monitor Data",
|
name='(Cached) Total Monitor Data',
|
||||||
description="Required storage space by all monitors",
|
description='Required storage space by all monitors',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
)
|
)
|
||||||
cache_est_cost: bpy.props.FloatProperty(
|
cache_est_cost: bpy.props.FloatProperty(
|
||||||
name="(Cached) Estimated Total Cost",
|
name='(Cached) Estimated Total Cost',
|
||||||
description="Est. Cost in FlexCompute units",
|
description='Est. Cost in FlexCompute units',
|
||||||
default=-1.0,
|
default=-1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -191,16 +197,17 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
####################
|
####################
|
||||||
def sync_lock_tree(self, context):
|
def sync_lock_tree(self, context):
|
||||||
if self.lock_tree:
|
if self.lock_tree:
|
||||||
self.trigger_action("enable_lock")
|
self.trigger_action('enable_lock')
|
||||||
self.locked = False
|
self.locked = False
|
||||||
for bl_socket in self.inputs:
|
for bl_socket in self.inputs:
|
||||||
if bl_socket.name == "FDTD Sim": continue
|
if bl_socket.name == 'FDTD Sim':
|
||||||
|
continue
|
||||||
bl_socket.locked = False
|
bl_socket.locked = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.trigger_action("disable_lock")
|
self.trigger_action('disable_lock')
|
||||||
|
|
||||||
self.sync_prop("lock_tree", context)
|
self.sync_prop('lock_tree', context)
|
||||||
|
|
||||||
def sync_tracked_task_id(self, context):
|
def sync_tracked_task_id(self, context):
|
||||||
# Select Tracked Task
|
# Select Tracked Task
|
||||||
|
@ -209,44 +216,43 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
task_info = tdcloud.TidyCloudTasks.task_info(self.tracked_task_id)
|
task_info = tdcloud.TidyCloudTasks.task_info(self.tracked_task_id)
|
||||||
|
|
||||||
self.loose_output_sockets = {
|
self.loose_output_sockets = {
|
||||||
"Cloud Task": sockets.Tidy3DCloudTaskSocketDef(
|
'Cloud Task': sockets.Tidy3DCloudTaskSocketDef(
|
||||||
should_exist=True,
|
should_exist=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
self.inputs["Cloud Task"].locked = True
|
self.inputs['Cloud Task'].locked = True
|
||||||
|
|
||||||
# Release Tracked Task
|
# Release Tracked Task
|
||||||
else:
|
else:
|
||||||
self.cache_est_cost = -1.0
|
self.cache_est_cost = -1.0
|
||||||
self.loose_output_sockets = {}
|
self.loose_output_sockets = {}
|
||||||
self.inputs["Cloud Task"].sync_prepare_new_task()
|
self.inputs['Cloud Task'].sync_prepare_new_task()
|
||||||
self.inputs["Cloud Task"].locked = False
|
self.inputs['Cloud Task'].locked = False
|
||||||
|
|
||||||
self.sync_prop("tracked_task_id", context)
|
self.sync_prop('tracked_task_id', context)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Callbacks
|
# - Output Socket Callbacks
|
||||||
####################
|
####################
|
||||||
def validate_sim(self):
|
def validate_sim(self):
|
||||||
if (sim := self._compute_input("FDTD Sim")) is None:
|
if (sim := self._compute_input('FDTD Sim')) is None:
|
||||||
msg = "Tried to validate simulation, but none is attached"
|
msg = 'Tried to validate simulation, but none is attached'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
sim.validate_pre_upload(source_required = True)
|
sim.validate_pre_upload(source_required=True)
|
||||||
|
|
||||||
def upload_sim(self):
|
def upload_sim(self):
|
||||||
if (sim := self._compute_input("FDTD Sim")) is None:
|
if (sim := self._compute_input('FDTD Sim')) is None:
|
||||||
msg = "Tried to upload simulation, but none is attached"
|
msg = 'Tried to upload simulation, but none is attached'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(new_task := self._compute_input("Cloud Task")) is None
|
new_task := self._compute_input('Cloud Task')
|
||||||
or isinstance(
|
) is None or isinstance(
|
||||||
new_task,
|
new_task,
|
||||||
tdcloud.CloudTask,
|
tdcloud.CloudTask,
|
||||||
)
|
|
||||||
):
|
):
|
||||||
msg = "Tried to upload simulation to new task, but existing task was selected"
|
msg = 'Tried to upload simulation to new task, but existing task was selected'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# Create Cloud Task
|
# Create Cloud Task
|
||||||
|
@ -261,7 +267,7 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
# Declare to Cloud Task that it Exists Now
|
# Declare to Cloud Task that it Exists Now
|
||||||
## This will change the UI to not allow free-text input.
|
## This will change the UI to not allow free-text input.
|
||||||
## If the socket is linked, this errors.
|
## If the socket is linked, this errors.
|
||||||
self.inputs["Cloud Task"].sync_created_new_task(cloud_task)
|
self.inputs['Cloud Task'].sync_created_new_task(cloud_task)
|
||||||
|
|
||||||
# Track the Newly Uploaded Task ID
|
# Track the Newly Uploaded Task ID
|
||||||
self.tracked_task_id = cloud_task.task_id
|
self.tracked_task_id = cloud_task.task_id
|
||||||
|
@ -274,7 +280,9 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
cloud_task.submit()
|
cloud_task.submit()
|
||||||
tdcloud.TidyCloudTasks.update_task(cloud_task) ## TODO: Check that status is actually immediately updated.
|
tdcloud.TidyCloudTasks.update_task(
|
||||||
|
cloud_task
|
||||||
|
) ## TODO: Check that status is actually immediately updated.
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
|
@ -284,93 +292,94 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator(
|
row.operator(
|
||||||
UploadSimulation.bl_idname,
|
UploadSimulation.bl_idname,
|
||||||
text="Upload",
|
text='Upload',
|
||||||
)
|
)
|
||||||
tree_lock_icon = "LOCKED" if self.lock_tree else "UNLOCKED"
|
tree_lock_icon = 'LOCKED' if self.lock_tree else 'UNLOCKED'
|
||||||
row.prop(self, "lock_tree", toggle=True, icon=tree_lock_icon, text="")
|
row.prop(self, 'lock_tree', toggle=True, icon=tree_lock_icon, text='')
|
||||||
|
|
||||||
# Row: Run Sim Buttons
|
# Row: Run Sim Buttons
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator(
|
row.operator(
|
||||||
RunSimulation.bl_idname,
|
RunSimulation.bl_idname,
|
||||||
text="Run",
|
text='Run',
|
||||||
)
|
)
|
||||||
if self.tracked_task_id:
|
if self.tracked_task_id:
|
||||||
tree_lock_icon = "LOOP_BACK"
|
tree_lock_icon = 'LOOP_BACK'
|
||||||
row.operator(
|
row.operator(
|
||||||
ReleaseTrackedTask.bl_idname,
|
ReleaseTrackedTask.bl_idname,
|
||||||
icon="LOOP_BACK",
|
icon='LOOP_BACK',
|
||||||
text="",
|
text='',
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw_info(self, context, layout):
|
def draw_info(self, context, layout):
|
||||||
# Connection Info
|
# Connection Info
|
||||||
auth_icon = "CHECKBOX_HLT" if tdcloud.IS_AUTHENTICATED else "CHECKBOX_DEHLT"
|
auth_icon = (
|
||||||
conn_icon = "CHECKBOX_HLT" if tdcloud.IS_ONLINE else "CHECKBOX_DEHLT"
|
'CHECKBOX_HLT' if tdcloud.IS_AUTHENTICATED else 'CHECKBOX_DEHLT'
|
||||||
|
)
|
||||||
|
conn_icon = 'CHECKBOX_HLT' if tdcloud.IS_ONLINE else 'CHECKBOX_DEHLT'
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.alignment = "CENTER"
|
row.alignment = 'CENTER'
|
||||||
row.label(text="Cloud Status")
|
row.label(text='Cloud Status')
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
split = box.split(factor=0.85)
|
split = box.split(factor=0.85)
|
||||||
|
|
||||||
## Split: Left Column
|
## Split: Left Column
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(text="Authed")
|
col.label(text='Authed')
|
||||||
col.label(text="Connected")
|
col.label(text='Connected')
|
||||||
|
|
||||||
## Split: Right Column
|
## Split: Right Column
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(icon=auth_icon)
|
col.label(icon=auth_icon)
|
||||||
col.label(icon=conn_icon)
|
col.label(icon=conn_icon)
|
||||||
|
|
||||||
|
|
||||||
# Simulation Info
|
# Simulation Info
|
||||||
if self.inputs["FDTD Sim"].is_linked:
|
if self.inputs['FDTD Sim'].is_linked:
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.alignment = "CENTER"
|
row.alignment = 'CENTER'
|
||||||
row.label(text="Sim Info")
|
row.label(text='Sim Info')
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
split = box.split(factor=0.4)
|
split = box.split(factor=0.4)
|
||||||
|
|
||||||
## Split: Left Column
|
## Split: Left Column
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(text="𝝨 Output")
|
col.label(text='𝝨 Output')
|
||||||
|
|
||||||
## Split: Right Column
|
## Split: Right Column
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.alignment = "RIGHT"
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=f"{self.cache_total_monitor_data / 1_000_000:.2f}MB")
|
col.label(
|
||||||
|
text=f'{self.cache_total_monitor_data / 1_000_000:.2f}MB'
|
||||||
|
)
|
||||||
|
|
||||||
# Cloud Task Info
|
# Cloud Task Info
|
||||||
if self.tracked_task_id and tdcloud.IS_AUTHENTICATED:
|
if self.tracked_task_id and tdcloud.IS_AUTHENTICATED:
|
||||||
task_info = tdcloud.TidyCloudTasks.task_info(
|
task_info = tdcloud.TidyCloudTasks.task_info(self.tracked_task_id)
|
||||||
self.tracked_task_id
|
if task_info is None:
|
||||||
)
|
return
|
||||||
if task_info is None: return
|
|
||||||
|
|
||||||
## Header
|
## Header
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.alignment = "CENTER"
|
row.alignment = 'CENTER'
|
||||||
row.label(text="Task Info")
|
row.label(text='Task Info')
|
||||||
|
|
||||||
## Progress Bar
|
## Progress Bar
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.progress(
|
row.progress(
|
||||||
factor=0.0,
|
factor=0.0,
|
||||||
type="BAR",
|
type='BAR',
|
||||||
text=f"Status: {task_info.status.capitalize()}",
|
text=f'Status: {task_info.status.capitalize()}',
|
||||||
)
|
)
|
||||||
row.operator(
|
row.operator(
|
||||||
ReloadTrackedTask.bl_idname,
|
ReloadTrackedTask.bl_idname,
|
||||||
text="",
|
text='',
|
||||||
icon="FILE_REFRESH",
|
icon='FILE_REFRESH',
|
||||||
)
|
)
|
||||||
row.operator(
|
row.operator(
|
||||||
EstCostTrackedTask.bl_idname,
|
EstCostTrackedTask.bl_idname,
|
||||||
text="",
|
text='',
|
||||||
icon="SORTTIME",
|
icon='SORTTIME',
|
||||||
)
|
)
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
@ -379,19 +388,27 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
|
|
||||||
## Split: Left Column
|
## Split: Left Column
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(text="Status")
|
col.label(text='Status')
|
||||||
col.label(text="Est. Cost")
|
col.label(text='Est. Cost')
|
||||||
col.label(text="Real Cost")
|
col.label(text='Real Cost')
|
||||||
|
|
||||||
## Split: Right Column
|
## Split: Right Column
|
||||||
cost_est = f"{self.cache_est_cost:.2f}" if self.cache_est_cost >= 0 else "TBD"
|
cost_est = (
|
||||||
cost_real = f"{task_info.cost_real:.2f}" if task_info.cost_real is not None else "TBD"
|
f'{self.cache_est_cost:.2f}'
|
||||||
|
if self.cache_est_cost >= 0
|
||||||
|
else 'TBD'
|
||||||
|
)
|
||||||
|
cost_real = (
|
||||||
|
f'{task_info.cost_real:.2f}'
|
||||||
|
if task_info.cost_real is not None
|
||||||
|
else 'TBD'
|
||||||
|
)
|
||||||
|
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.alignment = "RIGHT"
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=task_info.status.capitalize())
|
col.label(text=task_info.status.capitalize())
|
||||||
col.label(text=f"{cost_est} creds")
|
col.label(text=f'{cost_est} creds')
|
||||||
col.label(text=f"{cost_real} creds")
|
col.label(text=f'{cost_real} creds')
|
||||||
|
|
||||||
# Connection Information
|
# Connection Information
|
||||||
|
|
||||||
|
@ -399,13 +416,14 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
# - Output Methods
|
# - Output Methods
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Cloud Task",
|
'Cloud Task',
|
||||||
input_sockets={"Cloud Task"},
|
input_sockets={'Cloud Task'},
|
||||||
)
|
)
|
||||||
def compute_cloud_task(self, input_sockets: dict) -> tdcloud.CloudTask | None:
|
def compute_cloud_task(
|
||||||
|
self, input_sockets: dict
|
||||||
|
) -> tdcloud.CloudTask | None:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
cloud_task := input_sockets["Cloud Task"],
|
cloud_task := input_sockets['Cloud Task'], tdcloud.CloudTask
|
||||||
tdcloud.CloudTask
|
|
||||||
):
|
):
|
||||||
return cloud_task
|
return cloud_task
|
||||||
|
|
||||||
|
@ -415,15 +433,15 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
# - Output Methods
|
# - Output Methods
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="FDTD Sim",
|
socket_name='FDTD Sim',
|
||||||
input_sockets={"FDTD Sim"},
|
input_sockets={'FDTD Sim'},
|
||||||
)
|
)
|
||||||
def on_value_changed__fdtd_sim(self, input_sockets):
|
def on_value_changed__fdtd_sim(self, input_sockets):
|
||||||
if (sim := self._compute_input("FDTD Sim")) is None:
|
if (sim := self._compute_input('FDTD Sim')) is None:
|
||||||
self.cache_total_monitor_data = 0
|
self.cache_total_monitor_data = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
sim.validate_pre_upload(source_required = True)
|
sim.validate_pre_upload(source_required=True)
|
||||||
self.cache_total_monitor_data = sum(sim.monitors_data_size.values())
|
self.cache_total_monitor_data = sum(sim.monitors_data_size.values())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ from ...managed_objs import managed_bl_object
|
||||||
|
|
||||||
|
|
||||||
class ConsoleViewOperator(bpy.types.Operator):
|
class ConsoleViewOperator(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.console_view_operator"
|
bl_idname = 'blender_maxwell.console_view_operator'
|
||||||
bl_label = "View Plots"
|
bl_label = 'View Plots'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -27,9 +27,10 @@ class ConsoleViewOperator(bpy.types.Operator):
|
||||||
node.print_data_to_console()
|
node.print_data_to_console()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class RefreshPlotViewOperator(bpy.types.Operator):
|
class RefreshPlotViewOperator(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.refresh_plot_view_operator"
|
bl_idname = 'blender_maxwell.refresh_plot_view_operator'
|
||||||
bl_label = "Refresh Plots"
|
bl_label = 'Refresh Plots'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -37,35 +38,38 @@ class RefreshPlotViewOperator(bpy.types.Operator):
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
node = context.node
|
node = context.node
|
||||||
node.trigger_action("value_changed", "Data")
|
node.trigger_action('value_changed', 'Data')
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node
|
# - Node
|
||||||
####################
|
####################
|
||||||
class ViewerNode(base.MaxwellSimNode):
|
class ViewerNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.Viewer
|
node_type = ct.NodeType.Viewer
|
||||||
bl_label = "Viewer"
|
bl_label = 'Viewer'
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Data": sockets.AnySocketDef(),
|
'Data': sockets.AnySocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
auto_plot: bpy.props.BoolProperty(
|
auto_plot: bpy.props.BoolProperty(
|
||||||
name="Auto-Plot",
|
name='Auto-Plot',
|
||||||
description="Whether to auto-plot anything plugged into the viewer node",
|
description='Whether to auto-plot anything plugged into the viewer node',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("auto_plot", context),
|
update=lambda self, context: self.sync_prop('auto_plot', context),
|
||||||
)
|
)
|
||||||
|
|
||||||
auto_3d_preview: bpy.props.BoolProperty(
|
auto_3d_preview: bpy.props.BoolProperty(
|
||||||
name="Auto 3D Preview",
|
name='Auto 3D Preview',
|
||||||
description="Whether to auto-preview anything 3D, that's plugged into the viewer node",
|
description="Whether to auto-preview anything 3D, that's plugged into the viewer node",
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("auto_3d_preview", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'auto_3d_preview', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -76,34 +80,34 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
|
|
||||||
# Split LHS
|
# Split LHS
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(text="Console")
|
col.label(text='Console')
|
||||||
col.label(text="Plot")
|
col.label(text='Plot')
|
||||||
col.label(text="3D")
|
col.label(text='3D')
|
||||||
|
|
||||||
# Split RHS
|
# Split RHS
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
|
|
||||||
## Console Options
|
## Console Options
|
||||||
col.operator(ConsoleViewOperator.bl_idname, text="Print")
|
col.operator(ConsoleViewOperator.bl_idname, text='Print')
|
||||||
|
|
||||||
## Plot Options
|
## Plot Options
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.prop(self, "auto_plot", text="Plot", toggle=True)
|
row.prop(self, 'auto_plot', text='Plot', toggle=True)
|
||||||
row.operator(
|
row.operator(
|
||||||
RefreshPlotViewOperator.bl_idname,
|
RefreshPlotViewOperator.bl_idname,
|
||||||
text="",
|
text='',
|
||||||
icon="FILE_REFRESH",
|
icon='FILE_REFRESH',
|
||||||
)
|
)
|
||||||
|
|
||||||
## 3D Preview Options
|
## 3D Preview Options
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.prop(self, "auto_3d_preview", text="3D Preview", toggle=True)
|
row.prop(self, 'auto_3d_preview', text='3D Preview', toggle=True)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Methods
|
# - Methods
|
||||||
####################
|
####################
|
||||||
def print_data_to_console(self):
|
def print_data_to_console(self):
|
||||||
if not (data := self._compute_input("Data")):
|
if not (data := self._compute_input('Data')):
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(data, sp.Basic):
|
if isinstance(data, sp.Basic):
|
||||||
|
@ -115,14 +119,14 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
# - Updates
|
# - Updates
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="Data",
|
socket_name='Data',
|
||||||
props={"auto_3d_preview"},
|
props={'auto_3d_preview'},
|
||||||
)
|
)
|
||||||
def on_value_changed__data(self, props):
|
def on_value_changed__data(self, props):
|
||||||
# Show Plot
|
# Show Plot
|
||||||
## Don't have to un-show other plots.
|
## Don't have to un-show other plots.
|
||||||
if self.auto_plot:
|
if self.auto_plot:
|
||||||
self.trigger_action("show_plot")
|
self.trigger_action('show_plot')
|
||||||
|
|
||||||
# Remove Anything Previewed
|
# Remove Anything Previewed
|
||||||
preview_collection = managed_bl_object.bl_collection(
|
preview_collection = managed_bl_object.bl_collection(
|
||||||
|
@ -133,12 +137,12 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
preview_collection.objects.unlink(bl_object)
|
preview_collection.objects.unlink(bl_object)
|
||||||
|
|
||||||
# Preview Anything that Should be Previewed (maybe)
|
# Preview Anything that Should be Previewed (maybe)
|
||||||
if props["auto_3d_preview"]:
|
if props['auto_3d_preview']:
|
||||||
self.trigger_action("show_preview")
|
self.trigger_action('show_preview')
|
||||||
|
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
prop_name="auto_3d_preview",
|
prop_name='auto_3d_preview',
|
||||||
props={"auto_3d_preview"},
|
props={'auto_3d_preview'},
|
||||||
)
|
)
|
||||||
def on_value_changed__auto_3d_preview(self, props):
|
def on_value_changed__auto_3d_preview(self, props):
|
||||||
# Remove Anything Previewed
|
# Remove Anything Previewed
|
||||||
|
@ -150,8 +154,8 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
preview_collection.objects.unlink(bl_object)
|
preview_collection.objects.unlink(bl_object)
|
||||||
|
|
||||||
# Preview Anything that Should be Previewed (maybe)
|
# Preview Anything that Should be Previewed (maybe)
|
||||||
if props["auto_3d_preview"]:
|
if props['auto_3d_preview']:
|
||||||
self.trigger_action("show_preview")
|
self.trigger_action('show_preview')
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -162,8 +166,4 @@ BL_REGISTER = [
|
||||||
RefreshPlotViewOperator,
|
RefreshPlotViewOperator,
|
||||||
ViewerNode,
|
ViewerNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.Viewer: (ct.NodeCategory.MAXWELLSIM_OUTPUTS)}
|
||||||
ct.NodeType.Viewer: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_OUTPUTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
from . import sim_domain
|
from . import sim_domain
|
||||||
|
|
||||||
#from . import sim_grid
|
# from . import sim_grid
|
||||||
#from . import sim_grid_axes
|
# from . import sim_grid_axes
|
||||||
|
|
||||||
from . import fdtd_sim
|
from . import fdtd_sim
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*sim_domain.BL_REGISTER,
|
*sim_domain.BL_REGISTER,
|
||||||
# *sim_grid.BL_REGISTER,
|
# *sim_grid.BL_REGISTER,
|
||||||
# *sim_grid_axes.BL_REGISTER,
|
# *sim_grid_axes.BL_REGISTER,
|
||||||
*fdtd_sim.BL_REGISTER,
|
*fdtd_sim.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**sim_domain.BL_NODES,
|
**sim_domain.BL_NODES,
|
||||||
# **sim_grid.BL_NODES,
|
# **sim_grid.BL_NODES,
|
||||||
# **sim_grid_axes.BL_NODES,
|
# **sim_grid_axes.BL_NODES,
|
||||||
**fdtd_sim.BL_NODES,
|
**fdtd_sim.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,52 +6,51 @@ from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class FDTDSimNode(base.MaxwellSimNode):
|
class FDTDSimNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.FDTDSim
|
node_type = ct.NodeType.FDTDSim
|
||||||
bl_label = "FDTD Simulation"
|
bl_label = 'FDTD Simulation'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Domain": sockets.MaxwellSimDomainSocketDef(),
|
'Domain': sockets.MaxwellSimDomainSocketDef(),
|
||||||
"BCs": sockets.MaxwellBoundCondsSocketDef(),
|
'BCs': sockets.MaxwellBoundCondsSocketDef(),
|
||||||
"Sources": sockets.MaxwellSourceSocketDef(
|
'Sources': sockets.MaxwellSourceSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
"Structures": sockets.MaxwellStructureSocketDef(
|
'Structures': sockets.MaxwellStructureSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
"Monitors": sockets.MaxwellMonitorSocketDef(
|
'Monitors': sockets.MaxwellMonitorSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"FDTD Sim": sockets.MaxwellFDTDSimSocketDef(),
|
'FDTD Sim': sockets.MaxwellFDTDSimSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"FDTD Sim",
|
'FDTD Sim',
|
||||||
kind=ct.DataFlowKind.Value,
|
kind=ct.DataFlowKind.Value,
|
||||||
input_sockets={
|
input_sockets={'Sources', 'Structures', 'Domain', 'BCs', 'Monitors'},
|
||||||
"Sources", "Structures", "Domain", "BCs", "Monitors"
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
def compute_fdtd_sim(self, input_sockets: dict) -> sp.Expr:
|
def compute_fdtd_sim(self, input_sockets: dict) -> sp.Expr:
|
||||||
sim_domain = input_sockets["Domain"]
|
sim_domain = input_sockets['Domain']
|
||||||
sources = input_sockets["Sources"]
|
sources = input_sockets['Sources']
|
||||||
structures = input_sockets["Structures"]
|
structures = input_sockets['Structures']
|
||||||
bounds = input_sockets["BCs"]
|
bounds = input_sockets['BCs']
|
||||||
monitors = input_sockets["Monitors"]
|
monitors = input_sockets['Monitors']
|
||||||
|
|
||||||
#if not isinstance(sources, list):
|
# if not isinstance(sources, list):
|
||||||
# sources = [sources]
|
# sources = [sources]
|
||||||
#if not isinstance(structures, list):
|
# if not isinstance(structures, list):
|
||||||
# structures = [structures]
|
# structures = [structures]
|
||||||
#if not isinstance(monitors, list):
|
# if not isinstance(monitors, list):
|
||||||
# monitors = [monitors]
|
# monitors = [monitors]
|
||||||
|
|
||||||
return td.Simulation(
|
return td.Simulation(
|
||||||
|
@ -62,14 +61,11 @@ class FDTDSimNode(base.MaxwellSimNode):
|
||||||
boundary_spec=bounds,
|
boundary_spec=bounds,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
FDTDSimNode,
|
FDTDSimNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.FDTDSim: (ct.NodeCategory.MAXWELLSIM_SIMS)}
|
||||||
ct.NodeType.FDTDSim: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_SIMS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,30 +9,31 @@ from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
|
|
||||||
GEONODES_DOMAIN_BOX = "simdomain_box"
|
GEONODES_DOMAIN_BOX = 'simdomain_box'
|
||||||
|
|
||||||
|
|
||||||
class SimDomainNode(base.MaxwellSimNode):
|
class SimDomainNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.SimDomain
|
node_type = ct.NodeType.SimDomain
|
||||||
bl_label = "Sim Domain"
|
bl_label = 'Sim Domain'
|
||||||
|
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Duration": sockets.PhysicalTimeSocketDef(
|
'Duration': sockets.PhysicalTimeSocketDef(
|
||||||
default_value = 5 * spu.ps,
|
default_value=5 * spu.ps,
|
||||||
default_unit = spu.ps,
|
default_unit=spu.ps,
|
||||||
),
|
),
|
||||||
"Center": sockets.PhysicalSize3DSocketDef(),
|
'Center': sockets.PhysicalSize3DSocketDef(),
|
||||||
"Size": sockets.PhysicalSize3DSocketDef(),
|
'Size': sockets.PhysicalSize3DSocketDef(),
|
||||||
"Grid": sockets.MaxwellSimGridSocketDef(),
|
'Grid': sockets.MaxwellSimGridSocketDef(),
|
||||||
"Ambient Medium": sockets.MaxwellMediumSocketDef(),
|
'Ambient Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Domain": sockets.MaxwellSimDomainSocketDef(),
|
'Domain': sockets.MaxwellSimDomainSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"domain_box": ct.schemas.ManagedObjDef(
|
'domain_box': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,17 +41,19 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
# - Callbacks
|
# - Callbacks
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Domain",
|
'Domain',
|
||||||
input_sockets={"Duration", "Center", "Size", "Grid", "Ambient Medium"},
|
input_sockets={'Duration', 'Center', 'Size', 'Grid', 'Ambient Medium'},
|
||||||
)
|
)
|
||||||
def compute_sim_domain(self, input_sockets: dict) -> sp.Expr:
|
def compute_sim_domain(self, input_sockets: dict) -> sp.Expr:
|
||||||
if all([
|
if all(
|
||||||
(_duration := input_sockets["Duration"]),
|
[
|
||||||
(_center := input_sockets["Center"]),
|
(_duration := input_sockets['Duration']),
|
||||||
(_size := input_sockets["Size"]),
|
(_center := input_sockets['Center']),
|
||||||
(grid := input_sockets["Grid"]),
|
(_size := input_sockets['Size']),
|
||||||
(medium := input_sockets["Ambient Medium"]),
|
(grid := input_sockets['Grid']),
|
||||||
]):
|
(medium := input_sockets['Ambient Medium']),
|
||||||
|
]
|
||||||
|
):
|
||||||
duration = spu.convert_to(_duration, spu.second) / spu.second
|
duration = spu.convert_to(_duration, spu.second) / spu.second
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
|
@ -66,67 +69,62 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
# - Preview
|
# - Preview
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Size"},
|
socket_name={'Center', 'Size'},
|
||||||
input_sockets={"Center", "Size"},
|
input_sockets={'Center', 'Size'},
|
||||||
managed_objs={"domain_box"},
|
managed_objs={'domain_box'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_size(
|
def on_value_changed__center_size(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets['Size']
|
||||||
size = tuple([
|
size = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_size, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_DOMAIN_BOX]
|
geo_nodes = bpy.data.node_groups[GEONODES_DOMAIN_BOX]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["domain_box"].sync_geonodes_modifier(
|
managed_objs['domain_box'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Size"].identifier: size,
|
geonodes_interface['Size'].identifier: size,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["domain_box"].bl_object("MESH").location = center
|
managed_objs['domain_box'].bl_object('MESH').location = center
|
||||||
|
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"domain_box"},
|
managed_objs={'domain_box'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["domain_box"].show_preview("MESH")
|
managed_objs['domain_box'].show_preview('MESH')
|
||||||
self.on_value_changed__center_size()
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
SimDomainNode,
|
SimDomainNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.SimDomain: (ct.NodeCategory.MAXWELLSIM_SIMS)}
|
||||||
ct.NodeType.SimDomain: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_SIMS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
from . import temporal_shapes
|
from . import temporal_shapes
|
||||||
|
|
||||||
from . import point_dipole_source
|
from . import point_dipole_source
|
||||||
#from . import uniform_current_source
|
|
||||||
|
# from . import uniform_current_source
|
||||||
from . import plane_wave_source
|
from . import plane_wave_source
|
||||||
#from . import gaussian_beam_source
|
# from . import gaussian_beam_source
|
||||||
#from . import astigmatic_gaussian_beam_source
|
# from . import astigmatic_gaussian_beam_source
|
||||||
#from . import tfsf_source
|
# from . import tfsf_source
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*temporal_shapes.BL_REGISTER,
|
*temporal_shapes.BL_REGISTER,
|
||||||
*point_dipole_source.BL_REGISTER,
|
*point_dipole_source.BL_REGISTER,
|
||||||
# *uniform_current_source.BL_REGISTER,
|
# *uniform_current_source.BL_REGISTER,
|
||||||
*plane_wave_source.BL_REGISTER,
|
*plane_wave_source.BL_REGISTER,
|
||||||
# *gaussian_beam_source.BL_REGISTER,
|
# *gaussian_beam_source.BL_REGISTER,
|
||||||
# *astigmatic_gaussian_beam_source.BL_REGISTER,
|
# *astigmatic_gaussian_beam_source.BL_REGISTER,
|
||||||
# *tfsf_source.BL_REGISTER,
|
# *tfsf_source.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**temporal_shapes.BL_NODES,
|
**temporal_shapes.BL_NODES,
|
||||||
**point_dipole_source.BL_NODES,
|
**point_dipole_source.BL_NODES,
|
||||||
# **uniform_current_source.BL_NODES,
|
# **uniform_current_source.BL_NODES,
|
||||||
**plane_wave_source.BL_NODES,
|
**plane_wave_source.BL_NODES,
|
||||||
# **gaussian_beam_source.BL_NODES,
|
# **gaussian_beam_source.BL_NODES,
|
||||||
# **astigmatic_gaussian_beam_source.BL_NODES,
|
# **astigmatic_gaussian_beam_source.BL_NODES,
|
||||||
# **tfsf_source.BL_NODES,
|
# **tfsf_source.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
GEONODES_PLANE_WAVE = "source_plane_wave"
|
GEONODES_PLANE_WAVE = 'source_plane_wave'
|
||||||
|
|
||||||
|
|
||||||
def convert_vector_to_spherical(
|
def convert_vector_to_spherical(
|
||||||
v: sp.MatrixBase,
|
v: sp.MatrixBase,
|
||||||
|
@ -25,51 +26,49 @@ def convert_vector_to_spherical(
|
||||||
x, y, z = v
|
x, y, z = v
|
||||||
|
|
||||||
injection_axis = max(
|
injection_axis = max(
|
||||||
('x', abs(x)),
|
('x', abs(x)), ('y', abs(y)), ('z', abs(z)), key=lambda item: item[1]
|
||||||
('y', abs(y)),
|
|
||||||
('z', abs(z)),
|
|
||||||
key=lambda item: item[1]
|
|
||||||
)[0]
|
)[0]
|
||||||
## Select injection axis that minimizes 'theta'
|
## Select injection axis that minimizes 'theta'
|
||||||
|
|
||||||
if injection_axis == "x":
|
if injection_axis == 'x':
|
||||||
direction = "+" if x >= 0 else "-"
|
direction = '+' if x >= 0 else '-'
|
||||||
theta = sp.acos(x / sp.sqrt(x**2 + y**2 + z**2))
|
theta = sp.acos(x / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
phi = sp.atan2(z, y)
|
phi = sp.atan2(z, y)
|
||||||
elif injection_axis == "y":
|
elif injection_axis == 'y':
|
||||||
direction = "+" if y >= 0 else "-"
|
direction = '+' if y >= 0 else '-'
|
||||||
theta = sp.acos(y / sp.sqrt(x**2 + y**2 + z**2))
|
theta = sp.acos(y / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
phi = sp.atan2(x, z)
|
phi = sp.atan2(x, z)
|
||||||
else:
|
else:
|
||||||
direction = "+" if z >= 0 else "-"
|
direction = '+' if z >= 0 else '-'
|
||||||
theta = sp.acos(z / sp.sqrt(x**2 + y**2 + z**2))
|
theta = sp.acos(z / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
phi = sp.atan2(y, x)
|
phi = sp.atan2(y, x)
|
||||||
|
|
||||||
return injection_axis, direction, theta, phi
|
return injection_axis, direction, theta, phi
|
||||||
|
|
||||||
|
|
||||||
class PlaneWaveSourceNode(base.MaxwellSimNode):
|
class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.PlaneWaveSource
|
node_type = ct.NodeType.PlaneWaveSource
|
||||||
bl_label = "Plane Wave Source"
|
bl_label = 'Plane Wave Source'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Direction": sockets.Real3DVectorSocketDef(
|
'Direction': sockets.Real3DVectorSocketDef(
|
||||||
default_value=sp.Matrix([0, 0, -1])
|
default_value=sp.Matrix([0, 0, -1])
|
||||||
),
|
),
|
||||||
"Pol Angle": sockets.PhysicalAngleSocketDef(),
|
'Pol Angle': sockets.PhysicalAngleSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Source": sockets.MaxwellSourceSocketDef(),
|
'Source': sockets.MaxwellSourceSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"plane_wave_source": ct.schemas.ManagedObjDef(
|
'plane_wave_source': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,21 +76,23 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Source",
|
'Source',
|
||||||
input_sockets={"Temporal Shape", "Center", "Direction", "Pol Angle"},
|
input_sockets={'Temporal Shape', 'Center', 'Direction', 'Pol Angle'},
|
||||||
)
|
)
|
||||||
def compute_source(self, input_sockets: dict):
|
def compute_source(self, input_sockets: dict):
|
||||||
temporal_shape = input_sockets["Temporal Shape"]
|
temporal_shape = input_sockets['Temporal Shape']
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
direction = input_sockets["Direction"]
|
direction = input_sockets['Direction']
|
||||||
pol_angle = input_sockets["Pol Angle"]
|
pol_angle = input_sockets['Pol Angle']
|
||||||
|
|
||||||
injection_axis, dir_sgn, theta, phi = convert_vector_to_spherical(direction)
|
injection_axis, dir_sgn, theta, phi = convert_vector_to_spherical(
|
||||||
|
direction
|
||||||
|
)
|
||||||
|
|
||||||
size = {
|
size = {
|
||||||
"x": (0, math.inf, math.inf),
|
'x': (0, math.inf, math.inf),
|
||||||
"y": (math.inf, 0, math.inf),
|
'y': (math.inf, 0, math.inf),
|
||||||
"z": (math.inf, math.inf, 0),
|
'z': (math.inf, math.inf, 0),
|
||||||
}[injection_axis]
|
}[injection_axis]
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
|
||||||
|
@ -110,69 +111,60 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
# - Preview
|
# - Preview
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Direction"},
|
socket_name={'Center', 'Direction'},
|
||||||
input_sockets={"Center", "Direction"},
|
input_sockets={'Center', 'Direction'},
|
||||||
managed_objs={"plane_wave_source"},
|
managed_objs={'plane_wave_source'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_direction(
|
def on_value_changed__center_direction(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_direction = input_sockets["Direction"]
|
_direction = input_sockets['Direction']
|
||||||
direction = tuple([
|
direction = tuple([float(el) for el in _direction])
|
||||||
float(el)
|
|
||||||
for el in _direction
|
|
||||||
])
|
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_PLANE_WAVE]
|
geo_nodes = bpy.data.node_groups[GEONODES_PLANE_WAVE]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["plane_wave_source"].sync_geonodes_modifier(
|
managed_objs['plane_wave_source'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Direction"].identifier: direction,
|
geonodes_interface['Direction'].identifier: direction,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["plane_wave_source"].bl_object("MESH").location = center
|
managed_objs['plane_wave_source'].bl_object('MESH').location = center
|
||||||
|
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"plane_wave_source"},
|
managed_objs={'plane_wave_source'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["plane_wave_source"].show_preview("MESH")
|
managed_objs['plane_wave_source'].show_preview('MESH')
|
||||||
self.on_value_changed__center_direction()
|
self.on_value_changed__center_direction()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
PlaneWaveSourceNode,
|
PlaneWaveSourceNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.PlaneWaveSource: (ct.NodeCategory.MAXWELLSIM_SOURCES)}
|
||||||
ct.NodeType.PlaneWaveSource: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_SOURCES
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,28 +10,29 @@ from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
|
|
||||||
|
|
||||||
class PointDipoleSourceNode(base.MaxwellSimNode):
|
class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.PointDipoleSource
|
node_type = ct.NodeType.PointDipoleSource
|
||||||
bl_label = "Point Dipole Source"
|
bl_label = 'Point Dipole Source'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Interpolate": sockets.BoolSocketDef(
|
'Interpolate': sockets.BoolSocketDef(
|
||||||
default_value=True,
|
default_value=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Source": sockets.MaxwellSourceSocketDef(),
|
'Source': sockets.MaxwellSourceSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"sphere_empty": ct.schemas.ManagedObjDef(
|
'sphere_empty': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,15 +40,15 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
pol_axis: bpy.props.EnumProperty(
|
pol_axis: bpy.props.EnumProperty(
|
||||||
name="Polarization Axis",
|
name='Polarization Axis',
|
||||||
description="Polarization Axis",
|
description='Polarization Axis',
|
||||||
items=[
|
items=[
|
||||||
("EX", "Ex", "Electric field in x-dir"),
|
('EX', 'Ex', 'Electric field in x-dir'),
|
||||||
("EY", "Ey", "Electric field in y-dir"),
|
('EY', 'Ey', 'Electric field in y-dir'),
|
||||||
("EZ", "Ez", "Electric field in z-dir"),
|
('EZ', 'Ez', 'Electric field in z-dir'),
|
||||||
],
|
],
|
||||||
default="EX",
|
default='EX',
|
||||||
update=(lambda self, context: self.sync_prop("pol_axis", context)),
|
update=(lambda self, context: self.sync_prop('pol_axis', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -57,29 +58,31 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
split = layout.split(factor=0.6)
|
split = layout.split(factor=0.6)
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.label(text="Pol Axis")
|
col.label(text='Pol Axis')
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(self, "pol_axis", text="")
|
col.prop(self, 'pol_axis', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Source",
|
'Source',
|
||||||
input_sockets={"Temporal Shape", "Center", "Interpolate"},
|
input_sockets={'Temporal Shape', 'Center', 'Interpolate'},
|
||||||
props={"pol_axis"},
|
props={'pol_axis'},
|
||||||
)
|
)
|
||||||
def compute_source(self, input_sockets: dict[str, typ.Any], props: dict[str, typ.Any]) -> td.PointDipole:
|
def compute_source(
|
||||||
|
self, input_sockets: dict[str, typ.Any], props: dict[str, typ.Any]
|
||||||
|
) -> td.PointDipole:
|
||||||
pol_axis = {
|
pol_axis = {
|
||||||
"EX": "Ex",
|
'EX': 'Ex',
|
||||||
"EY": "Ey",
|
'EY': 'Ey',
|
||||||
"EZ": "Ez",
|
'EZ': 'Ez',
|
||||||
}[props["pol_axis"]]
|
}[props['pol_axis']]
|
||||||
|
|
||||||
temporal_shape = input_sockets["Temporal Shape"]
|
temporal_shape = input_sockets['Temporal Shape']
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
interpolate = input_sockets["Interpolate"]
|
interpolate = input_sockets['Interpolate']
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
|
||||||
|
@ -95,36 +98,37 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
# - Preview
|
# - Preview
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="Center",
|
socket_name='Center',
|
||||||
input_sockets={"Center"},
|
input_sockets={'Center'},
|
||||||
managed_objs={"sphere_empty"},
|
managed_objs={'sphere_empty'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center(
|
def on_value_changed__center(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
mobj = managed_objs["sphere_empty"]
|
mobj = managed_objs['sphere_empty']
|
||||||
bl_object = mobj.bl_object("EMPTY")
|
bl_object = mobj.bl_object('EMPTY')
|
||||||
bl_object.location = center #tuple([float(el) for el in center])
|
bl_object.location = center # tuple([float(el) for el in center])
|
||||||
|
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"sphere_empty"},
|
managed_objs={'sphere_empty'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["sphere_empty"].show_preview(
|
managed_objs['sphere_empty'].show_preview(
|
||||||
"EMPTY",
|
'EMPTY',
|
||||||
empty_display_type="SPHERE",
|
empty_display_type='SPHERE',
|
||||||
)
|
)
|
||||||
managed_objs["sphere_empty"].bl_object("EMPTY").empty_display_size = 0.2
|
managed_objs['sphere_empty'].bl_object(
|
||||||
|
'EMPTY'
|
||||||
|
).empty_display_size = 0.2
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -134,7 +138,5 @@ BL_REGISTER = [
|
||||||
PointDipoleSourceNode,
|
PointDipoleSourceNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
ct.NodeType.PointDipoleSource: (
|
ct.NodeType.PointDipoleSource: (ct.NodeCategory.MAXWELLSIM_SOURCES)
|
||||||
ct.NodeCategory.MAXWELLSIM_SOURCES
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
from . import gaussian_pulse_temporal_shape
|
from . import gaussian_pulse_temporal_shape
|
||||||
#from . import continuous_wave_temporal_shape
|
# from . import continuous_wave_temporal_shape
|
||||||
#from . import array_temporal_shape
|
# from . import array_temporal_shape
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*gaussian_pulse_temporal_shape.BL_REGISTER,
|
*gaussian_pulse_temporal_shape.BL_REGISTER,
|
||||||
# *continuous_wave_temporal_shape.BL_REGISTER,
|
# *continuous_wave_temporal_shape.BL_REGISTER,
|
||||||
# *array_temporal_shape.BL_REGISTER,
|
# *array_temporal_shape.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**gaussian_pulse_temporal_shape.BL_NODES,
|
**gaussian_pulse_temporal_shape.BL_NODES,
|
||||||
# **continuous_wave_temporal_shape.BL_NODES,
|
# **continuous_wave_temporal_shape.BL_NODES,
|
||||||
# **array_temporal_shape.BL_NODES,
|
# **array_temporal_shape.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -6,48 +6,49 @@ from .... import contracts
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class ContinuousWaveTemporalShapeNode(base.MaxwellSimTreeNode):
|
class ContinuousWaveTemporalShapeNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.ContinuousWaveTemporalShape
|
node_type = contracts.NodeType.ContinuousWaveTemporalShape
|
||||||
|
|
||||||
bl_label = "Continuous Wave Temporal Shape"
|
bl_label = 'Continuous Wave Temporal Shape'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
#"amplitude": sockets.RealNumberSocketDef(
|
# "amplitude": sockets.RealNumberSocketDef(
|
||||||
# label="Temporal Shape",
|
# label="Temporal Shape",
|
||||||
#), ## Should have a unit of some kind...
|
# ), ## Should have a unit of some kind...
|
||||||
"phase": sockets.PhysicalAngleSocketDef(
|
'phase': sockets.PhysicalAngleSocketDef(
|
||||||
label="Phase",
|
label='Phase',
|
||||||
),
|
),
|
||||||
"freq_center": sockets.PhysicalFreqSocketDef(
|
'freq_center': sockets.PhysicalFreqSocketDef(
|
||||||
label="Freq Center",
|
label='Freq Center',
|
||||||
),
|
),
|
||||||
"freq_std": sockets.PhysicalFreqSocketDef(
|
'freq_std': sockets.PhysicalFreqSocketDef(
|
||||||
label="Freq STD",
|
label='Freq STD',
|
||||||
),
|
),
|
||||||
"time_delay_rel_ang_freq": sockets.RealNumberSocketDef(
|
'time_delay_rel_ang_freq': sockets.RealNumberSocketDef(
|
||||||
label="Time Delay rel. Ang. Freq",
|
label='Time Delay rel. Ang. Freq',
|
||||||
default_value=5.0,
|
default_value=5.0,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"temporal_shape": sockets.MaxwellTemporalShapeSocketDef(
|
'temporal_shape': sockets.MaxwellTemporalShapeSocketDef(
|
||||||
label="Temporal Shape",
|
label='Temporal Shape',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("temporal_shape")
|
@base.computes_output_socket('temporal_shape')
|
||||||
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
||||||
_phase = self.compute_input("phase")
|
_phase = self.compute_input('phase')
|
||||||
_freq_center = self.compute_input("freq_center")
|
_freq_center = self.compute_input('freq_center')
|
||||||
_freq_std = self.compute_input("freq_std")
|
_freq_std = self.compute_input('freq_std')
|
||||||
time_delay_rel_ang_freq = self.compute_input("time_delay_rel_ang_freq")
|
time_delay_rel_ang_freq = self.compute_input('time_delay_rel_ang_freq')
|
||||||
|
|
||||||
cheating_amplitude = 1.0
|
cheating_amplitude = 1.0
|
||||||
phase = spu.convert_to(_phase, spu.radian) / spu.radian
|
phase = spu.convert_to(_phase, spu.radian) / spu.radian
|
||||||
|
@ -63,7 +64,6 @@ class ContinuousWaveTemporalShapeNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -13,40 +13,41 @@ from .... import sockets
|
||||||
from .... import managed_objs
|
from .... import managed_objs
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.GaussianPulseTemporalShape
|
node_type = ct.NodeType.GaussianPulseTemporalShape
|
||||||
bl_label = "Gaussian Pulse Temporal Shape"
|
bl_label = 'Gaussian Pulse Temporal Shape'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
#"amplitude": sockets.RealNumberSocketDef(
|
# "amplitude": sockets.RealNumberSocketDef(
|
||||||
# label="Temporal Shape",
|
# label="Temporal Shape",
|
||||||
#), ## Should have a unit of some kind...
|
# ), ## Should have a unit of some kind...
|
||||||
"Freq Center": sockets.PhysicalFreqSocketDef(
|
'Freq Center': sockets.PhysicalFreqSocketDef(
|
||||||
default_value=500 * spuex.terahertz,
|
default_value=500 * spuex.terahertz,
|
||||||
),
|
),
|
||||||
"Freq Std.": sockets.PhysicalFreqSocketDef(
|
'Freq Std.': sockets.PhysicalFreqSocketDef(
|
||||||
default_value=200 * spuex.terahertz,
|
default_value=200 * spuex.terahertz,
|
||||||
),
|
),
|
||||||
"Phase": sockets.PhysicalAngleSocketDef(),
|
'Phase': sockets.PhysicalAngleSocketDef(),
|
||||||
"Delay rel. AngFreq": sockets.RealNumberSocketDef(
|
'Delay rel. AngFreq': sockets.RealNumberSocketDef(
|
||||||
default_value=5.0,
|
default_value=5.0,
|
||||||
),
|
),
|
||||||
"Remove DC": sockets.BoolSocketDef(
|
'Remove DC': sockets.BoolSocketDef(
|
||||||
default_value=True,
|
default_value=True,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
'Temporal Shape': sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"amp_time": ct.schemas.ManagedObjDef(
|
'amp_time': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
mk=lambda name: managed_objs.ManagedBLImage(name),
|
||||||
name_prefix="amp_time_",
|
name_prefix='amp_time_',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,51 +55,59 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
plot_time_start: bpy.props.FloatProperty(
|
plot_time_start: bpy.props.FloatProperty(
|
||||||
name="Plot Time Start (ps)",
|
name='Plot Time Start (ps)',
|
||||||
description="The instance ID of a particular MaxwellSimNode instance, used to index caches",
|
description='The instance ID of a particular MaxwellSimNode instance, used to index caches',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
update=(lambda self, context: self.sync_prop("plot_time_start", context)),
|
update=(
|
||||||
|
lambda self, context: self.sync_prop('plot_time_start', context)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
plot_time_end: bpy.props.FloatProperty(
|
plot_time_end: bpy.props.FloatProperty(
|
||||||
name="Plot Time End (ps)",
|
name='Plot Time End (ps)',
|
||||||
description="The instance ID of a particular MaxwellSimNode instance, used to index caches",
|
description='The instance ID of a particular MaxwellSimNode instance, used to index caches',
|
||||||
default=5,
|
default=5,
|
||||||
update=(lambda self, context: self.sync_prop("plot_time_start", context)),
|
update=(
|
||||||
|
lambda self, context: self.sync_prop('plot_time_start', context)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
layout.label(text="Plot Settings")
|
layout.label(text='Plot Settings')
|
||||||
split = layout.split(factor=0.6)
|
split = layout.split(factor=0.6)
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.label(text="t-Range (ps)")
|
col.label(text='t-Range (ps)')
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(self, "plot_time_start", text="")
|
col.prop(self, 'plot_time_start', text='')
|
||||||
col.prop(self, "plot_time_end", text="")
|
col.prop(self, 'plot_time_end', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Temporal Shape",
|
'Temporal Shape',
|
||||||
input_sockets={
|
input_sockets={
|
||||||
"Freq Center", "Freq Std.", "Phase", "Delay rel. AngFreq",
|
'Freq Center',
|
||||||
"Remove DC",
|
'Freq Std.',
|
||||||
}
|
'Phase',
|
||||||
|
'Delay rel. AngFreq',
|
||||||
|
'Remove DC',
|
||||||
|
},
|
||||||
)
|
)
|
||||||
def compute_source(self, input_sockets: dict) -> td.GaussianPulse:
|
def compute_source(self, input_sockets: dict) -> td.GaussianPulse:
|
||||||
if (
|
if (
|
||||||
(_freq_center := input_sockets["Freq Center"]) is None
|
(_freq_center := input_sockets['Freq Center']) is None
|
||||||
or (_freq_std := input_sockets["Freq Std."]) is None
|
or (_freq_std := input_sockets['Freq Std.']) is None
|
||||||
or (_phase := input_sockets["Phase"]) is None
|
or (_phase := input_sockets['Phase']) is None
|
||||||
or (time_delay_rel_ang_freq := input_sockets["Delay rel. AngFreq"]) is None
|
or (time_delay_rel_ang_freq := input_sockets['Delay rel. AngFreq'])
|
||||||
or (remove_dc_component := input_sockets["Remove DC"]) is None
|
is None
|
||||||
|
or (remove_dc_component := input_sockets['Remove DC']) is None
|
||||||
):
|
):
|
||||||
raise ValueError("Inputs not defined")
|
raise ValueError('Inputs not defined')
|
||||||
|
|
||||||
cheating_amplitude = 1.0
|
cheating_amplitude = 1.0
|
||||||
freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz
|
freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz
|
||||||
|
@ -115,9 +124,9 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
@base.on_show_plot(
|
@base.on_show_plot(
|
||||||
managed_objs={"amp_time"},
|
managed_objs={'amp_time'},
|
||||||
props={"plot_time_start", "plot_time_end"},
|
props={'plot_time_start', 'plot_time_end'},
|
||||||
output_sockets={"Temporal Shape"},
|
output_sockets={'Temporal Shape'},
|
||||||
stop_propagation=True,
|
stop_propagation=True,
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
|
@ -126,19 +135,18 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
output_sockets: dict[str, typ.Any],
|
output_sockets: dict[str, typ.Any],
|
||||||
props: dict[str, typ.Any],
|
props: dict[str, typ.Any],
|
||||||
):
|
):
|
||||||
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
|
||||||
plot_time_end = props["plot_time_end"] * 1e-15
|
plot_time_end = props['plot_time_end'] * 1e-15
|
||||||
|
|
||||||
times = np.linspace(plot_time_start, plot_time_end)
|
times = np.linspace(plot_time_start, plot_time_end)
|
||||||
|
|
||||||
managed_objs["amp_time"].mpl_plot_to_image(
|
managed_objs['amp_time'].mpl_plot_to_image(
|
||||||
lambda ax: temporal_shape.plot_spectrum(times, ax=ax),
|
lambda ax: temporal_shape.plot_spectrum(times, ax=ax),
|
||||||
bl_select=True,
|
bl_select=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
#from . import object_structure
|
# from . import object_structure
|
||||||
from . import geonodes_structure
|
from . import geonodes_structure
|
||||||
|
|
||||||
from . import primitives
|
from . import primitives
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
# *object_structure.BL_REGISTER,
|
# *object_structure.BL_REGISTER,
|
||||||
*geonodes_structure.BL_REGISTER,
|
*geonodes_structure.BL_REGISTER,
|
||||||
|
|
||||||
*primitives.BL_REGISTER,
|
*primitives.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
# **object_structure.BL_NODES,
|
# **object_structure.BL_NODES,
|
||||||
**geonodes_structure.BL_NODES,
|
**geonodes_structure.BL_NODES,
|
||||||
|
|
||||||
**primitives.BL_NODES,
|
**primitives.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,26 +16,27 @@ from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
|
|
||||||
|
|
||||||
class GeoNodesStructureNode(base.MaxwellSimNode):
|
class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.GeoNodesStructure
|
node_type = ct.NodeType.GeoNodesStructure
|
||||||
bl_label = "GeoNodes Structure"
|
bl_label = 'GeoNodes Structure'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Unit System": sockets.PhysicalUnitSystemSocketDef(),
|
'Unit System': sockets.PhysicalUnitSystemSocketDef(),
|
||||||
"Medium": sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
"GeoNodes": sockets.BlenderGeoNodesSocketDef(),
|
'GeoNodes': sockets.BlenderGeoNodesSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Structure": sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"geometry": ct.schemas.ManagedObjDef(
|
'geometry': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +44,9 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Structure",
|
'Structure',
|
||||||
input_sockets={"Medium"},
|
input_sockets={'Medium'},
|
||||||
managed_objs={"geometry"},
|
managed_objs={'geometry'},
|
||||||
)
|
)
|
||||||
def compute_structure(
|
def compute_structure(
|
||||||
self,
|
self,
|
||||||
|
@ -53,7 +54,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
) -> td.Structure:
|
) -> td.Structure:
|
||||||
# Extract the Managed Blender Object
|
# Extract the Managed Blender Object
|
||||||
mobj = managed_objs["geometry"]
|
mobj = managed_objs['geometry']
|
||||||
|
|
||||||
# Extract Geometry as Arrays
|
# Extract Geometry as Arrays
|
||||||
geometry_as_arrays = mobj.mesh_as_arrays
|
geometry_as_arrays = mobj.mesh_as_arrays
|
||||||
|
@ -61,20 +62,19 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
# Return TriMesh Structure
|
# Return TriMesh Structure
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.TriangleMesh.from_vertices_faces(
|
geometry=td.TriangleMesh.from_vertices_faces(
|
||||||
geometry_as_arrays["verts"],
|
geometry_as_arrays['verts'],
|
||||||
geometry_as_arrays["faces"],
|
geometry_as_arrays['faces'],
|
||||||
),
|
),
|
||||||
medium=input_sockets["Medium"],
|
medium=input_sockets['Medium'],
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Event Methods
|
# - Event Methods
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="GeoNodes",
|
socket_name='GeoNodes',
|
||||||
|
managed_objs={'geometry'},
|
||||||
managed_objs={"geometry"},
|
input_sockets={'GeoNodes'},
|
||||||
input_sockets={"GeoNodes"},
|
|
||||||
)
|
)
|
||||||
def on_value_changed__geonodes(
|
def on_value_changed__geonodes(
|
||||||
self,
|
self,
|
||||||
|
@ -85,15 +85,15 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
|
|
||||||
Refreshes the Loose Input Sockets, which map directly to the GeoNodes tree input sockets.
|
Refreshes the Loose Input Sockets, which map directly to the GeoNodes tree input sockets.
|
||||||
"""
|
"""
|
||||||
if not (geo_nodes := input_sockets["GeoNodes"]):
|
if not (geo_nodes := input_sockets['GeoNodes']):
|
||||||
managed_objs["geometry"].free()
|
managed_objs['geometry'].free()
|
||||||
self.loose_input_sockets = {}
|
self.loose_input_sockets = {}
|
||||||
return
|
return
|
||||||
|
|
||||||
# Analyze GeoNodes
|
# Analyze GeoNodes
|
||||||
## Extract Valid Inputs (via GeoNodes Tree "Interface")
|
## Extract Valid Inputs (via GeoNodes Tree "Interface")
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set Loose Input Sockets
|
# Set Loose Input Sockets
|
||||||
|
@ -116,9 +116,8 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
|
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
any_loose_input_socket=True,
|
any_loose_input_socket=True,
|
||||||
|
managed_objs={'geometry'},
|
||||||
managed_objs={"geometry"},
|
input_sockets={'Unit System', 'GeoNodes'},
|
||||||
input_sockets={"Unit System", "GeoNodes"},
|
|
||||||
)
|
)
|
||||||
def on_value_changed__loose_inputs(
|
def on_value_changed__loose_inputs(
|
||||||
self,
|
self,
|
||||||
|
@ -131,15 +130,16 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
||||||
"""
|
"""
|
||||||
# Retrieve Data
|
# Retrieve Data
|
||||||
unit_system = input_sockets["Unit System"]
|
unit_system = input_sockets['Unit System']
|
||||||
mobj = managed_objs["geometry"]
|
mobj = managed_objs['geometry']
|
||||||
|
|
||||||
if not (geo_nodes := input_sockets["GeoNodes"]): return
|
if not (geo_nodes := input_sockets['GeoNodes']):
|
||||||
|
return
|
||||||
|
|
||||||
# Analyze GeoNodes Interface (input direction)
|
# Analyze GeoNodes Interface (input direction)
|
||||||
## This retrieves NodeTreeSocketInterface elements
|
## This retrieves NodeTreeSocketInterface elements
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
## TODO: Check that Loose Sockets matches the Interface
|
## TODO: Check that Loose Sockets matches the Interface
|
||||||
|
@ -159,14 +159,14 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
for socket_name, bl_interface_socket in (
|
for socket_name, bl_interface_socket in (
|
||||||
geonodes_interface.items()
|
geonodes_interface.items()
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Event Methods
|
# - Event Methods
|
||||||
####################
|
####################
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"geometry"},
|
managed_objs={'geometry'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
|
@ -176,7 +176,7 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
|
|
||||||
Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
||||||
"""
|
"""
|
||||||
managed_objs["geometry"].show_preview("MESH")
|
managed_objs['geometry'].show_preview('MESH')
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -186,7 +186,5 @@ BL_REGISTER = [
|
||||||
GeoNodesStructureNode,
|
GeoNodesStructureNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
ct.NodeType.GeoNodesStructure: (
|
ct.NodeType.GeoNodesStructure: (ct.NodeCategory.MAXWELLSIM_STRUCTURES)
|
||||||
ct.NodeCategory.MAXWELLSIM_STRUCTURES
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,35 +10,36 @@ from ... import contracts
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
|
||||||
class ObjectStructureNode(base.MaxwellSimTreeNode):
|
class ObjectStructureNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.ObjectStructure
|
node_type = contracts.NodeType.ObjectStructure
|
||||||
bl_label = "Object Structure"
|
bl_label = 'Object Structure'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"medium": sockets.MaxwellMediumSocketDef(
|
'medium': sockets.MaxwellMediumSocketDef(
|
||||||
label="Medium",
|
label='Medium',
|
||||||
),
|
),
|
||||||
"object": sockets.BlenderObjectSocketDef(
|
'object': sockets.BlenderObjectSocketDef(
|
||||||
label="Object",
|
label='Object',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"structure": sockets.MaxwellStructureSocketDef(
|
'structure': sockets.MaxwellStructureSocketDef(
|
||||||
label="Structure",
|
label='Structure',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("structure")
|
@base.computes_output_socket('structure')
|
||||||
def compute_structure(self: contracts.NodeTypeProtocol) -> td.Structure:
|
def compute_structure(self: contracts.NodeTypeProtocol) -> td.Structure:
|
||||||
# Extract the Blender Object
|
# Extract the Blender Object
|
||||||
bl_object = self.compute_input("object")
|
bl_object = self.compute_input('object')
|
||||||
|
|
||||||
# Ensure Updated Geometry
|
# Ensure Updated Geometry
|
||||||
bpy.context.view_layer.update()
|
bpy.context.view_layer.update()
|
||||||
|
@ -51,27 +52,25 @@ class ObjectStructureNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces)
|
bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces)
|
||||||
|
|
||||||
mesh = bpy.data.meshes.new(name="TriangulatedMesh")
|
mesh = bpy.data.meshes.new(name='TriangulatedMesh')
|
||||||
bmesh_mesh.to_mesh(mesh)
|
bmesh_mesh.to_mesh(mesh)
|
||||||
bmesh_mesh.free()
|
bmesh_mesh.free()
|
||||||
|
|
||||||
# Extract Vertices and Faces
|
# Extract Vertices and Faces
|
||||||
vertices = np.array([vert.co for vert in mesh.vertices])
|
vertices = np.array([vert.co for vert in mesh.vertices])
|
||||||
faces = np.array([
|
faces = np.array(
|
||||||
[vert for vert in poly.vertices]
|
[[vert for vert in poly.vertices] for poly in mesh.polygons]
|
||||||
for poly in mesh.polygons
|
)
|
||||||
])
|
|
||||||
|
|
||||||
# Remove Temporary Mesh
|
# Remove Temporary Mesh
|
||||||
bpy.data.meshes.remove(mesh)
|
bpy.data.meshes.remove(mesh)
|
||||||
|
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
||||||
medium=self.compute_input("medium")
|
medium=self.compute_input('medium'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from . import box_structure
|
from . import box_structure
|
||||||
#from . import cylinder_structure
|
|
||||||
|
# from . import cylinder_structure
|
||||||
from . import sphere_structure
|
from . import sphere_structure
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*box_structure.BL_REGISTER,
|
*box_structure.BL_REGISTER,
|
||||||
# *cylinder_structure.BL_REGISTER,
|
# *cylinder_structure.BL_REGISTER,
|
||||||
*sphere_structure.BL_REGISTER,
|
*sphere_structure.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**box_structure.BL_NODES,
|
**box_structure.BL_NODES,
|
||||||
# **cylinder_structure.BL_NODES,
|
# **cylinder_structure.BL_NODES,
|
||||||
**sphere_structure.BL_NODES,
|
**sphere_structure.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,30 +10,31 @@ from .... import sockets
|
||||||
from .... import managed_objs
|
from .... import managed_objs
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
GEONODES_STRUCTURE_BOX = "structure_box"
|
GEONODES_STRUCTURE_BOX = 'structure_box'
|
||||||
|
|
||||||
|
|
||||||
class BoxStructureNode(base.MaxwellSimNode):
|
class BoxStructureNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.BoxStructure
|
node_type = ct.NodeType.BoxStructure
|
||||||
bl_label = "Box Structure"
|
bl_label = 'Box Structure'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Medium": sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Size": sockets.PhysicalSize3DSocketDef(
|
'Size': sockets.PhysicalSize3DSocketDef(
|
||||||
default_value=sp.Matrix([500, 500, 500]) * spu.nm
|
default_value=sp.Matrix([500, 500, 500]) * spu.nm
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Structure": sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"structure_box": ct.schemas.ManagedObjDef(
|
'structure_box': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +42,13 @@ class BoxStructureNode(base.MaxwellSimNode):
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Structure",
|
'Structure',
|
||||||
input_sockets={"Medium", "Center", "Size"},
|
input_sockets={'Medium', 'Center', 'Size'},
|
||||||
)
|
)
|
||||||
def compute_simulation(self, input_sockets: dict) -> td.Box:
|
def compute_simulation(self, input_sockets: dict) -> td.Box:
|
||||||
medium = input_sockets["Medium"]
|
medium = input_sockets['Medium']
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets['Size']
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
|
@ -64,64 +65,61 @@ class BoxStructureNode(base.MaxwellSimNode):
|
||||||
# - Preview - Changes to Input Sockets
|
# - Preview - Changes to Input Sockets
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Size"},
|
socket_name={'Center', 'Size'},
|
||||||
input_sockets={"Center", "Size"},
|
input_sockets={'Center', 'Size'},
|
||||||
managed_objs={"structure_box"},
|
managed_objs={'structure_box'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_size(
|
def on_value_changed__center_size(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets['Size']
|
||||||
size = tuple([
|
size = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_size, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_STRUCTURE_BOX]
|
geo_nodes = bpy.data.node_groups[GEONODES_STRUCTURE_BOX]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["structure_box"].sync_geonodes_modifier(
|
managed_objs['structure_box'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Size"].identifier: size,
|
geonodes_interface['Size'].identifier: size,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["structure_box"].bl_object("MESH").location = center
|
managed_objs['structure_box'].bl_object('MESH').location = center
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Preview - Show Preview
|
# - Preview - Show Preview
|
||||||
####################
|
####################
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"structure_box"},
|
managed_objs={'structure_box'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["structure_box"].show_preview("MESH")
|
managed_objs['structure_box'].show_preview('MESH')
|
||||||
self.on_value_changed__center_size()
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -6,43 +6,44 @@ from .... import contracts
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class CylinderStructureNode(base.MaxwellSimTreeNode):
|
class CylinderStructureNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.CylinderStructure
|
node_type = contracts.NodeType.CylinderStructure
|
||||||
bl_label = "Cylinder Structure"
|
bl_label = 'Cylinder Structure'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"medium": sockets.MaxwellMediumSocketDef(
|
'medium': sockets.MaxwellMediumSocketDef(
|
||||||
label="Medium",
|
label='Medium',
|
||||||
),
|
),
|
||||||
"center": sockets.PhysicalPoint3DSocketDef(
|
'center': sockets.PhysicalPoint3DSocketDef(
|
||||||
label="Center",
|
label='Center',
|
||||||
),
|
),
|
||||||
"radius": sockets.PhysicalLengthSocketDef(
|
'radius': sockets.PhysicalLengthSocketDef(
|
||||||
label="Radius",
|
label='Radius',
|
||||||
),
|
),
|
||||||
"height": sockets.PhysicalLengthSocketDef(
|
'height': sockets.PhysicalLengthSocketDef(
|
||||||
label="Height",
|
label='Height',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"structure": sockets.MaxwellStructureSocketDef(
|
'structure': sockets.MaxwellStructureSocketDef(
|
||||||
label="Structure",
|
label='Structure',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("structure")
|
@base.computes_output_socket('structure')
|
||||||
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Box:
|
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Box:
|
||||||
medium = self.compute_input("medium")
|
medium = self.compute_input('medium')
|
||||||
_center = self.compute_input("center")
|
_center = self.compute_input('center')
|
||||||
_radius = self.compute_input("radius")
|
_radius = self.compute_input('radius')
|
||||||
_height = self.compute_input("height")
|
_height = self.compute_input('height')
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
radius = spu.convert_to(_radius, spu.um) / spu.um
|
radius = spu.convert_to(_radius, spu.um) / spu.um
|
||||||
|
@ -58,7 +59,6 @@ class CylinderStructureNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -10,30 +10,31 @@ from .... import sockets
|
||||||
from .... import managed_objs
|
from .... import managed_objs
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
GEONODES_STRUCTURE_SPHERE = "structure_sphere"
|
GEONODES_STRUCTURE_SPHERE = 'structure_sphere'
|
||||||
|
|
||||||
|
|
||||||
class SphereStructureNode(base.MaxwellSimNode):
|
class SphereStructureNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.SphereStructure
|
node_type = ct.NodeType.SphereStructure
|
||||||
bl_label = "Sphere Structure"
|
bl_label = 'Sphere Structure'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
'Center': sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Radius": sockets.PhysicalLengthSocketDef(
|
'Radius': sockets.PhysicalLengthSocketDef(
|
||||||
default_value=150*spu.nm,
|
default_value=150 * spu.nm,
|
||||||
),
|
),
|
||||||
"Medium": sockets.MaxwellMediumSocketDef(),
|
'Medium': sockets.MaxwellMediumSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Structure": sockets.MaxwellStructureSocketDef(),
|
'Structure': sockets.MaxwellStructureSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"structure_sphere": ct.schemas.ManagedObjDef(
|
'structure_sphere': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +42,13 @@ class SphereStructureNode(base.MaxwellSimNode):
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Structure",
|
'Structure',
|
||||||
input_sockets={"Center", "Radius", "Medium"},
|
input_sockets={'Center', 'Radius', 'Medium'},
|
||||||
)
|
)
|
||||||
def compute_structure(self, input_sockets: dict) -> td.Box:
|
def compute_structure(self, input_sockets: dict) -> td.Box:
|
||||||
medium = input_sockets["Medium"]
|
medium = input_sockets['Medium']
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
_radius = input_sockets["Radius"]
|
_radius = input_sockets['Radius']
|
||||||
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
radius = spu.convert_to(_radius, spu.um) / spu.um
|
radius = spu.convert_to(_radius, spu.um) / spu.um
|
||||||
|
@ -64,61 +65,59 @@ class SphereStructureNode(base.MaxwellSimNode):
|
||||||
# - Preview - Changes to Input Sockets
|
# - Preview - Changes to Input Sockets
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name={"Center", "Radius"},
|
socket_name={'Center', 'Radius'},
|
||||||
input_sockets={"Center", "Radius"},
|
input_sockets={'Center', 'Radius'},
|
||||||
managed_objs={"structure_sphere"},
|
managed_objs={'structure_sphere'},
|
||||||
)
|
)
|
||||||
def on_value_changed__center_radius(
|
def on_value_changed__center_radius(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets['Center']
|
||||||
center = tuple([
|
center = tuple(
|
||||||
float(el)
|
[float(el) for el in spu.convert_to(_center, spu.um) / spu.um]
|
||||||
for el in spu.convert_to(_center, spu.um) / spu.um
|
)
|
||||||
])
|
|
||||||
|
|
||||||
_radius = input_sockets["Radius"]
|
_radius = input_sockets['Radius']
|
||||||
radius = float(spu.convert_to(_radius, spu.um) / spu.um)
|
radius = float(spu.convert_to(_radius, spu.um) / spu.um)
|
||||||
## TODO: Preview unit system?? Presume um for now
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
geo_nodes = bpy.data.node_groups[GEONODES_STRUCTURE_SPHERE]
|
geo_nodes = bpy.data.node_groups[GEONODES_STRUCTURE_SPHERE]
|
||||||
geonodes_interface = analyze_geonodes.interface(
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
geo_nodes, direc="INPUT"
|
geo_nodes, direc='INPUT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Modifier Inputs
|
# Sync Modifier Inputs
|
||||||
managed_objs["structure_sphere"].sync_geonodes_modifier(
|
managed_objs['structure_sphere'].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Radius"].identifier: radius,
|
geonodes_interface['Radius'].identifier: radius,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
## - ...But it needs aligning with Blender, too. Hmm.
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync Object Position
|
# Sync Object Position
|
||||||
managed_objs["structure_sphere"].bl_object("MESH").location = center
|
managed_objs['structure_sphere'].bl_object('MESH').location = center
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Preview - Show Preview
|
# - Preview - Show Preview
|
||||||
####################
|
####################
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"structure_sphere"},
|
managed_objs={'structure_sphere'},
|
||||||
)
|
)
|
||||||
def on_show_preview(
|
def on_show_preview(
|
||||||
self,
|
self,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["structure_sphere"].show_preview("MESH")
|
managed_objs['structure_sphere'].show_preview('MESH')
|
||||||
self.on_value_changed__center_radius()
|
self.on_value_changed__center_radius()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
#from . import math
|
# from . import math
|
||||||
from . import combine
|
from . import combine
|
||||||
#from . import separate
|
# from . import separate
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
# *math.BL_REGISTER,
|
# *math.BL_REGISTER,
|
||||||
|
|
||||||
*combine.BL_REGISTER,
|
*combine.BL_REGISTER,
|
||||||
#*separate.BL_REGISTER,
|
# *separate.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
# **math.BL_NODES,
|
# **math.BL_NODES,
|
||||||
|
|
||||||
**combine.BL_NODES,
|
**combine.BL_NODES,
|
||||||
#**separate.BL_NODES,
|
# **separate.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,152 +10,143 @@ from .. import base
|
||||||
|
|
||||||
MAX_AMOUNT = 20
|
MAX_AMOUNT = 20
|
||||||
|
|
||||||
|
|
||||||
class CombineNode(base.MaxwellSimNode):
|
class CombineNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.Combine
|
node_type = ct.NodeType.Combine
|
||||||
bl_label = "Combine"
|
bl_label = 'Combine'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"Maxwell Sources": {},
|
'Maxwell Sources': {},
|
||||||
"Maxwell Structures": {},
|
'Maxwell Structures': {},
|
||||||
"Maxwell Monitors": {},
|
'Maxwell Monitors': {},
|
||||||
"Real 3D Vector": {
|
'Real 3D Vector': {
|
||||||
f"x_{i}": sockets.RealNumberSocketDef()
|
f'x_{i}': sockets.RealNumberSocketDef() for i in range(3)
|
||||||
for i in range(3)
|
|
||||||
},
|
},
|
||||||
#"Point 3D": {
|
# "Point 3D": {
|
||||||
# axis: sockets.PhysicalLengthSocketDef()
|
# axis: sockets.PhysicalLengthSocketDef()
|
||||||
# for i, axis in zip(
|
# for i, axis in zip(
|
||||||
# range(3),
|
# range(3),
|
||||||
# ["x", "y", "z"]
|
# ["x", "y", "z"]
|
||||||
# )
|
# )
|
||||||
#},
|
# },
|
||||||
#"Size 3D": {
|
# "Size 3D": {
|
||||||
# axis_key: sockets.PhysicalLengthSocketDef()
|
# axis_key: sockets.PhysicalLengthSocketDef()
|
||||||
# for i, axis_key, axis_label in zip(
|
# for i, axis_key, axis_label in zip(
|
||||||
# range(3),
|
# range(3),
|
||||||
# ["x_size", "y_size", "z_size"],
|
# ["x_size", "y_size", "z_size"],
|
||||||
# ["X Size", "Y Size", "Z Size"],
|
# ["X Size", "Y Size", "Z Size"],
|
||||||
# )
|
# )
|
||||||
#},
|
# },
|
||||||
}
|
}
|
||||||
output_socket_sets = {
|
output_socket_sets = {
|
||||||
"Maxwell Sources": {
|
'Maxwell Sources': {
|
||||||
"Sources": sockets.MaxwellSourceSocketDef(
|
'Sources': sockets.MaxwellSourceSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Maxwell Structures": {
|
'Maxwell Structures': {
|
||||||
"Structures": sockets.MaxwellStructureSocketDef(
|
'Structures': sockets.MaxwellStructureSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Maxwell Monitors": {
|
'Maxwell Monitors': {
|
||||||
"Monitors": sockets.MaxwellMonitorSocketDef(
|
'Monitors': sockets.MaxwellMonitorSocketDef(
|
||||||
is_list=True,
|
is_list=True,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Real 3D Vector": {
|
'Real 3D Vector': {
|
||||||
"Real 3D Vector": sockets.Real3DVectorSocketDef(),
|
'Real 3D Vector': sockets.Real3DVectorSocketDef(),
|
||||||
},
|
},
|
||||||
#"Point 3D": {
|
# "Point 3D": {
|
||||||
# "3D Point": sockets.PhysicalPoint3DSocketDef(),
|
# "3D Point": sockets.PhysicalPoint3DSocketDef(),
|
||||||
#},
|
# },
|
||||||
#"Size 3D": {
|
# "Size 3D": {
|
||||||
# "3D Size": sockets.PhysicalSize3DSocketDef(),
|
# "3D Size": sockets.PhysicalSize3DSocketDef(),
|
||||||
#},
|
# },
|
||||||
}
|
}
|
||||||
|
|
||||||
amount: bpy.props.IntProperty(
|
amount: bpy.props.IntProperty(
|
||||||
name="# Objects to Combine",
|
name='# Objects to Combine',
|
||||||
description="Amount of Objects to Combine",
|
description='Amount of Objects to Combine',
|
||||||
default=1,
|
default=1,
|
||||||
min=1,
|
min=1,
|
||||||
max=MAX_AMOUNT,
|
max=MAX_AMOUNT,
|
||||||
update=lambda self, context: self.sync_prop("amount", context)
|
update=lambda self, context: self.sync_prop('amount', context),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Draw
|
# - Draw
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
layout.prop(self, "amount", text="#")
|
layout.prop(self, 'amount', text='#')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Real 3D Vector",
|
'Real 3D Vector', input_sockets={'x_0', 'x_1', 'x_2'}
|
||||||
input_sockets={"x_0", "x_1", "x_2"}
|
|
||||||
)
|
)
|
||||||
def compute_real_3d_vector(self, input_sockets) -> sp.Expr:
|
def compute_real_3d_vector(self, input_sockets) -> sp.Expr:
|
||||||
return sp.Matrix([input_sockets[f"x_{i}"] for i in range(3)])
|
return sp.Matrix([input_sockets[f'x_{i}'] for i in range(3)])
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Sources",
|
'Sources',
|
||||||
input_sockets={f"Source #{i}" for i in range(MAX_AMOUNT)},
|
input_sockets={f'Source #{i}' for i in range(MAX_AMOUNT)},
|
||||||
props={"amount"},
|
props={'amount'},
|
||||||
)
|
)
|
||||||
def compute_sources(self, input_sockets, props) -> sp.Expr:
|
def compute_sources(self, input_sockets, props) -> sp.Expr:
|
||||||
return [
|
return [input_sockets[f'Source #{i}'] for i in range(props['amount'])]
|
||||||
input_sockets[f"Source #{i}"]
|
|
||||||
for i in range(props["amount"])
|
|
||||||
]
|
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Structures",
|
'Structures',
|
||||||
input_sockets={f"Structure #{i}" for i in range(MAX_AMOUNT)},
|
input_sockets={f'Structure #{i}' for i in range(MAX_AMOUNT)},
|
||||||
props={"amount"},
|
props={'amount'},
|
||||||
)
|
)
|
||||||
def compute_structures(self, input_sockets, props) -> sp.Expr:
|
def compute_structures(self, input_sockets, props) -> sp.Expr:
|
||||||
return [
|
return [
|
||||||
input_sockets[f"Structure #{i}"]
|
input_sockets[f'Structure #{i}'] for i in range(props['amount'])
|
||||||
for i in range(props["amount"])
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Monitors",
|
'Monitors',
|
||||||
input_sockets={f"Monitor #{i}" for i in range(MAX_AMOUNT)},
|
input_sockets={f'Monitor #{i}' for i in range(MAX_AMOUNT)},
|
||||||
props={"amount"},
|
props={'amount'},
|
||||||
)
|
)
|
||||||
def compute_monitors(self, input_sockets, props) -> sp.Expr:
|
def compute_monitors(self, input_sockets, props) -> sp.Expr:
|
||||||
return [
|
return [input_sockets[f'Monitor #{i}'] for i in range(props['amount'])]
|
||||||
input_sockets[f"Monitor #{i}"]
|
|
||||||
for i in range(props["amount"])
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Input Socket Compilation
|
# - Input Socket Compilation
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
prop_name="active_socket_set",
|
prop_name='active_socket_set',
|
||||||
props={"active_socket_set", "amount"},
|
props={'active_socket_set', 'amount'},
|
||||||
)
|
)
|
||||||
def on_value_changed__active_socket_set(self, props):
|
def on_value_changed__active_socket_set(self, props):
|
||||||
if props["active_socket_set"] == "Maxwell Sources":
|
if props['active_socket_set'] == 'Maxwell Sources':
|
||||||
self.loose_input_sockets = {
|
self.loose_input_sockets = {
|
||||||
f"Source #{i}": sockets.MaxwellSourceSocketDef()
|
f'Source #{i}': sockets.MaxwellSourceSocketDef()
|
||||||
for i in range(props["amount"])
|
for i in range(props['amount'])
|
||||||
}
|
}
|
||||||
elif props["active_socket_set"] == "Maxwell Structures":
|
elif props['active_socket_set'] == 'Maxwell Structures':
|
||||||
self.loose_input_sockets = {
|
self.loose_input_sockets = {
|
||||||
f"Structure #{i}": sockets.MaxwellStructureSocketDef()
|
f'Structure #{i}': sockets.MaxwellStructureSocketDef()
|
||||||
for i in range(props["amount"])
|
for i in range(props['amount'])
|
||||||
}
|
}
|
||||||
elif props["active_socket_set"] == "Maxwell Monitors":
|
elif props['active_socket_set'] == 'Maxwell Monitors':
|
||||||
self.loose_input_sockets = {
|
self.loose_input_sockets = {
|
||||||
f"Monitor #{i}": sockets.MaxwellMonitorSocketDef()
|
f'Monitor #{i}': sockets.MaxwellMonitorSocketDef()
|
||||||
for i in range(props["amount"])
|
for i in range(props['amount'])
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
self.loose_input_sockets = {}
|
self.loose_input_sockets = {}
|
||||||
|
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
prop_name="amount",
|
prop_name='amount',
|
||||||
)
|
)
|
||||||
def on_value_changed__amount(self):
|
def on_value_changed__amount(self):
|
||||||
self.on_value_changed__active_socket_set()
|
self.on_value_changed__active_socket_set()
|
||||||
|
@ -171,8 +162,4 @@ class CombineNode(base.MaxwellSimNode):
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
CombineNode,
|
CombineNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.Combine: (ct.NodeCategory.MAXWELLSIM_UTILITIES)}
|
||||||
ct.NodeType.Combine: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_UTILITIES
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,37 +7,38 @@ from .... import contracts
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
from ... import base
|
from ... import base
|
||||||
|
|
||||||
|
|
||||||
class WaveConverterNode(base.MaxwellSimTreeNode):
|
class WaveConverterNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.WaveConverter
|
node_type = contracts.NodeType.WaveConverter
|
||||||
bl_label = "Wave Converter"
|
bl_label = 'Wave Converter'
|
||||||
#bl_icon = ...
|
# bl_icon = ...
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {}
|
input_sockets = {}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
"freq_to_vacwl": {
|
'freq_to_vacwl': {
|
||||||
"freq": sockets.PhysicalFreqSocketDef(
|
'freq': sockets.PhysicalFreqSocketDef(
|
||||||
label="Freq",
|
label='Freq',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"vacwl_to_freq": {
|
'vacwl_to_freq': {
|
||||||
"vacwl": sockets.PhysicalVacWLSocketDef(
|
'vacwl': sockets.PhysicalVacWLSocketDef(
|
||||||
label="Vac WL",
|
label='Vac WL',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
output_sockets = {}
|
output_sockets = {}
|
||||||
output_socket_sets = {
|
output_socket_sets = {
|
||||||
"freq_to_vacwl": {
|
'freq_to_vacwl': {
|
||||||
"vacwl": sockets.PhysicalVacWLSocketDef(
|
'vacwl': sockets.PhysicalVacWLSocketDef(
|
||||||
label="Vac WL",
|
label='Vac WL',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"vacwl_to_freq": {
|
'vacwl_to_freq': {
|
||||||
"freq": sockets.PhysicalFreqSocketDef(
|
'freq': sockets.PhysicalFreqSocketDef(
|
||||||
label="Freq",
|
label='Freq',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -45,22 +46,26 @@ class WaveConverterNode(base.MaxwellSimTreeNode):
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("freq")
|
@base.computes_output_socket('freq')
|
||||||
def compute_freq(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
def compute_freq(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
vac_speed_of_light = (
|
||||||
|
sc.constants.speed_of_light * spu.meter / spu.second
|
||||||
|
)
|
||||||
|
|
||||||
vacwl = self.compute_input("vacwl")
|
vacwl = self.compute_input('vacwl')
|
||||||
|
|
||||||
return spu.convert_to(
|
return spu.convert_to(
|
||||||
vac_speed_of_light / vacwl,
|
vac_speed_of_light / vacwl,
|
||||||
spu.hertz,
|
spu.hertz,
|
||||||
)
|
)
|
||||||
|
|
||||||
@base.computes_output_socket("vacwl")
|
@base.computes_output_socket('vacwl')
|
||||||
def compute_vacwl(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
def compute_vacwl(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
vac_speed_of_light = (
|
||||||
|
sc.constants.speed_of_light * spu.meter / spu.second
|
||||||
|
)
|
||||||
|
|
||||||
freq = self.compute_input("freq")
|
freq = self.compute_input('freq')
|
||||||
|
|
||||||
return spu.convert_to(
|
return spu.convert_to(
|
||||||
vac_speed_of_light / freq,
|
vac_speed_of_light / freq,
|
||||||
|
@ -68,7 +73,6 @@ class WaveConverterNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -16,28 +16,27 @@ from ... import managed_objs
|
||||||
|
|
||||||
CACHE = {}
|
CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
class FDTDSimDataVizNode(base.MaxwellSimNode):
|
class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.FDTDSimDataViz
|
node_type = ct.NodeType.FDTDSimDataViz
|
||||||
bl_label = "FDTD Sim Data Viz"
|
bl_label = 'FDTD Sim Data Viz'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"FDTD Sim Data": sockets.MaxwellFDTDSimDataSocketDef(),
|
'FDTD Sim Data': sockets.MaxwellFDTDSimDataSocketDef(),
|
||||||
}
|
|
||||||
output_sockets= {
|
|
||||||
"Preview": sockets.AnySocketDef()
|
|
||||||
}
|
}
|
||||||
|
output_sockets = {'Preview': sockets.AnySocketDef()}
|
||||||
|
|
||||||
managed_obj_defs = {
|
managed_obj_defs = {
|
||||||
"viz_plot": ct.schemas.ManagedObjDef(
|
'viz_plot': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLImage(name),
|
mk=lambda name: managed_objs.ManagedBLImage(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
),
|
),
|
||||||
"viz_object": ct.schemas.ManagedObjDef(
|
'viz_object': ct.schemas.ManagedObjDef(
|
||||||
mk=lambda name: managed_objs.ManagedBLObject(name),
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
name_prefix="",
|
name_prefix='',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,147 +44,168 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
viz_monitor_name: bpy.props.EnumProperty(
|
viz_monitor_name: bpy.props.EnumProperty(
|
||||||
name="Viz Monitor Name",
|
name='Viz Monitor Name',
|
||||||
description="Monitor to visualize within the attached SimData",
|
description='Monitor to visualize within the attached SimData',
|
||||||
items=lambda self, context: self.retrieve_monitors(context),
|
items=lambda self, context: self.retrieve_monitors(context),
|
||||||
update=(lambda self, context: self.sync_viz_monitor_name(context)),
|
update=(lambda self, context: self.sync_viz_monitor_name(context)),
|
||||||
)
|
)
|
||||||
cache_viz_monitor_type: bpy.props.StringProperty(
|
cache_viz_monitor_type: bpy.props.StringProperty(
|
||||||
name="Viz Monitor Type",
|
name='Viz Monitor Type',
|
||||||
description="Type of the viz monitor",
|
description='Type of the viz monitor',
|
||||||
default=""
|
default='',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Field Monitor Type
|
# Field Monitor Type
|
||||||
field_viz_component: bpy.props.EnumProperty(
|
field_viz_component: bpy.props.EnumProperty(
|
||||||
name="Field Component",
|
name='Field Component',
|
||||||
description="Field component to visualize",
|
description='Field component to visualize',
|
||||||
items=[
|
items=[
|
||||||
("E", "E", "Electric"),
|
('E', 'E', 'Electric'),
|
||||||
#("H", "H", "Magnetic"),
|
# ("H", "H", "Magnetic"),
|
||||||
#("S", "S", "Poynting"),
|
# ("S", "S", "Poynting"),
|
||||||
("Ex", "Ex", "Ex"),
|
('Ex', 'Ex', 'Ex'),
|
||||||
("Ey", "Ey", "Ey"),
|
('Ey', 'Ey', 'Ey'),
|
||||||
("Ez", "Ez", "Ez"),
|
('Ez', 'Ez', 'Ez'),
|
||||||
#("Hx", "Hx", "Hx"),
|
# ("Hx", "Hx", "Hx"),
|
||||||
#("Hy", "Hy", "Hy"),
|
# ("Hy", "Hy", "Hy"),
|
||||||
#("Hz", "Hz", "Hz"),
|
# ("Hz", "Hz", "Hz"),
|
||||||
],
|
],
|
||||||
default="E",
|
default='E',
|
||||||
update=lambda self, context: self.sync_prop("field_viz_component", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_component', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_part: bpy.props.EnumProperty(
|
field_viz_part: bpy.props.EnumProperty(
|
||||||
name="Field Part",
|
name='Field Part',
|
||||||
description="Field part to visualize",
|
description='Field part to visualize',
|
||||||
items=[
|
items=[
|
||||||
("real", "Real", "Electric"),
|
('real', 'Real', 'Electric'),
|
||||||
("imag", "Imaginary", "Imaginary"),
|
('imag', 'Imaginary', 'Imaginary'),
|
||||||
("abs", "Abs", "Abs"),
|
('abs', 'Abs', 'Abs'),
|
||||||
("abs^2", "Squared Abs", "Square Abs"),
|
('abs^2', 'Squared Abs', 'Square Abs'),
|
||||||
("phase", "Phase", "Phase"),
|
('phase', 'Phase', 'Phase'),
|
||||||
],
|
],
|
||||||
default="real",
|
default='real',
|
||||||
update=lambda self, context: self.sync_prop("field_viz_part", context),
|
update=lambda self, context: self.sync_prop('field_viz_part', context),
|
||||||
)
|
)
|
||||||
field_viz_scale: bpy.props.EnumProperty(
|
field_viz_scale: bpy.props.EnumProperty(
|
||||||
name="Field Scale",
|
name='Field Scale',
|
||||||
description="Field scale to visualize in, Linear or Log",
|
description='Field scale to visualize in, Linear or Log',
|
||||||
items=[
|
items=[
|
||||||
("lin", "Linear", "Linear Scale"),
|
('lin', 'Linear', 'Linear Scale'),
|
||||||
("dB", "Log (dB)", "Logarithmic (dB) Scale"),
|
('dB', 'Log (dB)', 'Logarithmic (dB) Scale'),
|
||||||
],
|
],
|
||||||
default="lin",
|
default='lin',
|
||||||
update=lambda self, context: self.sync_prop("field_viz_scale", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_scale', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_structure_visibility: bpy.props.FloatProperty(
|
field_viz_structure_visibility: bpy.props.FloatProperty(
|
||||||
name="Field Viz Plot: Structure Visibility",
|
name='Field Viz Plot: Structure Visibility',
|
||||||
description="Visibility of structes",
|
description='Visibility of structes',
|
||||||
default=0.2,
|
default=0.2,
|
||||||
min=0.0,
|
min=0.0,
|
||||||
max=1.0,
|
max=1.0,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fixed_f", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fixed_f', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
field_viz_plot_fix_x: bpy.props.BoolProperty(
|
field_viz_plot_fix_x: bpy.props.BoolProperty(
|
||||||
name="Field Viz Plot: Fix X",
|
name='Field Viz Plot: Fix X',
|
||||||
description="Fix the x-coordinate on the plot",
|
description='Fix the x-coordinate on the plot',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fix_x", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fix_x', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fix_y: bpy.props.BoolProperty(
|
field_viz_plot_fix_y: bpy.props.BoolProperty(
|
||||||
name="Field Viz Plot: Fix Y",
|
name='Field Viz Plot: Fix Y',
|
||||||
description="Fix the y coordinate on the plot",
|
description='Fix the y coordinate on the plot',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fix_y", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fix_y', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fix_z: bpy.props.BoolProperty(
|
field_viz_plot_fix_z: bpy.props.BoolProperty(
|
||||||
name="Field Viz Plot: Fix Z",
|
name='Field Viz Plot: Fix Z',
|
||||||
description="Fix the z coordinate on the plot",
|
description='Fix the z coordinate on the plot',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fix_z", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fix_z', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fix_f: bpy.props.BoolProperty(
|
field_viz_plot_fix_f: bpy.props.BoolProperty(
|
||||||
name="Field Viz Plot: Fix Freq",
|
name='Field Viz Plot: Fix Freq',
|
||||||
description="Fix the frequency coordinate on the plot",
|
description='Fix the frequency coordinate on the plot',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fix_f", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fix_f', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
field_viz_plot_fixed_x: bpy.props.FloatProperty(
|
field_viz_plot_fixed_x: bpy.props.FloatProperty(
|
||||||
name="Field Viz Plot: Fix X",
|
name='Field Viz Plot: Fix X',
|
||||||
description="Fix the x-coordinate on the plot",
|
description='Fix the x-coordinate on the plot',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fixed_x", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fixed_x', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fixed_y: bpy.props.FloatProperty(
|
field_viz_plot_fixed_y: bpy.props.FloatProperty(
|
||||||
name="Field Viz Plot: Fixed Y",
|
name='Field Viz Plot: Fixed Y',
|
||||||
description="Fix the y coordinate on the plot",
|
description='Fix the y coordinate on the plot',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fixed_y", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fixed_y', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fixed_z: bpy.props.FloatProperty(
|
field_viz_plot_fixed_z: bpy.props.FloatProperty(
|
||||||
name="Field Viz Plot: Fixed Z",
|
name='Field Viz Plot: Fixed Z',
|
||||||
description="Fix the z coordinate on the plot",
|
description='Fix the z coordinate on the plot',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fixed_z", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fixed_z', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
field_viz_plot_fixed_f: bpy.props.FloatProperty(
|
field_viz_plot_fixed_f: bpy.props.FloatProperty(
|
||||||
name="Field Viz Plot: Fixed Freq (Thz)",
|
name='Field Viz Plot: Fixed Freq (Thz)',
|
||||||
description="Fix the frequency coordinate on the plot",
|
description='Fix the frequency coordinate on the plot',
|
||||||
default=0.0,
|
default=0.0,
|
||||||
update=lambda self, context: self.sync_prop("field_viz_plot_fixed_f", context),
|
update=lambda self, context: self.sync_prop(
|
||||||
|
'field_viz_plot_fixed_f', context
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Derived Properties
|
# - Derived Properties
|
||||||
####################
|
####################
|
||||||
def sync_viz_monitor_name(self, context):
|
def sync_viz_monitor_name(self, context):
|
||||||
if (sim_data := self._compute_input("FDTD Sim Data")) is None:
|
if (sim_data := self._compute_input('FDTD Sim Data')) is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.cache_viz_monitor_type = sim_data.monitor_data[
|
self.cache_viz_monitor_type = sim_data.monitor_data[
|
||||||
self.viz_monitor_name
|
self.viz_monitor_name
|
||||||
].type
|
].type
|
||||||
self.sync_prop("viz_monitor_name", context)
|
self.sync_prop('viz_monitor_name', context)
|
||||||
|
|
||||||
def retrieve_monitors(self, context) -> list[tuple]:
|
def retrieve_monitors(self, context) -> list[tuple]:
|
||||||
global CACHE
|
global CACHE
|
||||||
if not CACHE.get(self.instance_id):
|
if not CACHE.get(self.instance_id):
|
||||||
sim_data = self._compute_input("FDTD Sim Data")
|
sim_data = self._compute_input('FDTD Sim Data')
|
||||||
|
|
||||||
if sim_data is not None:
|
if sim_data is not None:
|
||||||
CACHE[self.instance_id] = {"monitors": list(
|
CACHE[self.instance_id] = {
|
||||||
sim_data.monitor_data.keys()
|
'monitors': list(sim_data.monitor_data.keys())
|
||||||
)}
|
}
|
||||||
else:
|
else:
|
||||||
return [("NONE", "None", "No monitors")]
|
return [('NONE', 'None', 'No monitors')]
|
||||||
|
|
||||||
monitor_names = CACHE[self.instance_id]["monitors"]
|
monitor_names = CACHE[self.instance_id]['monitors']
|
||||||
|
|
||||||
# Check for No Monitors
|
# Check for No Monitors
|
||||||
if not monitor_names:
|
if not monitor_names:
|
||||||
return [("NONE", "None", "No monitors")]
|
return [('NONE', 'None', 'No monitors')]
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(
|
(
|
||||||
|
@ -201,42 +221,41 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(self, "viz_monitor_name", text="")
|
row.prop(self, 'viz_monitor_name', text='')
|
||||||
if self.cache_viz_monitor_type == "FieldData":
|
if self.cache_viz_monitor_type == 'FieldData':
|
||||||
# Array Selection
|
# Array Selection
|
||||||
split = layout.split(factor=0.45)
|
split = layout.split(factor=0.45)
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.label(text="Component")
|
col.label(text='Component')
|
||||||
col.label(text="Part")
|
col.label(text='Part')
|
||||||
col.label(text="Scale")
|
col.label(text='Scale')
|
||||||
|
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.prop(self, "field_viz_component", text="")
|
col.prop(self, 'field_viz_component', text='')
|
||||||
col.prop(self, "field_viz_part", text="")
|
col.prop(self, 'field_viz_part', text='')
|
||||||
col.prop(self, "field_viz_scale", text="")
|
col.prop(self, 'field_viz_scale', text='')
|
||||||
|
|
||||||
# Coordinate Fixing
|
# Coordinate Fixing
|
||||||
split = layout.split(factor=0.45)
|
split = layout.split(factor=0.45)
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.prop(self, "field_viz_plot_fix_x", text="Fix x (um)")
|
col.prop(self, 'field_viz_plot_fix_x', text='Fix x (um)')
|
||||||
col.prop(self, "field_viz_plot_fix_y", text="Fix y (um)")
|
col.prop(self, 'field_viz_plot_fix_y', text='Fix y (um)')
|
||||||
col.prop(self, "field_viz_plot_fix_z", text="Fix z (um)")
|
col.prop(self, 'field_viz_plot_fix_z', text='Fix z (um)')
|
||||||
col.prop(self, "field_viz_plot_fix_f", text="Fix f (THz)")
|
col.prop(self, 'field_viz_plot_fix_f', text='Fix f (THz)')
|
||||||
|
|
||||||
col = split.column(align=False)
|
col = split.column(align=False)
|
||||||
col.prop(self, "field_viz_plot_fixed_x", text="")
|
col.prop(self, 'field_viz_plot_fixed_x', text='')
|
||||||
col.prop(self, "field_viz_plot_fixed_y", text="")
|
col.prop(self, 'field_viz_plot_fixed_y', text='')
|
||||||
col.prop(self, "field_viz_plot_fixed_z", text="")
|
col.prop(self, 'field_viz_plot_fixed_z', text='')
|
||||||
col.prop(self, "field_viz_plot_fixed_f", text="")
|
col.prop(self, 'field_viz_plot_fixed_f', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - On Value Changed Methods
|
# - On Value Changed Methods
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="FDTD Sim Data",
|
socket_name='FDTD Sim Data',
|
||||||
|
managed_objs={'viz_object'},
|
||||||
managed_objs={"viz_object"},
|
input_sockets={'FDTD Sim Data'},
|
||||||
input_sockets={"FDTD Sim Data"},
|
|
||||||
)
|
)
|
||||||
def on_value_changed__fdtd_sim_data(
|
def on_value_changed__fdtd_sim_data(
|
||||||
self,
|
self,
|
||||||
|
@ -245,29 +264,35 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
) -> None:
|
) -> None:
|
||||||
global CACHE
|
global CACHE
|
||||||
|
|
||||||
if (sim_data := input_sockets["FDTD Sim Data"]) is None:
|
if (sim_data := input_sockets['FDTD Sim Data']) is None:
|
||||||
CACHE.pop(self.instance_id, None)
|
CACHE.pop(self.instance_id, None)
|
||||||
return
|
return
|
||||||
|
|
||||||
CACHE[self.instance_id] = {"monitors": list(
|
CACHE[self.instance_id] = {
|
||||||
sim_data.monitor_data.keys()
|
'monitors': list(sim_data.monitor_data.keys())
|
||||||
)}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Plotting
|
# - Plotting
|
||||||
####################
|
####################
|
||||||
@base.on_show_plot(
|
@base.on_show_plot(
|
||||||
managed_objs={"viz_plot"},
|
managed_objs={'viz_plot'},
|
||||||
props={
|
props={
|
||||||
"viz_monitor_name", "field_viz_component",
|
'viz_monitor_name',
|
||||||
"field_viz_part", "field_viz_scale",
|
'field_viz_component',
|
||||||
"field_viz_structure_visibility",
|
'field_viz_part',
|
||||||
"field_viz_plot_fix_x", "field_viz_plot_fix_y",
|
'field_viz_scale',
|
||||||
"field_viz_plot_fix_z", "field_viz_plot_fix_f",
|
'field_viz_structure_visibility',
|
||||||
"field_viz_plot_fixed_x", "field_viz_plot_fixed_y",
|
'field_viz_plot_fix_x',
|
||||||
"field_viz_plot_fixed_z", "field_viz_plot_fixed_f",
|
'field_viz_plot_fix_y',
|
||||||
|
'field_viz_plot_fix_z',
|
||||||
|
'field_viz_plot_fix_f',
|
||||||
|
'field_viz_plot_fixed_x',
|
||||||
|
'field_viz_plot_fixed_y',
|
||||||
|
'field_viz_plot_fixed_z',
|
||||||
|
'field_viz_plot_fixed_f',
|
||||||
},
|
},
|
||||||
input_sockets={"FDTD Sim Data"},
|
input_sockets={'FDTD Sim Data'},
|
||||||
stop_propagation=True,
|
stop_propagation=True,
|
||||||
)
|
)
|
||||||
def on_show_plot(
|
def on_show_plot(
|
||||||
|
@ -276,42 +301,42 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
input_sockets: dict[str, typ.Any],
|
input_sockets: dict[str, typ.Any],
|
||||||
props: dict[str, typ.Any],
|
props: dict[str, typ.Any],
|
||||||
):
|
):
|
||||||
if (
|
if (sim_data := input_sockets['FDTD Sim Data']) is None or (
|
||||||
(sim_data := input_sockets["FDTD Sim Data"]) is None
|
monitor_name := props['viz_monitor_name']
|
||||||
or (monitor_name := props["viz_monitor_name"]) == "NONE"
|
) == 'NONE':
|
||||||
):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
coord_fix = {}
|
coord_fix = {}
|
||||||
for coord in ["x", "y", "z", "f"]:
|
for coord in ['x', 'y', 'z', 'f']:
|
||||||
if props[f"field_viz_plot_fix_{coord}"]:
|
if props[f'field_viz_plot_fix_{coord}']:
|
||||||
coord_fix |= {
|
coord_fix |= {
|
||||||
coord: props[f"field_viz_plot_fixed_{coord}"],
|
coord: props[f'field_viz_plot_fixed_{coord}'],
|
||||||
}
|
}
|
||||||
|
|
||||||
if "f" in coord_fix:
|
if 'f' in coord_fix:
|
||||||
coord_fix["f"] *= 1e12
|
coord_fix['f'] *= 1e12
|
||||||
|
|
||||||
managed_objs["viz_plot"].mpl_plot_to_image(
|
managed_objs['viz_plot'].mpl_plot_to_image(
|
||||||
lambda ax: sim_data.plot_field(
|
lambda ax: sim_data.plot_field(
|
||||||
monitor_name,
|
monitor_name,
|
||||||
props["field_viz_component"],
|
props['field_viz_component'],
|
||||||
val=props["field_viz_part"],
|
val=props['field_viz_part'],
|
||||||
scale=props["field_viz_scale"],
|
scale=props['field_viz_scale'],
|
||||||
eps_alpha=props["field_viz_structure_visibility"],
|
eps_alpha=props['field_viz_structure_visibility'],
|
||||||
phase=0,
|
phase=0,
|
||||||
**coord_fix,
|
**coord_fix,
|
||||||
ax=ax,
|
ax=ax,
|
||||||
),
|
),
|
||||||
bl_select=True,
|
bl_select=True,
|
||||||
)
|
)
|
||||||
#@base.on_show_preview(
|
|
||||||
|
# @base.on_show_preview(
|
||||||
# managed_objs={"viz_object"},
|
# managed_objs={"viz_object"},
|
||||||
#)
|
# )
|
||||||
#def on_show_preview(
|
# def on_show_preview(
|
||||||
# self,
|
# self,
|
||||||
# managed_objs: dict[str, ct.schemas.ManagedObj],
|
# managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
#):
|
# ):
|
||||||
# """Called whenever a Loose Input Socket is altered.
|
# """Called whenever a Loose Input Socket is altered.
|
||||||
#
|
#
|
||||||
# Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
# Synchronizes the change to the actual GeoNodes modifier, so that the change is immediately visible.
|
||||||
|
@ -325,8 +350,4 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
FDTDSimDataVizNode,
|
FDTDSimDataVizNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {ct.NodeType.FDTDSimDataViz: (ct.NodeCategory.MAXWELLSIM_VIZ)}
|
||||||
ct.NodeType.FDTDSimDataViz: (
|
|
||||||
ct.NodeCategory.MAXWELLSIM_VIZ
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
from . import base
|
from . import base
|
||||||
|
|
||||||
from . import basic
|
from . import basic
|
||||||
|
|
||||||
AnySocketDef = basic.AnySocketDef
|
AnySocketDef = basic.AnySocketDef
|
||||||
BoolSocketDef = basic.BoolSocketDef
|
BoolSocketDef = basic.BoolSocketDef
|
||||||
StringSocketDef = basic.StringSocketDef
|
StringSocketDef = basic.StringSocketDef
|
||||||
FilePathSocketDef = basic.FilePathSocketDef
|
FilePathSocketDef = basic.FilePathSocketDef
|
||||||
|
|
||||||
from . import number
|
from . import number
|
||||||
|
|
||||||
IntegerNumberSocketDef = number.IntegerNumberSocketDef
|
IntegerNumberSocketDef = number.IntegerNumberSocketDef
|
||||||
RationalNumberSocketDef = number.RationalNumberSocketDef
|
RationalNumberSocketDef = number.RationalNumberSocketDef
|
||||||
RealNumberSocketDef = number.RealNumberSocketDef
|
RealNumberSocketDef = number.RealNumberSocketDef
|
||||||
ComplexNumberSocketDef = number.ComplexNumberSocketDef
|
ComplexNumberSocketDef = number.ComplexNumberSocketDef
|
||||||
|
|
||||||
from . import vector
|
from . import vector
|
||||||
|
|
||||||
Real2DVectorSocketDef = vector.Real2DVectorSocketDef
|
Real2DVectorSocketDef = vector.Real2DVectorSocketDef
|
||||||
Complex2DVectorSocketDef = vector.Complex2DVectorSocketDef
|
Complex2DVectorSocketDef = vector.Complex2DVectorSocketDef
|
||||||
Integer3DVectorSocketDef = vector.Integer3DVectorSocketDef
|
Integer3DVectorSocketDef = vector.Integer3DVectorSocketDef
|
||||||
|
@ -20,6 +23,7 @@ Real3DVectorSocketDef = vector.Real3DVectorSocketDef
|
||||||
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
||||||
|
|
||||||
from . import physical
|
from . import physical
|
||||||
|
|
||||||
PhysicalUnitSystemSocketDef = physical.PhysicalUnitSystemSocketDef
|
PhysicalUnitSystemSocketDef = physical.PhysicalUnitSystemSocketDef
|
||||||
PhysicalTimeSocketDef = physical.PhysicalTimeSocketDef
|
PhysicalTimeSocketDef = physical.PhysicalTimeSocketDef
|
||||||
PhysicalAngleSocketDef = physical.PhysicalAngleSocketDef
|
PhysicalAngleSocketDef = physical.PhysicalAngleSocketDef
|
||||||
|
@ -36,6 +40,7 @@ PhysicalPolSocketDef = physical.PhysicalPolSocketDef
|
||||||
PhysicalFreqSocketDef = physical.PhysicalFreqSocketDef
|
PhysicalFreqSocketDef = physical.PhysicalFreqSocketDef
|
||||||
|
|
||||||
from . import blender
|
from . import blender
|
||||||
|
|
||||||
BlenderObjectSocketDef = blender.BlenderObjectSocketDef
|
BlenderObjectSocketDef = blender.BlenderObjectSocketDef
|
||||||
BlenderCollectionSocketDef = blender.BlenderCollectionSocketDef
|
BlenderCollectionSocketDef = blender.BlenderCollectionSocketDef
|
||||||
BlenderImageSocketDef = blender.BlenderImageSocketDef
|
BlenderImageSocketDef = blender.BlenderImageSocketDef
|
||||||
|
@ -43,6 +48,7 @@ BlenderGeoNodesSocketDef = blender.BlenderGeoNodesSocketDef
|
||||||
BlenderTextSocketDef = blender.BlenderTextSocketDef
|
BlenderTextSocketDef = blender.BlenderTextSocketDef
|
||||||
|
|
||||||
from . import maxwell
|
from . import maxwell
|
||||||
|
|
||||||
MaxwellBoundCondSocketDef = maxwell.MaxwellBoundCondSocketDef
|
MaxwellBoundCondSocketDef = maxwell.MaxwellBoundCondSocketDef
|
||||||
MaxwellBoundCondsSocketDef = maxwell.MaxwellBoundCondsSocketDef
|
MaxwellBoundCondsSocketDef = maxwell.MaxwellBoundCondsSocketDef
|
||||||
MaxwellMediumSocketDef = maxwell.MaxwellMediumSocketDef
|
MaxwellMediumSocketDef = maxwell.MaxwellMediumSocketDef
|
||||||
|
@ -58,6 +64,7 @@ MaxwellSimGridAxisSocketDef = maxwell.MaxwellSimGridAxisSocketDef
|
||||||
MaxwellSimDomainSocketDef = maxwell.MaxwellSimDomainSocketDef
|
MaxwellSimDomainSocketDef = maxwell.MaxwellSimDomainSocketDef
|
||||||
|
|
||||||
from . import tidy3d
|
from . import tidy3d
|
||||||
|
|
||||||
Tidy3DCloudTaskSocketDef = tidy3d.Tidy3DCloudTaskSocketDef
|
Tidy3DCloudTaskSocketDef = tidy3d.Tidy3DCloudTaskSocketDef
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
|
|
@ -9,6 +9,7 @@ import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
from .. import contracts as ct
|
from .. import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
class MaxwellSimSocket(bpy.types.NodeSocket):
|
class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
# Fundamentals
|
# Fundamentals
|
||||||
socket_type: ct.SocketType
|
socket_type: ct.SocketType
|
||||||
|
@ -16,8 +17,12 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
|
|
||||||
# Style
|
# Style
|
||||||
display_shape: typx.Literal[
|
display_shape: typx.Literal[
|
||||||
"CIRCLE", "SQUARE", "DIAMOND", "CIRCLE_DOT", "SQUARE_DOT",
|
'CIRCLE',
|
||||||
"DIAMOND_DOT",
|
'SQUARE',
|
||||||
|
'DIAMOND',
|
||||||
|
'CIRCLE_DOT',
|
||||||
|
'SQUARE_DOT',
|
||||||
|
'DIAMOND_DOT',
|
||||||
]
|
]
|
||||||
## We use the following conventions for shapes:
|
## We use the following conventions for shapes:
|
||||||
## - CIRCLE: Single Value.
|
## - CIRCLE: Single Value.
|
||||||
|
@ -27,7 +32,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
socket_color: tuple
|
socket_color: tuple
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
#link_limit: int = 0
|
# link_limit: int = 0
|
||||||
use_units: bool = False
|
use_units: bool = False
|
||||||
use_prelock: bool = False
|
use_prelock: bool = False
|
||||||
|
|
||||||
|
@ -41,14 +46,14 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
super().__init_subclass__(**kwargs) ## Yucky superclass setup.
|
super().__init_subclass__(**kwargs) ## Yucky superclass setup.
|
||||||
|
|
||||||
# Setup Blender ID for Node
|
# Setup Blender ID for Node
|
||||||
if not hasattr(cls, "socket_type"):
|
if not hasattr(cls, 'socket_type'):
|
||||||
msg = f"Socket class {cls} does not define 'socket_type'"
|
msg = f"Socket class {cls} does not define 'socket_type'"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
cls.bl_idname = str(cls.socket_type.value)
|
cls.bl_idname = str(cls.socket_type.value)
|
||||||
|
|
||||||
# Setup Locked Property for Node
|
# Setup Locked Property for Node
|
||||||
cls.__annotations__["locked"] = bpy.props.BoolProperty(
|
cls.__annotations__['locked'] = bpy.props.BoolProperty(
|
||||||
name="Locked State",
|
name='Locked State',
|
||||||
description="The lock-state of a particular socket, which determines the socket's user editability",
|
description="The lock-state of a particular socket, which determines the socket's user editability",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
@ -58,37 +63,37 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
cls.socket_shape = ct.SOCKET_SHAPES[cls.socket_type]
|
cls.socket_shape = ct.SOCKET_SHAPES[cls.socket_type]
|
||||||
|
|
||||||
# Setup List
|
# Setup List
|
||||||
cls.__annotations__["is_list"] = bpy.props.BoolProperty(
|
cls.__annotations__['is_list'] = bpy.props.BoolProperty(
|
||||||
name="Is List",
|
name='Is List',
|
||||||
description="Whether or not a particular socket is a list type socket",
|
description='Whether or not a particular socket is a list type socket',
|
||||||
default=False,
|
default=False,
|
||||||
update=lambda self, context: self.sync_is_list(context)
|
update=lambda self, context: self.sync_is_list(context),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure Use of Units
|
# Configure Use of Units
|
||||||
if cls.use_units:
|
if cls.use_units:
|
||||||
# Set Shape :)
|
# Set Shape :)
|
||||||
cls.socket_shape += "_DOT"
|
cls.socket_shape += '_DOT'
|
||||||
|
|
||||||
if not (socket_units := ct.SOCKET_UNITS.get(cls.socket_type)):
|
if not (socket_units := ct.SOCKET_UNITS.get(cls.socket_type)):
|
||||||
msg = "Tried to `use_units` on {cls.bl_idname} socket, but `SocketType` has no units defined in `contracts.SOCKET_UNITS`"
|
msg = 'Tried to `use_units` on {cls.bl_idname} socket, but `SocketType` has no units defined in `contracts.SOCKET_UNITS`'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
# Current Unit
|
# Current Unit
|
||||||
cls.__annotations__["active_unit"] = bpy.props.EnumProperty(
|
cls.__annotations__['active_unit'] = bpy.props.EnumProperty(
|
||||||
name="Unit",
|
name='Unit',
|
||||||
description="Choose a unit",
|
description='Choose a unit',
|
||||||
items=[
|
items=[
|
||||||
(unit_name, str(unit_value), str(unit_value))
|
(unit_name, str(unit_value), str(unit_value))
|
||||||
for unit_name, unit_value in socket_units["values"].items()
|
for unit_name, unit_value in socket_units['values'].items()
|
||||||
],
|
],
|
||||||
default=socket_units["default"],
|
default=socket_units['default'],
|
||||||
update=lambda self, context: self.sync_unit_change(),
|
update=lambda self, context: self.sync_unit_change(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Previous Unit (for conversion)
|
# Previous Unit (for conversion)
|
||||||
cls.__annotations__["prev_active_unit"] = bpy.props.StringProperty(
|
cls.__annotations__['prev_active_unit'] = bpy.props.StringProperty(
|
||||||
default=socket_units["default"],
|
default=socket_units['default'],
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -96,7 +101,13 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
####################
|
####################
|
||||||
def trigger_action(
|
def trigger_action(
|
||||||
self,
|
self,
|
||||||
action: typx.Literal["enable_lock", "disable_lock", "value_changed", "show_preview", "show_plot"],
|
action: typx.Literal[
|
||||||
|
'enable_lock',
|
||||||
|
'disable_lock',
|
||||||
|
'value_changed',
|
||||||
|
'show_preview',
|
||||||
|
'show_plot',
|
||||||
|
],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called whenever the socket's output value has changed.
|
"""Called whenever the socket's output value has changed.
|
||||||
|
|
||||||
|
@ -109,7 +120,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
`trigger_action` method will be called.
|
`trigger_action` method will be called.
|
||||||
"""
|
"""
|
||||||
# Forwards Chains
|
# Forwards Chains
|
||||||
if action in {"value_changed"}:
|
if action in {'value_changed'}:
|
||||||
## Input Socket
|
## Input Socket
|
||||||
if not self.is_output:
|
if not self.is_output:
|
||||||
self.node.trigger_action(action, socket_name=self.name)
|
self.node.trigger_action(action, socket_name=self.name)
|
||||||
|
@ -120,11 +131,16 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
link.to_socket.trigger_action(action)
|
link.to_socket.trigger_action(action)
|
||||||
|
|
||||||
# Backwards Chains
|
# Backwards Chains
|
||||||
elif action in {"enable_lock", "disable_lock", "show_preview", "show_plot"}:
|
elif action in {
|
||||||
if action == "enable_lock":
|
'enable_lock',
|
||||||
|
'disable_lock',
|
||||||
|
'show_preview',
|
||||||
|
'show_plot',
|
||||||
|
}:
|
||||||
|
if action == 'enable_lock':
|
||||||
self.locked = True
|
self.locked = True
|
||||||
|
|
||||||
if action == "disable_lock":
|
if action == 'disable_lock':
|
||||||
self.locked = False
|
self.locked = False
|
||||||
|
|
||||||
## Output Socket
|
## Output Socket
|
||||||
|
@ -140,36 +156,35 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
# - Action Chain: Event Handlers
|
# - Action Chain: Event Handlers
|
||||||
####################
|
####################
|
||||||
def sync_is_list(self, context: bpy.types.Context):
|
def sync_is_list(self, context: bpy.types.Context):
|
||||||
"""Called when the "is_list_ property has been updated.
|
"""Called when the "is_list_ property has been updated."""
|
||||||
"""
|
|
||||||
if self.is_list:
|
if self.is_list:
|
||||||
if self.use_units:
|
if self.use_units:
|
||||||
self.display_shape = "SQUARE_DOT"
|
self.display_shape = 'SQUARE_DOT'
|
||||||
else:
|
else:
|
||||||
self.display_shape = "SQUARE"
|
self.display_shape = 'SQUARE'
|
||||||
|
|
||||||
self.trigger_action("value_changed")
|
self.trigger_action('value_changed')
|
||||||
|
|
||||||
def sync_prop(self, prop_name: str, context: bpy.types.Context):
|
def sync_prop(self, prop_name: str, context: bpy.types.Context):
|
||||||
"""Called when a property has been updated.
|
"""Called when a property has been updated."""
|
||||||
"""
|
|
||||||
if not hasattr(self, prop_name):
|
if not hasattr(self, prop_name):
|
||||||
msg = f"Property {prop_name} not defined on socket {self}"
|
msg = f'Property {prop_name} not defined on socket {self}'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.trigger_action("value_changed")
|
self.trigger_action('value_changed')
|
||||||
|
|
||||||
def sync_link_added(self, link) -> bool:
|
def sync_link_added(self, link) -> bool:
|
||||||
"""Called when a link has been added to this (input) socket.
|
"""Called when a link has been added to this (input) socket.
|
||||||
|
|
||||||
Returns a bool, whether or not the socket consents to the link change.
|
Returns a bool, whether or not the socket consents to the link change.
|
||||||
"""
|
"""
|
||||||
if self.locked: return False
|
if self.locked:
|
||||||
|
return False
|
||||||
if self.is_output:
|
if self.is_output:
|
||||||
msg = f"Tried to sync 'link add' on output socket"
|
msg = f"Tried to sync 'link add' on output socket"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.trigger_action("value_changed")
|
self.trigger_action('value_changed')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -178,12 +193,13 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
|
|
||||||
Returns a bool, whether or not the socket consents to the link change.
|
Returns a bool, whether or not the socket consents to the link change.
|
||||||
"""
|
"""
|
||||||
if self.locked: return False
|
if self.locked:
|
||||||
|
return False
|
||||||
if self.is_output:
|
if self.is_output:
|
||||||
msg = f"Tried to sync 'link add' on output socket"
|
msg = f"Tried to sync 'link add' on output socket"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.trigger_action("value_changed")
|
self.trigger_action('value_changed')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -193,6 +209,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
@property
|
@property
|
||||||
def value(self) -> typ.Any:
|
def value(self) -> typ.Any:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value: typ.Any) -> None:
|
def value(self, value: typ.Any) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -200,26 +217,29 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
@property
|
@property
|
||||||
def value_list(self) -> typ.Any:
|
def value_list(self) -> typ.Any:
|
||||||
return [self.value]
|
return [self.value]
|
||||||
|
|
||||||
@value_list.setter
|
@value_list.setter
|
||||||
def value_list(self, value: typ.Any) -> None:
|
def value_list(self, value: typ.Any) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def value_as_unit_system(
|
def value_as_unit_system(
|
||||||
self,
|
self, unit_system: dict, dimensionless: bool = True
|
||||||
unit_system: dict,
|
|
||||||
dimensionless: bool = True
|
|
||||||
) -> typ.Any:
|
) -> typ.Any:
|
||||||
## TODO: Caching could speed this boi up quite a bit
|
## TODO: Caching could speed this boi up quite a bit
|
||||||
|
|
||||||
unit_system_unit = unit_system[self.socket_type]
|
unit_system_unit = unit_system[self.socket_type]
|
||||||
return spu.convert_to(
|
return (
|
||||||
|
spu.convert_to(
|
||||||
self.value,
|
self.value,
|
||||||
unit_system_unit,
|
unit_system_unit,
|
||||||
) / unit_system_unit
|
)
|
||||||
|
/ unit_system_unit
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lazy_value(self) -> None:
|
def lazy_value(self) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@lazy_value.setter
|
@lazy_value.setter
|
||||||
def lazy_value(self, lazy_value: typ.Any) -> None:
|
def lazy_value(self, lazy_value: typ.Any) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -227,6 +247,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
@property
|
@property
|
||||||
def lazy_value_list(self) -> typ.Any:
|
def lazy_value_list(self) -> typ.Any:
|
||||||
return [self.lazy_value]
|
return [self.lazy_value]
|
||||||
|
|
||||||
@lazy_value_list.setter
|
@lazy_value_list.setter
|
||||||
def lazy_value_list(self, value: typ.Any) -> None:
|
def lazy_value_list(self, value: typ.Any) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -244,11 +265,15 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
**NOTE**: Low-level method. Use `compute_data` instead.
|
**NOTE**: Low-level method. Use `compute_data` instead.
|
||||||
"""
|
"""
|
||||||
if kind == ct.DataFlowKind.Value:
|
if kind == ct.DataFlowKind.Value:
|
||||||
if self.is_list: return self.value_list
|
if self.is_list:
|
||||||
else: return self.value
|
return self.value_list
|
||||||
|
else:
|
||||||
|
return self.value
|
||||||
elif kind == ct.DataFlowKind.LazyValue:
|
elif kind == ct.DataFlowKind.LazyValue:
|
||||||
if self.is_list: return self.lazy_value_list
|
if self.is_list:
|
||||||
else: return self.lazy_value
|
return self.lazy_value_list
|
||||||
|
else:
|
||||||
|
return self.lazy_value
|
||||||
return self.lazy_value
|
return self.lazy_value
|
||||||
elif kind == ct.DataFlowKind.Capabilities:
|
elif kind == ct.DataFlowKind.Capabilities:
|
||||||
return self.capabilities
|
return self.capabilities
|
||||||
|
@ -268,21 +293,23 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
## List-like sockets guarantee that a list of a thing is passed.
|
## List-like sockets guarantee that a list of a thing is passed.
|
||||||
if self.is_output:
|
if self.is_output:
|
||||||
res = self.node.compute_output(self.name, kind=kind)
|
res = self.node.compute_output(self.name, kind=kind)
|
||||||
if self.is_list and not isinstance(res, list): return [res]
|
if self.is_list and not isinstance(res, list):
|
||||||
|
return [res]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Compute Input Socket
|
# Compute Input Socket
|
||||||
## Unlinked: Retrieve Socket Value
|
## Unlinked: Retrieve Socket Value
|
||||||
if not self.is_linked: return self._compute_data(kind)
|
if not self.is_linked:
|
||||||
|
return self._compute_data(kind)
|
||||||
|
|
||||||
## Linked: Compute Output of Linked Sockets
|
## Linked: Compute Output of Linked Sockets
|
||||||
linked_values = [
|
linked_values = [
|
||||||
link.from_socket.compute_data(kind)
|
link.from_socket.compute_data(kind) for link in self.links
|
||||||
for link in self.links
|
|
||||||
]
|
]
|
||||||
|
|
||||||
## Return Single Value / List of Values
|
## Return Single Value / List of Values
|
||||||
if len(linked_values) == 1: return linked_values[0]
|
if len(linked_values) == 1:
|
||||||
|
return linked_values[0]
|
||||||
return linked_values
|
return linked_values
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -294,9 +321,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
msg = "Tried to get possible units for socket {self}, but socket doesn't `use_units`"
|
msg = "Tried to get possible units for socket {self}, but socket doesn't `use_units`"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
return ct.SOCKET_UNITS[
|
return ct.SOCKET_UNITS[self.socket_type]['values']
|
||||||
self.socket_type
|
|
||||||
]["values"]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit(self) -> sp.Expr:
|
def unit(self) -> sp.Expr:
|
||||||
|
@ -344,8 +369,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
## - Using only self.value avoids implementation-specific details.
|
## - Using only self.value avoids implementation-specific details.
|
||||||
|
|
||||||
self.value = spu.convert_to(
|
self.value = spu.convert_to(
|
||||||
prev_value,
|
prev_value, self.unit
|
||||||
self.unit
|
|
||||||
) ## Now, the unit conversion can be done correctly.
|
) ## Now, the unit conversion can be done correctly.
|
||||||
|
|
||||||
self.prev_active_unit = self.active_unit
|
self.prev_active_unit = self.active_unit
|
||||||
|
@ -358,14 +382,12 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
node: bpy.types.Node,
|
node: bpy.types.Node,
|
||||||
) -> ct.BLColorRGBA:
|
) -> ct.BLColorRGBA:
|
||||||
"""Color of the socket icon, when embedded in a node.
|
"""Color of the socket icon, when embedded in a node."""
|
||||||
"""
|
|
||||||
return self.socket_color
|
return self.socket_color
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_color_simple(cls) -> ct.BLColorRGBA:
|
def draw_color_simple(cls) -> ct.BLColorRGBA:
|
||||||
"""Fallback color of the socket icon (ex.when not embedded in a node).
|
"""Fallback color of the socket icon (ex.when not embedded in a node)."""
|
||||||
"""
|
|
||||||
return cls.socket_color
|
return cls.socket_color
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -378,8 +400,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
node: bpy.types.Node,
|
node: bpy.types.Node,
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called by Blender to draw the socket UI.
|
"""Called by Blender to draw the socket UI."""
|
||||||
"""
|
|
||||||
|
|
||||||
if self.is_output:
|
if self.is_output:
|
||||||
self.draw_output(context, layout, node, text)
|
self.draw_output(context, layout, node, text)
|
||||||
|
@ -402,13 +423,13 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
node: bpy.types.Node,
|
node: bpy.types.Node,
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Draws the socket UI, when the socket is an input socket.
|
"""Draws the socket UI, when the socket is an input socket."""
|
||||||
"""
|
|
||||||
col = layout.column(align=False)
|
col = layout.column(align=False)
|
||||||
|
|
||||||
# Label Row
|
# Label Row
|
||||||
row = col.row(align=False)
|
row = col.row(align=False)
|
||||||
if self.locked: row.enabled = False
|
if self.locked:
|
||||||
|
row.enabled = False
|
||||||
|
|
||||||
## Linked Label
|
## Linked Label
|
||||||
if self.is_linked:
|
if self.is_linked:
|
||||||
|
@ -423,7 +444,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
self.draw_label_row(_row, text)
|
self.draw_label_row(_row, text)
|
||||||
|
|
||||||
_col = split.column(align=True)
|
_col = split.column(align=True)
|
||||||
_col.prop(self, "active_unit", text="")
|
_col.prop(self, 'active_unit', text='')
|
||||||
else:
|
else:
|
||||||
self.draw_label_row(row, text)
|
self.draw_label_row(row, text)
|
||||||
|
|
||||||
|
@ -438,7 +459,8 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
row = col.row(align=False)
|
row = col.row(align=False)
|
||||||
row.enabled = False
|
row.enabled = False
|
||||||
else:
|
else:
|
||||||
if self.locked: row.enabled = False
|
if self.locked:
|
||||||
|
row.enabled = False
|
||||||
|
|
||||||
# Value Column(s)
|
# Value Column(s)
|
||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
|
@ -454,8 +476,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
node: bpy.types.Node,
|
node: bpy.types.Node,
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Draws the socket UI, when the socket is an output socket.
|
"""Draws the socket UI, when the socket is an output socket."""
|
||||||
"""
|
|
||||||
layout.label(text=text)
|
layout.label(text=text)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -485,4 +506,3 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
Can be overridden.
|
Can be overridden.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
from . import any as any_socket
|
from . import any as any_socket
|
||||||
|
|
||||||
AnySocketDef = any_socket.AnySocketDef
|
AnySocketDef = any_socket.AnySocketDef
|
||||||
|
|
||||||
from . import bool as bool_socket
|
from . import bool as bool_socket
|
||||||
|
|
||||||
BoolSocketDef = bool_socket.BoolSocketDef
|
BoolSocketDef = bool_socket.BoolSocketDef
|
||||||
|
|
||||||
from . import string
|
from . import string
|
||||||
|
|
||||||
StringSocketDef = string.StringSocketDef
|
StringSocketDef = string.StringSocketDef
|
||||||
|
|
||||||
from . import file_path
|
from . import file_path
|
||||||
|
|
||||||
FilePathSocketDef = file_path.FilePathSocketDef
|
FilePathSocketDef = file_path.FilePathSocketDef
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,14 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class AnyBLSocket(base.MaxwellSimSocket):
|
class AnyBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.Any
|
socket_type = ct.SocketType.Any
|
||||||
bl_label = "Any"
|
bl_label = 'Any'
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
|
@ -23,6 +25,7 @@ class AnySocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: AnyBLSocket) -> None:
|
def init(self, bl_socket: AnyBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -7,29 +7,32 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class BoolBLSocket(base.MaxwellSimSocket):
|
class BoolBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.Bool
|
socket_type = ct.SocketType.Bool
|
||||||
bl_label = "Bool"
|
bl_label = 'Bool'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.BoolProperty(
|
raw_value: bpy.props.BoolProperty(
|
||||||
name="Boolean",
|
name='Boolean',
|
||||||
description="Represents a boolean value",
|
description='Represents a boolean value',
|
||||||
default=False,
|
default=False,
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket UI
|
# - Socket UI
|
||||||
####################
|
####################
|
||||||
def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None:
|
def draw_label_row(
|
||||||
|
self, label_col_row: bpy.types.UILayout, text: str
|
||||||
|
) -> None:
|
||||||
label_col_row.label(text=text)
|
label_col_row.label(text=text)
|
||||||
label_col_row.prop(self, "raw_value", text="")
|
label_col_row.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
|
@ -42,6 +45,7 @@ class BoolBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bool) -> None:
|
def value(self, value: bool) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -53,6 +57,7 @@ class BoolSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BoolBLSocket) -> None:
|
def init(self, bl_socket: BoolBLSocket) -> None:
|
||||||
bl_socket.value = self.default_value
|
bl_socket.value = self.default_value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -8,21 +8,22 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class FilePathBLSocket(base.MaxwellSimSocket):
|
class FilePathBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.FilePath
|
socket_type = ct.SocketType.FilePath
|
||||||
bl_label = "File Path"
|
bl_label = 'File Path'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.StringProperty(
|
raw_value: bpy.props.StringProperty(
|
||||||
name="File Path",
|
name='File Path',
|
||||||
description="Represents the path to a file",
|
description='Represents the path to a file',
|
||||||
subtype="FILE_PATH",
|
subtype='FILE_PATH',
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -30,7 +31,7 @@ class FilePathBLSocket(base.MaxwellSimSocket):
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col_row = col.row(align=True)
|
col_row = col.row(align=True)
|
||||||
col_row.prop(self, "raw_value", text="")
|
col_row.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
|
@ -43,17 +44,19 @@ class FilePathBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: Path) -> None:
|
def value(self, value: Path) -> None:
|
||||||
self.raw_value = bpy.path.relpath(str(value))
|
self.raw_value = bpy.path.relpath(str(value))
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
class FilePathSocketDef(pyd.BaseModel):
|
class FilePathSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.FilePath
|
socket_type: ct.SocketType = ct.SocketType.FilePath
|
||||||
|
|
||||||
default_path: Path = Path("")
|
default_path: Path = Path('')
|
||||||
|
|
||||||
def init(self, bl_socket: FilePathBLSocket) -> None:
|
def init(self, bl_socket: FilePathBLSocket) -> None:
|
||||||
bl_socket.value = self.default_path
|
bl_socket.value = self.default_path
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -7,28 +7,31 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class StringBLSocket(base.MaxwellSimSocket):
|
class StringBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.String
|
socket_type = ct.SocketType.String
|
||||||
bl_label = "String"
|
bl_label = 'String'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.StringProperty(
|
raw_value: bpy.props.StringProperty(
|
||||||
name="String",
|
name='String',
|
||||||
description="Represents a string",
|
description='Represents a string',
|
||||||
default="",
|
default='',
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket UI
|
# - Socket UI
|
||||||
####################
|
####################
|
||||||
def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None:
|
def draw_label_row(
|
||||||
label_col_row.prop(self, "raw_value", text=text)
|
self, label_col_row: bpy.types.UILayout, text: str
|
||||||
|
) -> None:
|
||||||
|
label_col_row.prop(self, 'raw_value', text=text)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
|
@ -41,17 +44,19 @@ class StringBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: str) -> None:
|
def value(self, value: str) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
class StringSocketDef(pyd.BaseModel):
|
class StringSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.String
|
socket_type: ct.SocketType = ct.SocketType.String
|
||||||
|
|
||||||
default_text: str = ""
|
default_text: str = ''
|
||||||
|
|
||||||
def init(self, bl_socket: StringBLSocket) -> None:
|
def init(self, bl_socket: StringBLSocket) -> None:
|
||||||
bl_socket.value = self.default_text
|
bl_socket.value = self.default_text
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
from . import object as object_socket
|
from . import object as object_socket
|
||||||
from . import collection
|
from . import collection
|
||||||
|
|
||||||
BlenderObjectSocketDef = object_socket.BlenderObjectSocketDef
|
BlenderObjectSocketDef = object_socket.BlenderObjectSocketDef
|
||||||
BlenderCollectionSocketDef = collection.BlenderCollectionSocketDef
|
BlenderCollectionSocketDef = collection.BlenderCollectionSocketDef
|
||||||
|
|
||||||
from . import image
|
from . import image
|
||||||
|
|
||||||
BlenderImageSocketDef = image.BlenderImageSocketDef
|
BlenderImageSocketDef = image.BlenderImageSocketDef
|
||||||
|
|
||||||
from . import geonodes
|
from . import geonodes
|
||||||
from . import text
|
from . import text
|
||||||
|
|
||||||
BlenderGeoNodesSocketDef = geonodes.BlenderGeoNodesSocketDef
|
BlenderGeoNodesSocketDef = geonodes.BlenderGeoNodesSocketDef
|
||||||
BlenderTextSocketDef = text.BlenderTextSocketDef
|
BlenderTextSocketDef = text.BlenderTextSocketDef
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*object_socket.BL_REGISTER,
|
*object_socket.BL_REGISTER,
|
||||||
*collection.BL_REGISTER,
|
*collection.BL_REGISTER,
|
||||||
|
|
||||||
*text.BL_REGISTER,
|
*text.BL_REGISTER,
|
||||||
*image.BL_REGISTER,
|
*image.BL_REGISTER,
|
||||||
*geonodes.BL_REGISTER,
|
*geonodes.BL_REGISTER,
|
||||||
|
|
|
@ -6,28 +6,29 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class BlenderCollectionBLSocket(base.MaxwellSimSocket):
|
class BlenderCollectionBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.BlenderCollection
|
socket_type = ct.SocketType.BlenderCollection
|
||||||
bl_label = "Blender Collection"
|
bl_label = 'Blender Collection'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.PointerProperty(
|
raw_value: bpy.props.PointerProperty(
|
||||||
name="Blender Collection",
|
name='Blender Collection',
|
||||||
description="A Blender collection",
|
description='A Blender collection',
|
||||||
type=bpy.types.Collection,
|
type=bpy.types.Collection,
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, "raw_value", text="")
|
col.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
|
@ -40,6 +41,7 @@ class BlenderCollectionBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bpy.types.Collection) -> None:
|
def value(self, value: bpy.types.Collection) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -49,9 +51,8 @@ class BlenderCollectionSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BlenderCollectionBLSocket) -> None:
|
def init(self, bl_socket: BlenderCollectionBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [BlenderCollectionBLSocket]
|
||||||
BlenderCollectionBLSocket
|
|
||||||
]
|
|
||||||
|
|
|
@ -6,16 +6,17 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Operators
|
# - Operators
|
||||||
####################
|
####################
|
||||||
class BlenderMaxwellResetGeoNodesSocket(bpy.types.Operator):
|
class BlenderMaxwellResetGeoNodesSocket(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.reset_geo_nodes_socket"
|
bl_idname = 'blender_maxwell.reset_geo_nodes_socket'
|
||||||
bl_label = "Reset GeoNodes Socket"
|
bl_label = 'Reset GeoNodes Socket'
|
||||||
|
|
||||||
node_tree_name: bpy.props.StringProperty(name="Node Tree Name")
|
node_tree_name: bpy.props.StringProperty(name='Node Tree Name')
|
||||||
node_name: bpy.props.StringProperty(name="Node Name")
|
node_name: bpy.props.StringProperty(name='Node Name')
|
||||||
socket_name: bpy.props.StringProperty(name="Socket Name")
|
socket_name: bpy.props.StringProperty(name='Socket Name')
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
node_tree = bpy.data.node_groups[self.node_tree_name]
|
node_tree = bpy.data.node_groups[self.node_tree_name]
|
||||||
|
@ -23,7 +24,7 @@ class BlenderMaxwellResetGeoNodesSocket(bpy.types.Operator):
|
||||||
socket = node.inputs[self.socket_name]
|
socket = node.inputs[self.socket_name]
|
||||||
|
|
||||||
# Report as though the GeoNodes Tree Changed
|
# Report as though the GeoNodes Tree Changed
|
||||||
socket.sync_prop("raw_value", context)
|
socket.sync_prop('raw_value', context)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
@ -33,23 +34,23 @@ class BlenderMaxwellResetGeoNodesSocket(bpy.types.Operator):
|
||||||
####################
|
####################
|
||||||
class BlenderGeoNodesBLSocket(base.MaxwellSimSocket):
|
class BlenderGeoNodesBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.BlenderGeoNodes
|
socket_type = ct.SocketType.BlenderGeoNodes
|
||||||
bl_label = "Geometry Node Tree"
|
bl_label = 'Geometry Node Tree'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.PointerProperty(
|
raw_value: bpy.props.PointerProperty(
|
||||||
name="Blender GeoNodes Tree",
|
name='Blender GeoNodes Tree',
|
||||||
description="Represents a Blender GeoNodes Tree",
|
description='Represents a Blender GeoNodes Tree',
|
||||||
type=bpy.types.NodeTree,
|
type=bpy.types.NodeTree,
|
||||||
poll=(lambda self, obj: obj.bl_idname == "GeometryNodeTree"),
|
poll=(lambda self, obj: obj.bl_idname == 'GeometryNodeTree'),
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
#def draw_label_row(self, label_col_row, text):
|
# def draw_label_row(self, label_col_row, text):
|
||||||
# label_col_row.label(text=text)
|
# label_col_row.label(text=text)
|
||||||
# if not self.raw_value: return
|
# if not self.raw_value: return
|
||||||
#
|
#
|
||||||
|
@ -66,7 +67,7 @@ class BlenderGeoNodesBLSocket(base.MaxwellSimSocket):
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, "raw_value", text="")
|
col.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
|
@ -79,6 +80,7 @@ class BlenderGeoNodesBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bpy.types.NodeTree) -> None:
|
def value(self, value: bpy.types.NodeTree) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -88,6 +90,7 @@ class BlenderGeoNodesSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BlenderGeoNodesBLSocket) -> None:
|
def init(self, bl_socket: BlenderGeoNodesBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -6,28 +6,29 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class BlenderImageBLSocket(base.MaxwellSimSocket):
|
class BlenderImageBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.BlenderImage
|
socket_type = ct.SocketType.BlenderImage
|
||||||
bl_label = "Blender Image"
|
bl_label = 'Blender Image'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.PointerProperty(
|
raw_value: bpy.props.PointerProperty(
|
||||||
name="Blender Image",
|
name='Blender Image',
|
||||||
description="Represents a Blender Image",
|
description='Represents a Blender Image',
|
||||||
type=bpy.types.Image,
|
type=bpy.types.Image,
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, "raw_value", text="")
|
col.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
|
@ -40,6 +41,7 @@ class BlenderImageBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bpy.types.Image) -> None:
|
def value(self, value: bpy.types.Image) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -49,9 +51,8 @@ class BlenderImageSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BlenderImageBLSocket) -> None:
|
def init(self, bl_socket: BlenderImageBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [BlenderImageBLSocket]
|
||||||
BlenderImageBLSocket
|
|
||||||
]
|
|
||||||
|
|
|
@ -6,16 +6,17 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Create and Assign BL Object
|
# - Create and Assign BL Object
|
||||||
####################
|
####################
|
||||||
class BlenderMaxwellCreateAndAssignBLObject(bpy.types.Operator):
|
class BlenderMaxwellCreateAndAssignBLObject(bpy.types.Operator):
|
||||||
bl_idname = "blender_maxwell.create_and_assign_bl_object"
|
bl_idname = 'blender_maxwell.create_and_assign_bl_object'
|
||||||
bl_label = "Create and Assign BL Object"
|
bl_label = 'Create and Assign BL Object'
|
||||||
|
|
||||||
node_tree_name = bpy.props.StringProperty(name="Node Tree Name")
|
node_tree_name = bpy.props.StringProperty(name='Node Tree Name')
|
||||||
node_name = bpy.props.StringProperty(name="Node Name")
|
node_name = bpy.props.StringProperty(name='Node Name')
|
||||||
socket_name = bpy.props.StringProperty(name="Socket Name")
|
socket_name = bpy.props.StringProperty(name='Socket Name')
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
node_tree = bpy.data.node_groups[self.node_tree_name]
|
node_tree = bpy.data.node_groups[self.node_tree_name]
|
||||||
|
@ -26,21 +27,22 @@ class BlenderMaxwellCreateAndAssignBLObject(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class BlenderObjectBLSocket(base.MaxwellSimSocket):
|
class BlenderObjectBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.BlenderObject
|
socket_type = ct.SocketType.BlenderObject
|
||||||
bl_label = "Blender Object"
|
bl_label = 'Blender Object'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.PointerProperty(
|
raw_value: bpy.props.PointerProperty(
|
||||||
name="Blender Object",
|
name='Blender Object',
|
||||||
description="Represents a Blender object",
|
description='Represents a Blender object',
|
||||||
type=bpy.types.Object,
|
type=bpy.types.Object,
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -50,24 +52,24 @@ class BlenderObjectBLSocket(base.MaxwellSimSocket):
|
||||||
label_col_row.label(text=text)
|
label_col_row.label(text=text)
|
||||||
|
|
||||||
op = label_col_row.operator(
|
op = label_col_row.operator(
|
||||||
"blender_maxwell.create_and_assign_bl_object",
|
'blender_maxwell.create_and_assign_bl_object',
|
||||||
text="",
|
text='',
|
||||||
icon="ADD",
|
icon='ADD',
|
||||||
)
|
)
|
||||||
op.socket_name = self.name
|
op.socket_name = self.name
|
||||||
op.node_name = self.node.name
|
op.node_name = self.node.name
|
||||||
op.node_tree_name = self.node.id_data.name
|
op.node_tree_name = self.node.id_data.name
|
||||||
|
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, "raw_value", text="")
|
col.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Methods
|
# - Methods
|
||||||
####################
|
####################
|
||||||
def create_and_assign_bl_object(self):
|
def create_and_assign_bl_object(self):
|
||||||
node_tree = self.node.id_data
|
node_tree = self.node.id_data
|
||||||
mesh = bpy.data.meshes.new("MaxwellMesh")
|
mesh = bpy.data.meshes.new('MaxwellMesh')
|
||||||
new_bl_object = bpy.data.objects.new("MaxwellObject", mesh)
|
new_bl_object = bpy.data.objects.new('MaxwellObject', mesh)
|
||||||
|
|
||||||
bpy.context.collection.objects.link(new_bl_object)
|
bpy.context.collection.objects.link(new_bl_object)
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ class BlenderObjectBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bpy.types.Object) -> None:
|
def value(self, value: bpy.types.Object) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -93,6 +96,7 @@ class BlenderObjectSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BlenderObjectBLSocket) -> None:
|
def init(self, bl_socket: BlenderObjectBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -6,28 +6,29 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
class BlenderTextBLSocket(base.MaxwellSimSocket):
|
class BlenderTextBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.BlenderText
|
socket_type = ct.SocketType.BlenderText
|
||||||
bl_label = "Blender Text"
|
bl_label = 'Blender Text'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
raw_value: bpy.props.PointerProperty(
|
raw_value: bpy.props.PointerProperty(
|
||||||
name="Blender Text",
|
name='Blender Text',
|
||||||
description="Represents a Blender text datablock",
|
description='Represents a Blender text datablock',
|
||||||
type=bpy.types.Text,
|
type=bpy.types.Text,
|
||||||
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
update=(lambda self, context: self.sync_prop('raw_value', context)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, "raw_value", text="")
|
col.prop(self, 'raw_value', text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
|
@ -40,6 +41,7 @@ class BlenderTextBLSocket(base.MaxwellSimSocket):
|
||||||
def value(self, value: bpy.types.Text) -> None:
|
def value(self, value: bpy.types.Text) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
|
@ -49,9 +51,8 @@ class BlenderTextSocketDef(pyd.BaseModel):
|
||||||
def init(self, bl_socket: BlenderTextBLSocket) -> None:
|
def init(self, bl_socket: BlenderTextBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [BlenderTextBLSocket]
|
||||||
BlenderTextBLSocket
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,22 +1,29 @@
|
||||||
from . import bound_cond
|
from . import bound_cond
|
||||||
from . import bound_conds
|
from . import bound_conds
|
||||||
|
|
||||||
MaxwellBoundCondSocketDef = bound_cond.MaxwellBoundCondSocketDef
|
MaxwellBoundCondSocketDef = bound_cond.MaxwellBoundCondSocketDef
|
||||||
MaxwellBoundCondsSocketDef = bound_conds.MaxwellBoundCondsSocketDef
|
MaxwellBoundCondsSocketDef = bound_conds.MaxwellBoundCondsSocketDef
|
||||||
|
|
||||||
from . import medium
|
from . import medium
|
||||||
from . import medium_non_linearity
|
from . import medium_non_linearity
|
||||||
|
|
||||||
MaxwellMediumSocketDef = medium.MaxwellMediumSocketDef
|
MaxwellMediumSocketDef = medium.MaxwellMediumSocketDef
|
||||||
MaxwellMediumNonLinearitySocketDef = medium_non_linearity.MaxwellMediumNonLinearitySocketDef
|
MaxwellMediumNonLinearitySocketDef = (
|
||||||
|
medium_non_linearity.MaxwellMediumNonLinearitySocketDef
|
||||||
|
)
|
||||||
|
|
||||||
from . import source
|
from . import source
|
||||||
from . import temporal_shape
|
from . import temporal_shape
|
||||||
|
|
||||||
MaxwellSourceSocketDef = source.MaxwellSourceSocketDef
|
MaxwellSourceSocketDef = source.MaxwellSourceSocketDef
|
||||||
MaxwellTemporalShapeSocketDef = temporal_shape.MaxwellTemporalShapeSocketDef
|
MaxwellTemporalShapeSocketDef = temporal_shape.MaxwellTemporalShapeSocketDef
|
||||||
|
|
||||||
from . import structure
|
from . import structure
|
||||||
|
|
||||||
MaxwellStructureSocketDef = structure.MaxwellStructureSocketDef
|
MaxwellStructureSocketDef = structure.MaxwellStructureSocketDef
|
||||||
|
|
||||||
from . import monitor
|
from . import monitor
|
||||||
|
|
||||||
MaxwellMonitorSocketDef = monitor.MaxwellMonitorSocketDef
|
MaxwellMonitorSocketDef = monitor.MaxwellMonitorSocketDef
|
||||||
|
|
||||||
from . import fdtd_sim
|
from . import fdtd_sim
|
||||||
|
@ -24,6 +31,7 @@ from . import fdtd_sim_data
|
||||||
from . import sim_grid
|
from . import sim_grid
|
||||||
from . import sim_grid_axis
|
from . import sim_grid_axis
|
||||||
from . import sim_domain
|
from . import sim_domain
|
||||||
|
|
||||||
MaxwellFDTDSimSocketDef = fdtd_sim.MaxwellFDTDSimSocketDef
|
MaxwellFDTDSimSocketDef = fdtd_sim.MaxwellFDTDSimSocketDef
|
||||||
MaxwellFDTDSimDataSocketDef = fdtd_sim_data.MaxwellFDTDSimDataSocketDef
|
MaxwellFDTDSimDataSocketDef = fdtd_sim_data.MaxwellFDTDSimDataSocketDef
|
||||||
MaxwellSimGridSocketDef = sim_grid.MaxwellSimGridSocketDef
|
MaxwellSimGridSocketDef = sim_grid.MaxwellSimGridSocketDef
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue