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,47 +26,47 @@ 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.
|
||||||
|
|
||||||
Since there are no 2D sockets in Blender, the user can specify "2D" in the Blender socket's description to "promise" that only the first two values will be used.
|
Since there are no 2D sockets in Blender, the user can specify "2D" in the Blender socket's description to "promise" that only the first two values will be used.
|
||||||
When this is done, the third value is left entirely untouched by this entire system.
|
When this is done, the third value is left entirely untouched by this entire system.
|
||||||
|
|
||||||
A hard-coded set of NodeSocket<Type> prefixes are used to determine which interface sockets are, in fact, 3D.
|
A hard-coded set of NodeSocket<Type> prefixes are used to determine which interface sockets are, in fact, 3D.
|
||||||
- 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
|
||||||
|
@ -77,7 +77,7 @@ def size_from_bl_interface_socket(
|
||||||
for bl_socket_4d_type_prefix in BL_SOCKET_4D_TYPE_PREFIXES
|
for bl_socket_4d_type_prefix in BL_SOCKET_4D_TYPE_PREFIXES
|
||||||
):
|
):
|
||||||
return 4
|
return 4
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,15 +88,15 @@ def parse_bl_interface_socket(
|
||||||
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
bl_interface_socket: bpy.types.NodeTreeInterfaceSocket,
|
||||||
) -> tuple[ST, sp.Expr | None]:
|
) -> tuple[ST, sp.Expr | None]:
|
||||||
"""Parse a Blender interface socket by parsing its description, falling back to any direct type links.
|
"""Parse a Blender interface socket by parsing its description, falling back to any direct type links.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
bl_interface_socket: An interface socket associated with the global input to a node tree.
|
bl_interface_socket: An interface socket associated with the global input to a node tree.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The type of a corresponding MaxwellSimSocket, as well as a unit (if a particular unit was requested by the Blender interface socket).
|
The type of a corresponding MaxwellSimSocket, as well as a unit (if a particular unit was requested by the Blender interface socket).
|
||||||
"""
|
"""
|
||||||
size = size_from_bl_interface_socket(bl_interface_socket)
|
size = size_from_bl_interface_socket(bl_interface_socket)
|
||||||
|
|
||||||
# Determine Direct Socket Type
|
# Determine Direct Socket Type
|
||||||
if (
|
if (
|
||||||
direct_socket_type := ct.BL_SOCKET_DIRECT_TYPE_MAP.get(
|
direct_socket_type := ct.BL_SOCKET_DIRECT_TYPE_MAP.get(
|
||||||
|
@ -105,44 +105,55 @@ def parse_bl_interface_socket(
|
||||||
) is None:
|
) is None:
|
||||||
msg = "Blender interface socket has no mapping among 'MaxwellSimSocket's."
|
msg = "Blender interface socket has no mapping among 'MaxwellSimSocket's."
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# (Maybe) Return Direct Socket Type
|
# (Maybe) Return Direct Socket Type
|
||||||
## When there's no description, that's it; return.
|
## When there's no description, that's it; return.
|
||||||
if not ct.BL_SOCKET_DESCR_ANNOT_STRING in bl_interface_socket.description:
|
if not ct.BL_SOCKET_DESCR_ANNOT_STRING in bl_interface_socket.description:
|
||||||
return (direct_socket_type, None)
|
return (direct_socket_type, None)
|
||||||
|
|
||||||
# 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 (
|
||||||
socket_type := ct.BL_SOCKET_DESCR_TYPE_MAP.get(
|
socket_type := ct.BL_SOCKET_DESCR_TYPE_MAP.get(
|
||||||
(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 = (
|
||||||
unit
|
_socket_unit
|
||||||
for unit in ct.SOCKET_UNITS[socket_type]["values"].values()
|
if (
|
||||||
if str(unit) == unit_token
|
_socket_unit := [
|
||||||
]) else ct.SOCKET_UNITS[socket_type]["values"][
|
unit
|
||||||
ct.SOCKET_UNITS[socket_type]["default"]
|
for unit in ct.SOCKET_UNITS[socket_type][
|
||||||
]
|
'values'
|
||||||
|
].values()
|
||||||
|
if str(unit) == unit_token
|
||||||
|
]
|
||||||
|
)
|
||||||
|
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]
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -169,7 +177,7 @@ def value_from_bl(
|
||||||
"""Reads the value of any Blender socket, and writes its `default_value` to the `value` of any `MaxwellSimSocket`.
|
"""Reads the value of any Blender socket, and writes its `default_value` to the `value` of any `MaxwellSimSocket`.
|
||||||
- If the size of the Blender socket is >1, then `value` is written to as a `sympy.Matrix`.
|
- If the size of the Blender socket is >1, then `value` is written to as a `sympy.Matrix`.
|
||||||
- If a unit system is given, then the Blender socket is matched to a `MaxwellSimSocket`, which is used to lookup an appropriate unit in the given `unit_system`.
|
- If a unit system is given, then the Blender socket is matched to a `MaxwellSimSocket`, which is used to lookup an appropriate unit in the given `unit_system`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
## TODO: Consider sympy.S()'ing the default_value
|
## TODO: Consider sympy.S()'ing the default_value
|
||||||
parsed_bl_socket_value = {
|
parsed_bl_socket_value = {
|
||||||
|
@ -179,24 +187,25 @@ def value_from_bl(
|
||||||
4: lambda: sp.Matrix(tuple(bl_interface_socket.default_value)),
|
4: lambda: sp.Matrix(tuple(bl_interface_socket.default_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
|
||||||
|
|
||||||
socket_type, unit = parse_bl_interface_socket(bl_interface_socket)
|
socket_type, unit = parse_bl_interface_socket(bl_interface_socket)
|
||||||
|
|
||||||
# Add Unit to Parsed (if relevant)
|
# Add Unit to Parsed (if relevant)
|
||||||
if unit is not None:
|
if unit is not None:
|
||||||
parsed_bl_socket_value *= unit
|
parsed_bl_socket_value *= unit
|
||||||
elif unit_system is not None:
|
elif unit_system is not None:
|
||||||
parsed_bl_socket_value *= unit_system[socket_type]
|
parsed_bl_socket_value *= unit_system[socket_type]
|
||||||
|
|
||||||
return parsed_bl_socket_value
|
return parsed_bl_socket_value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Convert to Blender-Compatible Value
|
# - Convert to Blender-Compatible Value
|
||||||
####################
|
####################
|
||||||
def make_scalar_bl_compat(scalar: typ.Any) -> typ.Any:
|
def make_scalar_bl_compat(scalar: typ.Any) -> typ.Any:
|
||||||
"""Blender doesn't accept ex. Sympy numbers as values.
|
"""Blender doesn't accept ex. Sympy numbers as values.
|
||||||
Therefore, we need to do some conforming.
|
Therefore, we need to do some conforming.
|
||||||
|
|
||||||
Currently hard-coded; this is probably best.
|
Currently hard-coded; this is probably best.
|
||||||
"""
|
"""
|
||||||
if isinstance(scalar, sp.Integer):
|
if isinstance(scalar, sp.Integer):
|
||||||
|
@ -208,44 +217,43 @@ def make_scalar_bl_compat(scalar: typ.Any) -> typ.Any:
|
||||||
elif isinstance(scalar, sp.Expr):
|
elif isinstance(scalar, sp.Expr):
|
||||||
return float(scalar.n())
|
return float(scalar.n())
|
||||||
## TODO: More?
|
## TODO: More?
|
||||||
|
|
||||||
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,
|
||||||
unit_system: dict | None = None,
|
unit_system: dict | None = None,
|
||||||
) -> typ.Any:
|
) -> typ.Any:
|
||||||
socket_type, unit = parse_bl_interface_socket(bl_interface_socket)
|
socket_type, unit = parse_bl_interface_socket(bl_interface_socket)
|
||||||
|
|
||||||
# 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[1]),
|
make_scalar_bl_compat(bl_socket_value[0]),
|
||||||
bl_interface_socket.default_value[2]
|
make_scalar_bl_compat(bl_socket_value[1]),
|
||||||
## Don't touch (unused) 3rd bl_socket coordinate
|
bl_interface_socket.default_value[2],
|
||||||
]),
|
## Don't touch (unused) 3rd bl_socket coordinate
|
||||||
3: lambda: tuple([
|
]
|
||||||
make_scalar_bl_compat(el)
|
),
|
||||||
for el in bl_socket_value
|
3: lambda: tuple(
|
||||||
]),
|
[make_scalar_bl_compat(el) for el in bl_socket_value]
|
||||||
4: lambda: tuple([
|
),
|
||||||
make_scalar_bl_compat(el)
|
4: lambda: tuple(
|
||||||
for el in bl_socket_value
|
[make_scalar_bl_compat(el) 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,34 +6,35 @@ 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))
|
||||||
|
|
||||||
# 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):
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -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,34 +53,39 @@ 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(
|
||||||
'bl_idname': current_category.value,
|
str(current_category.value),
|
||||||
'bl_label': ct.NODE_CAT_LABELS[current_category],
|
(bpy.types.Menu,),
|
||||||
'draw': draw_factory(tuple(subitems)),
|
{
|
||||||
})
|
'bl_idname': current_category.value,
|
||||||
|
'bl_label': ct.NODE_CAT_LABELS[current_category],
|
||||||
|
'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)
|
||||||
DYNAMIC_SUBMENU_REGISTRATIONS.append(menu_class)
|
DYNAMIC_SUBMENU_REGISTRATIONS.append(menu_class)
|
||||||
|
|
||||||
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:
|
||||||
|
@ -87,5 +93,6 @@ def menu_draw(self, context):
|
||||||
if isinstance(nodeitem_or_submenu, str):
|
if 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)
|
||||||
|
|
||||||
|
|
||||||
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[
|
||||||
pattern=r'^[A-Z_]+$',
|
str,
|
||||||
)]
|
pyd.StringConstraints(
|
||||||
SocketName = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
pattern=r'^[A-Z_]+$',
|
||||||
pattern=r'^[a-zA-Z0-9_]+$',
|
),
|
||||||
)]
|
]
|
||||||
PresetName = pytypes_ext.Annotated[str, pyd.StringConstraints(
|
SocketName = pytypes_ext.Annotated[
|
||||||
pattern=r'^[a-zA-Z0-9_]+$',
|
str,
|
||||||
)]
|
pyd.StringConstraints(
|
||||||
|
pattern=r'^[a-zA-Z0-9_]+$',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
PresetName = pytypes_ext.Annotated[
|
||||||
|
str,
|
||||||
|
pyd.StringConstraints(
|
||||||
|
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[
|
||||||
pattern=r'^[a-z_]+$',
|
str,
|
||||||
)]
|
pyd.StringConstraints(
|
||||||
|
pattern=r'^[a-z_]+$',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
|
@ -2,11 +2,12 @@ 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.
|
||||||
|
|
||||||
Since a node socket may define one of each, we can support several related kinds of data flow through the same node-graph infrastructure.
|
Since a node socket may define one of each, we can support several related kinds of data flow through the same node-graph infrastructure.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
Value: A value usable without new data.
|
Value: A value usable without new data.
|
||||||
- Basic types aka. float, int, list, string, etc. .
|
- Basic types aka. float, int, list, string, etc. .
|
||||||
|
@ -14,43 +15,43 @@ class DataFlowKind(BlenderTypeEnum):
|
||||||
- A usable constructed object, ex. a `tidy3d.Box`.
|
- A usable constructed object, ex. a `tidy3d.Box`.
|
||||||
- Expressions (`sp.Expr`) that don't have unknown variables.
|
- Expressions (`sp.Expr`) that don't have unknown variables.
|
||||||
- Lazy sequences aka. generators, with all data bound.
|
- Lazy sequences aka. generators, with all data bound.
|
||||||
|
|
||||||
LazyValue: An object which, when given new data, can make many values.
|
LazyValue: An object which, when given new data, can make many values.
|
||||||
- An `sp.Expr`, which might need `simplify`ing, `jax` JIT'ing, unit cancellations, variable substitutions, etc. before use.
|
- An `sp.Expr`, which might need `simplify`ing, `jax` JIT'ing, unit cancellations, variable substitutions, etc. before use.
|
||||||
- Lazy objects, for which all parameters aren't yet known.
|
- Lazy objects, for which all parameters aren't yet known.
|
||||||
- A computational graph aka. `aesara`, which may even need to be handled before
|
- A computational graph aka. `aesara`, which may even need to be handled before
|
||||||
|
|
||||||
Capabilities: A `ValueCapability` object providing compatibility.
|
Capabilities: A `ValueCapability` object providing compatibility.
|
||||||
|
|
||||||
# Value Data Flow
|
# Value Data Flow
|
||||||
Simply passing values is the simplest and easiest use case.
|
Simply passing values is the simplest and easiest use case.
|
||||||
|
|
||||||
This doesn't mean it's "dumb" - ex. a `sp.Expr` might, before use, have `simplify`, rewriting, unit cancellation, etc. run.
|
This doesn't mean it's "dumb" - ex. a `sp.Expr` might, before use, have `simplify`, rewriting, unit cancellation, etc. run.
|
||||||
All of this is okay, as long as there is no *introduction of new data* ex. variable substitutions.
|
All of this is okay, as long as there is no *introduction of new data* ex. variable substitutions.
|
||||||
|
|
||||||
|
|
||||||
# Lazy Value Data Flow
|
# Lazy Value Data Flow
|
||||||
By passing (essentially) functions, one supports:
|
By passing (essentially) functions, one supports:
|
||||||
- **Lightness**: While lazy values can be made expensive to construct, they will generally not be nearly as heavy to handle when trying to work with ex. operations on voxel arrays.
|
- **Lightness**: While lazy values can be made expensive to construct, they will generally not be nearly as heavy to handle when trying to work with ex. operations on voxel arrays.
|
||||||
- **Performance**: Parameterizing ex. `sp.Expr` with variables allows one to build very optimized functions, which can make ex. node graph updates very fast if the only operation run is the `jax` JIT'ed function (aka. GPU accelerated) generated from the final full expression.
|
- **Performance**: Parameterizing ex. `sp.Expr` with variables allows one to build very optimized functions, which can make ex. node graph updates very fast if the only operation run is the `jax` JIT'ed function (aka. GPU accelerated) generated from the final full expression.
|
||||||
- **Numerical Stability**: Libraries like `aesara` build a computational graph, which can be automatically rewritten to avoid many obvious conditioning / cancellation errors.
|
- **Numerical Stability**: Libraries like `aesara` build a computational graph, which can be automatically rewritten to avoid many obvious conditioning / cancellation errors.
|
||||||
- **Lazy Output**: The goal of a node-graph may not be the definition of a single value, but rather, a parameterized expression for generating *many values* with known properties. This is especially interesting for use cases where one wishes to build an optimization step using nodes.
|
- **Lazy Output**: The goal of a node-graph may not be the definition of a single value, but rather, a parameterized expression for generating *many values* with known properties. This is especially interesting for use cases where one wishes to build an optimization step using nodes.
|
||||||
|
|
||||||
|
|
||||||
# Capability Passing
|
# Capability Passing
|
||||||
By being able to pass "capabilities" next to other kinds of values, nodes can quickly determine whether a given link is valid without having to actually compute it.
|
By being able to pass "capabilities" next to other kinds of values, nodes can quickly determine whether a given link is valid without having to actually compute it.
|
||||||
|
|
||||||
|
|
||||||
# Lazy Parameter Value
|
# Lazy Parameter Value
|
||||||
When using parameterized LazyValues, one may wish to independently pass parameter values through the graph, so they can be inserted into the final (cached) high-performance expression without.
|
When using parameterized LazyValues, one may wish to independently pass parameter values through the graph, so they can be inserted into the final (cached) high-performance expression without.
|
||||||
|
|
||||||
The advantage of using a different data flow would be changing this kind of value would ONLY invalidate lazy parameter value caches, which would allow an incredibly fast path of getting the value into the lazy expression for high-performance computation.
|
The advantage of using a different data flow would be changing this kind of value would ONLY invalidate lazy parameter value caches, which would allow an incredibly fast path of getting the value into the lazy expression for high-performance computation.
|
||||||
|
|
||||||
Implementation TBD - though, ostensibly, one would have a "parameter" node which both would only provide a LazyValue (aka. a symbolic variable), but would also be able to provide a LazyParamValue, which would be a particular value of some kind (probably via the `value` of some other node socket).
|
Implementation TBD - though, ostensibly, one would have a "parameter" node which both would only provide a LazyValue (aka. a symbolic variable), but would also be able to provide a LazyParamValue, which would be a particular value of some kind (probably via the `value` of some other node socket).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Value = enum.auto()
|
Value = enum.auto()
|
||||||
LazyValue = enum.auto()
|
LazyValue = enum.auto()
|
||||||
Capabilities = enum.auto()
|
Capabilities = enum.auto()
|
||||||
|
|
||||||
LazyParamValue = enum.auto()
|
LazyParamValue = enum.auto()
|
||||||
|
|
|
@ -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,13 +1,12 @@
|
||||||
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):
|
||||||
MAXWELLSIM = enum.auto()
|
MAXWELLSIM = enum.auto()
|
||||||
|
|
||||||
# Inputs/
|
# Inputs/
|
||||||
MAXWELLSIM_INPUTS = enum.auto()
|
MAXWELLSIM_INPUTS = enum.auto()
|
||||||
MAXWELLSIM_INPUTS_IMPORTERS = enum.auto()
|
MAXWELLSIM_INPUTS_IMPORTERS = enum.auto()
|
||||||
|
@ -15,63 +14,63 @@ class NodeCategory(BlenderTypeEnum):
|
||||||
MAXWELLSIM_INPUTS_PARAMETERS = enum.auto()
|
MAXWELLSIM_INPUTS_PARAMETERS = enum.auto()
|
||||||
MAXWELLSIM_INPUTS_CONSTANTS = enum.auto()
|
MAXWELLSIM_INPUTS_CONSTANTS = enum.auto()
|
||||||
MAXWELLSIM_INPUTS_LISTS = enum.auto()
|
MAXWELLSIM_INPUTS_LISTS = enum.auto()
|
||||||
|
|
||||||
# Outputs/
|
# Outputs/
|
||||||
MAXWELLSIM_OUTPUTS = enum.auto()
|
MAXWELLSIM_OUTPUTS = enum.auto()
|
||||||
MAXWELLSIM_OUTPUTS_VIEWERS = enum.auto()
|
MAXWELLSIM_OUTPUTS_VIEWERS = enum.auto()
|
||||||
MAXWELLSIM_OUTPUTS_EXPORTERS = enum.auto()
|
MAXWELLSIM_OUTPUTS_EXPORTERS = enum.auto()
|
||||||
MAXWELLSIM_OUTPUTS_PLOTTERS = enum.auto()
|
MAXWELLSIM_OUTPUTS_PLOTTERS = enum.auto()
|
||||||
|
|
||||||
# Sources/
|
# Sources/
|
||||||
MAXWELLSIM_SOURCES = enum.auto()
|
MAXWELLSIM_SOURCES = enum.auto()
|
||||||
MAXWELLSIM_SOURCES_TEMPORALSHAPES = enum.auto()
|
MAXWELLSIM_SOURCES_TEMPORALSHAPES = enum.auto()
|
||||||
|
|
||||||
# Mediums/
|
# Mediums/
|
||||||
MAXWELLSIM_MEDIUMS = enum.auto()
|
MAXWELLSIM_MEDIUMS = enum.auto()
|
||||||
MAXWELLSIM_MEDIUMS_NONLINEARITIES = enum.auto()
|
MAXWELLSIM_MEDIUMS_NONLINEARITIES = enum.auto()
|
||||||
|
|
||||||
# Structures/
|
# Structures/
|
||||||
MAXWELLSIM_STRUCTURES = enum.auto()
|
MAXWELLSIM_STRUCTURES = enum.auto()
|
||||||
MAXWELLSIM_STRUCTURES_PRIMITIVES = enum.auto()
|
MAXWELLSIM_STRUCTURES_PRIMITIVES = enum.auto()
|
||||||
|
|
||||||
# Bounds/
|
# Bounds/
|
||||||
MAXWELLSIM_BOUNDS = enum.auto()
|
MAXWELLSIM_BOUNDS = enum.auto()
|
||||||
MAXWELLSIM_BOUNDS_BOUNDCONDS = enum.auto()
|
MAXWELLSIM_BOUNDS_BOUNDCONDS = enum.auto()
|
||||||
|
|
||||||
# Monitors/
|
# Monitors/
|
||||||
MAXWELLSIM_MONITORS = enum.auto()
|
MAXWELLSIM_MONITORS = enum.auto()
|
||||||
MAXWELLSIM_MONITORS_NEARFIELDPROJECTIONS = enum.auto()
|
MAXWELLSIM_MONITORS_NEARFIELDPROJECTIONS = enum.auto()
|
||||||
|
|
||||||
# Simulations/
|
# Simulations/
|
||||||
MAXWELLSIM_SIMS = enum.auto()
|
MAXWELLSIM_SIMS = enum.auto()
|
||||||
MAXWELLSIM_SIMGRIDAXES = enum.auto()
|
MAXWELLSIM_SIMGRIDAXES = enum.auto()
|
||||||
|
|
||||||
# Utilities/
|
# Utilities/
|
||||||
MAXWELLSIM_UTILITIES = enum.auto()
|
MAXWELLSIM_UTILITIES = enum.auto()
|
||||||
MAXWELLSIM_UTILITIES_CONVERTERS = enum.auto()
|
MAXWELLSIM_UTILITIES_CONVERTERS = enum.auto()
|
||||||
MAXWELLSIM_UTILITIES_OPERATIONS = enum.auto()
|
MAXWELLSIM_UTILITIES_OPERATIONS = enum.auto()
|
||||||
|
|
||||||
# Viz/
|
# Viz/
|
||||||
MAXWELLSIM_VIZ = enum.auto()
|
MAXWELLSIM_VIZ = enum.auto()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
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 = {}
|
||||||
for syllable_category in syllable_categories:
|
for syllable_category in syllable_categories:
|
||||||
# Set Current Subtree to Root
|
# Set Current Subtree to Root
|
||||||
current_category_subtree = category_tree
|
current_category_subtree = category_tree
|
||||||
|
|
||||||
for i, syllable in enumerate(syllable_category):
|
for i, syllable in enumerate(syllable_category):
|
||||||
# Create New Category Subtree and/or Step to Subtree
|
# Create New Category Subtree and/or Step to Subtree
|
||||||
if syllable not in current_category_subtree:
|
if syllable not in current_category_subtree:
|
||||||
current_category_subtree[syllable] = {}
|
current_category_subtree[syllable] = {}
|
||||||
current_category_subtree = current_category_subtree[syllable]
|
current_category_subtree = current_category_subtree[syllable]
|
||||||
|
|
||||||
return category_tree
|
return category_tree
|
||||||
|
|
|
@ -1,58 +1,58 @@
|
||||||
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()
|
||||||
|
|
||||||
# Inputs
|
# Inputs
|
||||||
UnitSystem = enum.auto()
|
UnitSystem = enum.auto()
|
||||||
|
|
||||||
## Inputs / Scene
|
## Inputs / Scene
|
||||||
Time = enum.auto()
|
Time = enum.auto()
|
||||||
|
|
||||||
## Inputs / Importers
|
## Inputs / Importers
|
||||||
Tidy3DWebImporter = enum.auto()
|
Tidy3DWebImporter = enum.auto()
|
||||||
|
|
||||||
## Inputs / Parameters
|
## Inputs / Parameters
|
||||||
NumberParameter = enum.auto()
|
NumberParameter = enum.auto()
|
||||||
PhysicalParameter = enum.auto()
|
PhysicalParameter = enum.auto()
|
||||||
|
|
||||||
## Inputs / Constants
|
## Inputs / Constants
|
||||||
WaveConstant = enum.auto()
|
WaveConstant = enum.auto()
|
||||||
ScientificConstant = enum.auto()
|
ScientificConstant = enum.auto()
|
||||||
NumberConstant = enum.auto()
|
NumberConstant = enum.auto()
|
||||||
PhysicalConstant = enum.auto()
|
PhysicalConstant = enum.auto()
|
||||||
BlenderConstant = enum.auto()
|
BlenderConstant = enum.auto()
|
||||||
|
|
||||||
## Inputs / Lists
|
## Inputs / Lists
|
||||||
RealList = enum.auto()
|
RealList = enum.auto()
|
||||||
ComplexList = enum.auto()
|
ComplexList = enum.auto()
|
||||||
|
|
||||||
## Inputs /
|
## Inputs /
|
||||||
InputFile = enum.auto()
|
InputFile = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Outputs
|
# Outputs
|
||||||
## Outputs / Viewers
|
## Outputs / Viewers
|
||||||
Viewer = enum.auto()
|
Viewer = enum.auto()
|
||||||
ValueViewer = enum.auto()
|
ValueViewer = enum.auto()
|
||||||
ConsoleViewer = enum.auto()
|
ConsoleViewer = enum.auto()
|
||||||
|
|
||||||
## Outputs / Exporters
|
## Outputs / Exporters
|
||||||
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()
|
||||||
ContinuousWaveTemporalShape = enum.auto()
|
ContinuousWaveTemporalShape = enum.auto()
|
||||||
ListTemporalShape = enum.auto()
|
ListTemporalShape = enum.auto()
|
||||||
|
|
||||||
## Sources /
|
## Sources /
|
||||||
PointDipoleSource = enum.auto()
|
PointDipoleSource = enum.auto()
|
||||||
UniformCurrentSource = enum.auto()
|
UniformCurrentSource = enum.auto()
|
||||||
|
@ -61,92 +61,86 @@ class NodeType(BlenderTypeEnum):
|
||||||
GaussianBeamSource = enum.auto()
|
GaussianBeamSource = enum.auto()
|
||||||
AstigmaticGaussianBeamSource = enum.auto()
|
AstigmaticGaussianBeamSource = enum.auto()
|
||||||
TFSFSource = enum.auto()
|
TFSFSource = enum.auto()
|
||||||
|
|
||||||
EHEquivalenceSource = enum.auto()
|
EHEquivalenceSource = enum.auto()
|
||||||
EHSource = enum.auto()
|
EHSource = enum.auto()
|
||||||
|
|
||||||
# Mediums
|
# Mediums
|
||||||
LibraryMedium = enum.auto()
|
LibraryMedium = enum.auto()
|
||||||
|
|
||||||
PECMedium = enum.auto()
|
PECMedium = enum.auto()
|
||||||
IsotropicMedium = enum.auto()
|
IsotropicMedium = enum.auto()
|
||||||
AnisotropicMedium = enum.auto()
|
AnisotropicMedium = enum.auto()
|
||||||
|
|
||||||
TripleSellmeierMedium = enum.auto()
|
TripleSellmeierMedium = enum.auto()
|
||||||
SellmeierMedium = enum.auto()
|
SellmeierMedium = enum.auto()
|
||||||
PoleResidueMedium = enum.auto()
|
PoleResidueMedium = enum.auto()
|
||||||
DrudeMedium = enum.auto()
|
DrudeMedium = enum.auto()
|
||||||
DrudeLorentzMedium = enum.auto()
|
DrudeLorentzMedium = enum.auto()
|
||||||
DebyeMedium = enum.auto()
|
DebyeMedium = enum.auto()
|
||||||
|
|
||||||
## Mediums / Non-Linearities
|
## Mediums / Non-Linearities
|
||||||
AddNonLinearity = enum.auto()
|
AddNonLinearity = enum.auto()
|
||||||
ChiThreeSusceptibilityNonLinearity = enum.auto()
|
ChiThreeSusceptibilityNonLinearity = enum.auto()
|
||||||
TwoPhotonAbsorptionNonLinearity = enum.auto()
|
TwoPhotonAbsorptionNonLinearity = enum.auto()
|
||||||
KerrNonLinearity = enum.auto()
|
KerrNonLinearity = enum.auto()
|
||||||
|
|
||||||
# Structures
|
# Structures
|
||||||
ObjectStructure = enum.auto()
|
ObjectStructure = enum.auto()
|
||||||
GeoNodesStructure = enum.auto()
|
GeoNodesStructure = enum.auto()
|
||||||
ScriptedStructure = enum.auto()
|
ScriptedStructure = enum.auto()
|
||||||
|
|
||||||
## Structures / Primitives
|
## Structures / Primitives
|
||||||
BoxStructure = enum.auto()
|
BoxStructure = enum.auto()
|
||||||
SphereStructure = enum.auto()
|
SphereStructure = enum.auto()
|
||||||
CylinderStructure = enum.auto()
|
CylinderStructure = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Bounds
|
# Bounds
|
||||||
BoundConds = enum.auto()
|
BoundConds = enum.auto()
|
||||||
|
|
||||||
## Bounds / Bound Faces
|
## Bounds / Bound Faces
|
||||||
PMLBoundCond = enum.auto()
|
PMLBoundCond = enum.auto()
|
||||||
PECBoundCond = enum.auto()
|
PECBoundCond = enum.auto()
|
||||||
PMCBoundCond = enum.auto()
|
PMCBoundCond = enum.auto()
|
||||||
|
|
||||||
BlochBoundCond = enum.auto()
|
BlochBoundCond = enum.auto()
|
||||||
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()
|
||||||
EpsilonTensorMonitor = enum.auto()
|
EpsilonTensorMonitor = enum.auto()
|
||||||
DiffractionMonitor = enum.auto()
|
DiffractionMonitor = enum.auto()
|
||||||
|
|
||||||
## Monitors / Near-Field Projections
|
## Monitors / Near-Field Projections
|
||||||
CartesianNearFieldProjectionMonitor = enum.auto()
|
CartesianNearFieldProjectionMonitor = enum.auto()
|
||||||
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()
|
||||||
|
|
||||||
## Sims / Sim Grid Axis
|
## Sims / Sim Grid Axis
|
||||||
AutomaticSimGridAxis = enum.auto()
|
AutomaticSimGridAxis = enum.auto()
|
||||||
ManualSimGridAxis = enum.auto()
|
ManualSimGridAxis = enum.auto()
|
||||||
UniformSimGridAxis = enum.auto()
|
UniformSimGridAxis = enum.auto()
|
||||||
ArraySimGridAxis = enum.auto()
|
ArraySimGridAxis = enum.auto()
|
||||||
|
|
||||||
## Sim /
|
## Sim /
|
||||||
FDTDSim = enum.auto()
|
FDTDSim = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
Combine = enum.auto()
|
Combine = enum.auto()
|
||||||
Separate = enum.auto()
|
Separate = enum.auto()
|
||||||
Math = enum.auto()
|
Math = enum.auto()
|
||||||
|
|
||||||
## Utilities / Converters
|
## Utilities / Converters
|
||||||
WaveConverter = enum.auto()
|
WaveConverter = enum.auto()
|
||||||
|
|
||||||
## Utilities / Operations
|
## Utilities / Operations
|
||||||
ArrayOperation = enum.auto()
|
ArrayOperation = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Viz
|
# Viz
|
||||||
FDTDSimDataViz = enum.auto()
|
FDTDSimDataViz = enum.auto()
|
||||||
|
|
|
@ -6,21 +6,19 @@ from ..managed_obj_type import ManagedObjType
|
||||||
|
|
||||||
class ManagedObj(typ.Protocol):
|
class ManagedObj(typ.Protocol):
|
||||||
managed_obj_type: ManagedObjType
|
managed_obj_type: ManagedObjType
|
||||||
|
|
||||||
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
|
||||||
|
@ -12,43 +15,43 @@ class SocketType(BlenderTypeEnum):
|
||||||
String = enum.auto()
|
String = enum.auto()
|
||||||
FilePath = enum.auto()
|
FilePath = enum.auto()
|
||||||
Color = enum.auto()
|
Color = enum.auto()
|
||||||
|
|
||||||
# Number
|
# Number
|
||||||
IntegerNumber = enum.auto()
|
IntegerNumber = enum.auto()
|
||||||
RationalNumber = enum.auto()
|
RationalNumber = enum.auto()
|
||||||
RealNumber = enum.auto()
|
RealNumber = enum.auto()
|
||||||
ComplexNumber = enum.auto()
|
ComplexNumber = enum.auto()
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
Integer2DVector = enum.auto()
|
Integer2DVector = enum.auto()
|
||||||
Real2DVector = enum.auto()
|
Real2DVector = enum.auto()
|
||||||
Real2DVectorDir = enum.auto()
|
Real2DVectorDir = enum.auto()
|
||||||
Complex2DVector = enum.auto()
|
Complex2DVector = enum.auto()
|
||||||
|
|
||||||
Integer3DVector = enum.auto()
|
Integer3DVector = enum.auto()
|
||||||
Real3DVector = enum.auto()
|
Real3DVector = enum.auto()
|
||||||
Real3DVectorDir = enum.auto()
|
Real3DVectorDir = enum.auto()
|
||||||
Complex3DVector = enum.auto()
|
Complex3DVector = enum.auto()
|
||||||
|
|
||||||
# Blender
|
# Blender
|
||||||
BlenderObject = enum.auto()
|
BlenderObject = enum.auto()
|
||||||
BlenderCollection = enum.auto()
|
BlenderCollection = enum.auto()
|
||||||
|
|
||||||
BlenderImage = enum.auto()
|
BlenderImage = enum.auto()
|
||||||
|
|
||||||
BlenderGeoNodes = enum.auto()
|
BlenderGeoNodes = enum.auto()
|
||||||
BlenderText = enum.auto()
|
BlenderText = enum.auto()
|
||||||
|
|
||||||
# Maxwell
|
# Maxwell
|
||||||
MaxwellBoundConds = enum.auto()
|
MaxwellBoundConds = enum.auto()
|
||||||
MaxwellBoundCond = enum.auto()
|
MaxwellBoundCond = enum.auto()
|
||||||
|
|
||||||
MaxwellMedium = enum.auto()
|
MaxwellMedium = enum.auto()
|
||||||
MaxwellMediumNonLinearity = enum.auto()
|
MaxwellMediumNonLinearity = enum.auto()
|
||||||
|
|
||||||
MaxwellSource = enum.auto()
|
MaxwellSource = enum.auto()
|
||||||
MaxwellTemporalShape = enum.auto()
|
MaxwellTemporalShape = enum.auto()
|
||||||
|
|
||||||
MaxwellStructure = enum.auto()
|
MaxwellStructure = enum.auto()
|
||||||
MaxwellMonitor = enum.auto()
|
MaxwellMonitor = enum.auto()
|
||||||
|
|
||||||
|
@ -57,42 +60,42 @@ class SocketType(BlenderTypeEnum):
|
||||||
MaxwellSimDomain = enum.auto()
|
MaxwellSimDomain = enum.auto()
|
||||||
MaxwellSimGrid = enum.auto()
|
MaxwellSimGrid = enum.auto()
|
||||||
MaxwellSimGridAxis = enum.auto()
|
MaxwellSimGridAxis = enum.auto()
|
||||||
|
|
||||||
# Tidy3D
|
# Tidy3D
|
||||||
Tidy3DCloudTask = enum.auto()
|
Tidy3DCloudTask = enum.auto()
|
||||||
|
|
||||||
# Physical
|
# Physical
|
||||||
PhysicalUnitSystem = enum.auto()
|
PhysicalUnitSystem = enum.auto()
|
||||||
|
|
||||||
PhysicalTime = enum.auto()
|
PhysicalTime = enum.auto()
|
||||||
|
|
||||||
PhysicalAngle = enum.auto()
|
PhysicalAngle = enum.auto()
|
||||||
PhysicalSolidAngle = enum.auto()
|
PhysicalSolidAngle = enum.auto()
|
||||||
|
|
||||||
PhysicalRot2D = enum.auto()
|
PhysicalRot2D = enum.auto()
|
||||||
PhysicalRot3D = enum.auto()
|
PhysicalRot3D = enum.auto()
|
||||||
|
|
||||||
PhysicalFreq = enum.auto()
|
PhysicalFreq = enum.auto()
|
||||||
PhysicalAngFreq = enum.auto()
|
PhysicalAngFreq = enum.auto()
|
||||||
|
|
||||||
## Cartesian
|
## Cartesian
|
||||||
PhysicalLength = enum.auto()
|
PhysicalLength = enum.auto()
|
||||||
PhysicalArea = enum.auto()
|
PhysicalArea = enum.auto()
|
||||||
PhysicalVolume = enum.auto()
|
PhysicalVolume = enum.auto()
|
||||||
|
|
||||||
PhysicalDisp2D = enum.auto()
|
PhysicalDisp2D = enum.auto()
|
||||||
PhysicalDisp3D = enum.auto()
|
PhysicalDisp3D = enum.auto()
|
||||||
|
|
||||||
PhysicalPoint1D = enum.auto()
|
PhysicalPoint1D = enum.auto()
|
||||||
PhysicalPoint2D = enum.auto()
|
PhysicalPoint2D = enum.auto()
|
||||||
PhysicalPoint3D = enum.auto()
|
PhysicalPoint3D = enum.auto()
|
||||||
|
|
||||||
PhysicalSize2D = enum.auto()
|
PhysicalSize2D = enum.auto()
|
||||||
PhysicalSize3D = enum.auto()
|
PhysicalSize3D = enum.auto()
|
||||||
|
|
||||||
## Mechanical
|
## Mechanical
|
||||||
PhysicalMass = enum.auto()
|
PhysicalMass = enum.auto()
|
||||||
|
|
||||||
PhysicalSpeed = enum.auto()
|
PhysicalSpeed = enum.auto()
|
||||||
PhysicalVel2D = enum.auto()
|
PhysicalVel2D = enum.auto()
|
||||||
PhysicalVel3D = enum.auto()
|
PhysicalVel3D = enum.auto()
|
||||||
|
@ -103,37 +106,37 @@ class SocketType(BlenderTypeEnum):
|
||||||
PhysicalForce2D = enum.auto()
|
PhysicalForce2D = enum.auto()
|
||||||
PhysicalForce3D = enum.auto()
|
PhysicalForce3D = enum.auto()
|
||||||
PhysicalPressure = enum.auto()
|
PhysicalPressure = enum.auto()
|
||||||
|
|
||||||
## Energetic
|
## Energetic
|
||||||
PhysicalEnergy = enum.auto()
|
PhysicalEnergy = enum.auto()
|
||||||
PhysicalPower = enum.auto()
|
PhysicalPower = enum.auto()
|
||||||
PhysicalTemp = enum.auto()
|
PhysicalTemp = enum.auto()
|
||||||
|
|
||||||
## Electrodynamical
|
## Electrodynamical
|
||||||
PhysicalCurr = enum.auto()
|
PhysicalCurr = enum.auto()
|
||||||
PhysicalCurrDens2D = enum.auto()
|
PhysicalCurrDens2D = enum.auto()
|
||||||
PhysicalCurrDens3D = enum.auto()
|
PhysicalCurrDens3D = enum.auto()
|
||||||
|
|
||||||
PhysicalCharge = enum.auto()
|
PhysicalCharge = enum.auto()
|
||||||
PhysicalVoltage = enum.auto()
|
PhysicalVoltage = enum.auto()
|
||||||
PhysicalCapacitance = enum.auto()
|
PhysicalCapacitance = enum.auto()
|
||||||
PhysicalResistance = enum.auto()
|
PhysicalResistance = enum.auto()
|
||||||
PhysicalConductance = enum.auto()
|
PhysicalConductance = enum.auto()
|
||||||
|
|
||||||
PhysicalMagFlux = enum.auto()
|
PhysicalMagFlux = enum.auto()
|
||||||
PhysicalMagFluxDens = enum.auto()
|
PhysicalMagFluxDens = enum.auto()
|
||||||
PhysicalInductance = enum.auto()
|
PhysicalInductance = enum.auto()
|
||||||
|
|
||||||
PhysicalEField2D = enum.auto()
|
PhysicalEField2D = enum.auto()
|
||||||
PhysicalEField3D = enum.auto()
|
PhysicalEField3D = enum.auto()
|
||||||
PhysicalHField2D = enum.auto()
|
PhysicalHField2D = enum.auto()
|
||||||
PhysicalHField3D = enum.auto()
|
PhysicalHField3D = enum.auto()
|
||||||
|
|
||||||
## Luminal
|
## Luminal
|
||||||
PhysicalLumIntensity = enum.auto()
|
PhysicalLumIntensity = enum.auto()
|
||||||
PhysicalLumFlux = enum.auto()
|
PhysicalLumFlux = enum.auto()
|
||||||
PhysicalIlluminance = enum.auto()
|
PhysicalIlluminance = enum.auto()
|
||||||
|
|
||||||
## Optical
|
## Optical
|
||||||
PhysicalPolJones = enum.auto()
|
PhysicalPolJones = enum.auto()
|
||||||
PhysicalPol = enum.auto()
|
PhysicalPol = enum.auto()
|
||||||
|
|
|
@ -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,48 +10,49 @@ 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
|
||||||
_bl_image_name: str
|
_bl_image_name: str
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
## TODO: Check that blender doesn't have any other images by the same name.
|
## TODO: Check that blender doesn't have any other images by the same name.
|
||||||
self._bl_image_name = name
|
self._bl_image_name = name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self._bl_image_name
|
return self._bl_image_name
|
||||||
|
|
||||||
@name.setter
|
@name.setter
|
||||||
def name(self, value: str):
|
def name(self, value: str):
|
||||||
# Image Doesn't Exist
|
# Image Doesn't Exist
|
||||||
if not (bl_image := bpy.data.images.get(self._bl_image_name)):
|
if not (bl_image := bpy.data.images.get(self._bl_image_name)):
|
||||||
# ...AND Desired Image Name is Not Taken
|
# ...AND Desired Image Name is Not Taken
|
||||||
if not bpy.data.objects.get(value):
|
if not bpy.data.objects.get(value):
|
||||||
self._bl_image_name = value
|
self._bl_image_name = value
|
||||||
return
|
return
|
||||||
|
|
||||||
# ...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
|
||||||
bl_image.name = value
|
bl_image.name = value
|
||||||
self._bl_image_name = bl_image.name
|
self._bl_image_name = bl_image.name
|
||||||
## - When name exists, Blender adds .### to prevent overlap.
|
## - When name exists, Blender adds .### to prevent overlap.
|
||||||
## - `set_name` is allowed to change the name; nodes account for this.
|
## - `set_name` is allowed to change the name; nodes account for this.
|
||||||
|
|
||||||
def free(self):
|
def free(self):
|
||||||
if not (bl_image := bpy.data.images.get(self.name)):
|
if not (bl_image := bpy.data.images.get(self.name)):
|
||||||
msg = "Can't free BL image that doesn't exist"
|
msg = "Can't free BL image that doesn't exist"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
bpy.data.images.remove(bl_image)
|
bpy.data.images.remove(bl_image)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Managed Object Management
|
# - Managed Object Management
|
||||||
####################
|
####################
|
||||||
|
@ -59,27 +60,24 @@ 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))
|
bl_image.size[0] != width_px
|
||||||
and (
|
or bl_image.size[1] != height_px
|
||||||
bl_image.size[0] != width_px
|
or bl_image.channels != channels
|
||||||
or bl_image.size[1] != height_px
|
or bl_image.is_float ^ (dtype == 'float32')
|
||||||
or bl_image.channels != channels
|
|
||||||
or bl_image.is_float ^ (dtype == "float32")
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self.free()
|
self.free()
|
||||||
|
|
||||||
# Create Image w/Geometry (if none exists)
|
# Create Image w/Geometry (if none exists)
|
||||||
if not (bl_image := bpy.data.images.get(self.name)):
|
if not (bl_image := bpy.data.images.get(self.name)):
|
||||||
bl_image = bpy.data.images.new(
|
bl_image = bpy.data.images.new(
|
||||||
|
@ -87,9 +85,9 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
width=width_px,
|
width=width_px,
|
||||||
height=height_px,
|
height=height_px,
|
||||||
)
|
)
|
||||||
|
|
||||||
return bl_image
|
return bl_image
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Editor UX Manipulation
|
# - Editor UX Manipulation
|
||||||
####################
|
####################
|
||||||
|
@ -99,25 +97,23 @@ 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]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preview_space(self) -> bpy.types.SpaceProperties:
|
def preview_space(self) -> bpy.types.SpaceProperties:
|
||||||
"""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
|
||||||
if space.type == SPACE_TYPE
|
if space.type == SPACE_TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Actions
|
# - Actions
|
||||||
####################
|
####################
|
||||||
|
@ -125,9 +121,9 @@ 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Special Methods
|
# - Special Methods
|
||||||
####################
|
####################
|
||||||
|
@ -140,37 +136,37 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
bl_select: bool = False,
|
bl_select: bool = False,
|
||||||
):
|
):
|
||||||
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
|
||||||
|
|
||||||
# Retrieve Image Geometry from Area
|
# Retrieve Image Geometry from Area
|
||||||
width_px = preview_area.width
|
width_px = preview_area.width
|
||||||
height_px = preview_area.height
|
height_px = preview_area.height
|
||||||
|
|
||||||
# Compute Inches
|
# Compute Inches
|
||||||
_width_inches = width_px / _dpi
|
_width_inches = width_px / _dpi
|
||||||
_height_inches = height_px / _dpi
|
_height_inches = height_px / _dpi
|
||||||
|
|
||||||
elif width_inches and height_inches and dpi:
|
elif width_inches and height_inches and dpi:
|
||||||
# Copy Parameters
|
# Copy Parameters
|
||||||
_dpi = dpi
|
_dpi = dpi
|
||||||
_width_inches = height_inches
|
_width_inches = height_inches
|
||||||
_height_inches = height_inches
|
_height_inches = height_inches
|
||||||
|
|
||||||
# Compute Pixel Geometry
|
# Compute Pixel Geometry
|
||||||
width_px = int(_width_inches * _dpi)
|
width_px = int(_width_inches * _dpi)
|
||||||
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
|
||||||
aspect_ratio = _width_inches / _height_inches
|
aspect_ratio = _width_inches / _height_inches
|
||||||
|
|
||||||
# Create MPL Figure, Axes, and Compute Figure Geometry
|
# Create MPL Figure, Axes, and Compute Figure Geometry
|
||||||
fig, ax = plt.subplots(
|
fig, ax = plt.subplots(
|
||||||
figsize=[_width_inches, _height_inches],
|
figsize=[_width_inches, _height_inches],
|
||||||
|
@ -179,10 +175,10 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
ax.set_aspect(aspect_ratio)
|
ax.set_aspect(aspect_ratio)
|
||||||
cmp_width_px, cmp_height_px = fig.canvas.get_width_height()
|
cmp_width_px, cmp_height_px = fig.canvas.get_width_height()
|
||||||
## Use computed pixel w/h to preempt off-by-one size errors.
|
## Use computed pixel w/h to preempt off-by-one size errors.
|
||||||
|
|
||||||
# Plot w/User Parameter
|
# Plot w/User Parameter
|
||||||
func_plotter(ax)
|
func_plotter(ax)
|
||||||
|
|
||||||
# Save Figure to BytesIO
|
# Save Figure to BytesIO
|
||||||
with io.BytesIO() as buff:
|
with io.BytesIO() as buff:
|
||||||
fig.savefig(buff, format='raw', dpi=dpi)
|
fig.savefig(buff, format='raw', dpi=dpi)
|
||||||
|
@ -191,15 +187,14 @@ class ManagedBLImage(ct.schemas.ManagedObj):
|
||||||
buff.getvalue(),
|
buff.getvalue(),
|
||||||
dtype=np.uint8,
|
dtype=np.uint8,
|
||||||
).reshape([cmp_height_px, cmp_width_px, -1])
|
).reshape([cmp_height_px, cmp_width_px, -1])
|
||||||
|
|
||||||
image_data = np.flipud(image_data).astype(np.float32) / 255
|
image_data = np.flipud(image_data).astype(np.float32) / 255
|
||||||
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
|
||||||
|
@ -27,113 +28,133 @@ def bl_collection(
|
||||||
# Init the "Managed Collection"
|
# Init the "Managed Collection"
|
||||||
# Ensure Collection exists (and is in the Scene collection)
|
# Ensure Collection exists (and is in the Scene collection)
|
||||||
if collection_name not in bpy.data.collections:
|
if collection_name not in bpy.data.collections:
|
||||||
collection = bpy.data.collections.new(collection_name)
|
collection = bpy.data.collections.new(collection_name)
|
||||||
bpy.context.scene.collection.children.link(collection)
|
bpy.context.scene.collection.children.link(collection)
|
||||||
else:
|
else:
|
||||||
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 (
|
||||||
collection_name
|
layer_collection := bpy.context.view_layer.layer_collection.children[
|
||||||
]).exclude != view_layer_exclude:
|
collection_name
|
||||||
|
]
|
||||||
|
).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
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
self._bl_object_name = name
|
self._bl_object_name = name
|
||||||
|
|
||||||
# Object Name
|
# Object Name
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self._bl_object_name
|
return self._bl_object_name
|
||||||
|
|
||||||
@name.setter
|
@name.setter
|
||||||
def set_name(self, value: str) -> None:
|
def set_name(self, value: str) -> None:
|
||||||
# Object Doesn't Exist
|
# Object Doesn't Exist
|
||||||
if not (bl_object := bpy.data.objects.get(self._bl_object_name)):
|
if not (bl_object := bpy.data.objects.get(self._bl_object_name)):
|
||||||
# ...AND Desired Object Name is Not Taken
|
# ...AND Desired Object Name is Not Taken
|
||||||
if not bpy.data.objects.get(value):
|
if not bpy.data.objects.get(value):
|
||||||
self._bl_object_name = value
|
self._bl_object_name = value
|
||||||
return
|
return
|
||||||
|
|
||||||
# ...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
|
||||||
bl_object.name = value
|
bl_object.name = value
|
||||||
self._bl_object_name = bl_object.name
|
self._bl_object_name = bl_object.name
|
||||||
## - When name exists, Blender adds .### to prevent overlap.
|
## - When name exists, Blender adds .### to prevent overlap.
|
||||||
## - `set_name` is allowed to change the name; nodes account for this.
|
## - `set_name` is allowed to change the name; nodes account for this.
|
||||||
|
|
||||||
# Object Datablock Name
|
# Object Datablock Name
|
||||||
@property
|
@property
|
||||||
def bl_mesh_name(self):
|
def bl_mesh_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bl_volume_name(self):
|
def bl_volume_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
# Deallocation
|
# Deallocation
|
||||||
def free(self):
|
def free(self):
|
||||||
if not (bl_object := bpy.data.objects.get(self.name)):
|
if not (bl_object := bpy.data.objects.get(self.name)):
|
||||||
return ## Nothing to do
|
return ## Nothing to do
|
||||||
|
|
||||||
# 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)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Actions
|
# - Actions
|
||||||
####################
|
####################
|
||||||
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 (
|
||||||
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
bl_object.name
|
||||||
)).objects:
|
not in (
|
||||||
|
preview_collection := bl_collection(
|
||||||
|
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
||||||
|
)
|
||||||
|
).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 (
|
||||||
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
bl_object.name
|
||||||
)).objects:
|
not in (
|
||||||
|
preview_collection := bl_collection(
|
||||||
|
PREVIEW_COLLECTION_NAME, view_layer_exclude=False
|
||||||
|
)
|
||||||
|
).objects
|
||||||
|
):
|
||||||
preview_collection.objects.unlink(bl_object)
|
preview_collection.objects.unlink(bl_object)
|
||||||
|
|
||||||
def bl_select(self) -> None:
|
def bl_select(self) -> None:
|
||||||
|
@ -141,68 +162,68 @@ 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')
|
||||||
bl_object.select_set(True)
|
bl_object.select_set(True)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Managed Object Management
|
# - Managed Object Management
|
||||||
####################
|
####################
|
||||||
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.
|
||||||
|
|
||||||
If the requested object data type is different, then delete the old
|
If the requested object data type is different, then delete the old
|
||||||
object and recreate.
|
object and recreate.
|
||||||
"""
|
"""
|
||||||
# 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)
|
||||||
bl_collection(
|
bl_collection(
|
||||||
MANAGED_COLLECTION_NAME, view_layer_exclude=True
|
MANAGED_COLLECTION_NAME, view_layer_exclude=True
|
||||||
).objects.link(bl_object)
|
).objects.link(bl_object)
|
||||||
|
|
||||||
return bl_object
|
return bl_object
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Mesh Data Properties
|
# - Mesh Data Properties
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def raw_mesh(self) -> bpy.types.Mesh:
|
def raw_mesh(self) -> bpy.types.Mesh:
|
||||||
"""Returns the object's raw mesh data.
|
"""Returns the object's raw mesh data.
|
||||||
|
|
||||||
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
|
||||||
def mesh_as_bmesh(
|
def mesh_as_bmesh(
|
||||||
self,
|
self,
|
||||||
|
@ -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()
|
||||||
|
@ -223,52 +243,53 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
bmesh_mesh.from_object(bl_object)
|
bmesh_mesh.from_object(bl_object)
|
||||||
|
|
||||||
if triangulate:
|
if triangulate:
|
||||||
bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces)
|
bmesh.ops.triangulate(bmesh_mesh, faces=bmesh_mesh.faces)
|
||||||
|
|
||||||
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
|
||||||
def mesh_as_arrays(self) -> dict:
|
def mesh_as_arrays(self) -> dict:
|
||||||
## TODO: Cached
|
## TODO: Cached
|
||||||
|
|
||||||
# Ensure Updated Geometry
|
# Ensure Updated Geometry
|
||||||
bpy.context.view_layer.update()
|
bpy.context.view_layer.update()
|
||||||
## 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)
|
||||||
|
|
||||||
# Optimized Vertex Copy
|
# Optimized Vertex Copy
|
||||||
## See <https://blog.michelanders.nl/2016/02/copying-vertices-to-numpy-arrays-in_4.html>
|
## See <https://blog.michelanders.nl/2016/02/copying-vertices-to-numpy-arrays-in_4.html>
|
||||||
verts = np.zeros(3 * len(_mesh.vertices), dtype=np.float64)
|
verts = np.zeros(3 * len(_mesh.vertices), dtype=np.float64)
|
||||||
_mesh.vertices.foreach_get('co', verts)
|
_mesh.vertices.foreach_get('co', verts)
|
||||||
verts.shape = (-1, 3)
|
verts.shape = (-1, 3)
|
||||||
|
|
||||||
# Optimized Triangle Copy
|
# Optimized Triangle Copy
|
||||||
## To understand, read it, **carefully**.
|
## To understand, read it, **carefully**.
|
||||||
faces = np.zeros(3 * len(_mesh.polygons), dtype=np.uint64)
|
faces = np.zeros(3 * len(_mesh.polygons), dtype=np.uint64)
|
||||||
_mesh.polygons.foreach_get('vertices', faces)
|
_mesh.polygons.foreach_get('vertices', faces)
|
||||||
faces.shape = (-1, 3)
|
faces.shape = (-1, 3)
|
||||||
|
|
||||||
# Remove Temporary Mesh
|
# Remove Temporary Mesh
|
||||||
bpy.data.meshes.remove(_mesh)
|
bpy.data.meshes.remove(_mesh)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"verts": verts,
|
'verts': verts,
|
||||||
"faces": faces,
|
'faces': faces,
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Modifier Methods
|
# - Modifier Methods
|
||||||
####################
|
####################
|
||||||
|
@ -277,13 +298,13 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
modifier_type: ModifierType,
|
modifier_type: ModifierType,
|
||||||
):
|
):
|
||||||
"""Creates a new modifier for the current `bl_object`.
|
"""Creates a new modifier for the current `bl_object`.
|
||||||
|
|
||||||
For all Blender modifier type names, see: <https://docs.blender.org/api/current/bpy_types_enum_items/object_modifier_type_items.html#rna-enum-object-modifier-type-items>
|
For all Blender modifier type names, see: <https://docs.blender.org/api/current/bpy_types_enum_items/object_modifier_type_items.html#rna-enum-object-modifier-type-items>
|
||||||
"""
|
"""
|
||||||
if not (bl_object := bpy.data.objects.get(self.name)):
|
if not (bl_object := bpy.data.objects.get(self.name)):
|
||||||
msg = "Can't add modifier to BL object that doesn't exist"
|
msg = "Can't add modifier to BL object that doesn't exist"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
# (Create and) Return Modifier
|
# (Create and) Return Modifier
|
||||||
bl_modifier_name = MODIFIER_NAMES[modifier_type]
|
bl_modifier_name = MODIFIER_NAMES[modifier_type]
|
||||||
if bl_modifier_name not in bl_object.modifiers:
|
if bl_modifier_name not in bl_object.modifiers:
|
||||||
|
@ -292,33 +313,33 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
type=modifier_type,
|
type=modifier_type,
|
||||||
)
|
)
|
||||||
return bl_object.modifiers[bl_modifier_name]
|
return bl_object.modifiers[bl_modifier_name]
|
||||||
|
|
||||||
def modifier_attrs(self, modifier_type: ModifierType) -> dict:
|
def modifier_attrs(self, modifier_type: ModifierType) -> dict:
|
||||||
"""Based on the modifier type, retrieve a representative dictionary of modifier attributes.
|
"""Based on the modifier type, retrieve a representative dictionary of modifier attributes.
|
||||||
The attributes can then easily be set using `setattr`.
|
The attributes can then easily be set using `setattr`.
|
||||||
"""
|
"""
|
||||||
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(
|
||||||
self,
|
self,
|
||||||
modifier_type: ModifierType,
|
modifier_type: ModifierType,
|
||||||
modifier_attrs: dict,
|
modifier_attrs: dict,
|
||||||
):
|
):
|
||||||
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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - GeoNodes Modifier
|
# - GeoNodes Modifier
|
||||||
####################
|
####################
|
||||||
|
@ -328,65 +349,64 @@ class ManagedBLObject(ct.schemas.ManagedObj):
|
||||||
geonodes_identifier_to_value: dict,
|
geonodes_identifier_to_value: dict,
|
||||||
):
|
):
|
||||||
"""Push the given GeoNodes Interface values to a GeoNodes modifier attached to a managed MESH object.
|
"""Push the given GeoNodes Interface values to a GeoNodes modifier attached to a managed MESH object.
|
||||||
|
|
||||||
The values must be compatible with the `default_value`s of the interface sockets.
|
The values must be compatible with the `default_value`s of the interface sockets.
|
||||||
|
|
||||||
If there is no object, it is created.
|
If there is no object, it is created.
|
||||||
If the object isn't a MESH object, it is made so.
|
If the object isn't a MESH object, it is made so.
|
||||||
If the GeoNodes modifier doesn't exist, it is created.
|
If the GeoNodes modifier doesn't exist, it is created.
|
||||||
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
|
||||||
if isinstance(
|
if isinstance(
|
||||||
bl_modifier[interface_identifier],
|
bl_modifier[interface_identifier],
|
||||||
float,
|
float,
|
||||||
) and isinstance(value, int):
|
) and isinstance(value, int):
|
||||||
value = float(value)
|
value = float(value)
|
||||||
|
|
||||||
bl_modifier[interface_identifier] = value
|
bl_modifier[interface_identifier] = value
|
||||||
|
|
||||||
modifier_altered = True
|
modifier_altered = True
|
||||||
|
|
||||||
# Update DepGraph (if anything changed)
|
# Update DepGraph (if anything changed)
|
||||||
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.
|
|
||||||
# """
|
|
||||||
# if (
|
|
||||||
# (bl_object := bpy.data.objects.get(self.bl_object_name))
|
|
||||||
# and bl_object.type == "VOLUME"
|
|
||||||
# ):
|
|
||||||
# return bl_object.data
|
|
||||||
#
|
#
|
||||||
# msg = f"Requested VOLUME data from `bl_object` of type {bl_object.type}"
|
# Raises an error if the object has no volume data.
|
||||||
# raise ValueError(msg)
|
# """
|
||||||
|
# if (
|
||||||
|
# (bl_object := bpy.data.objects.get(self.bl_object_name))
|
||||||
|
# and bl_object.type == "VOLUME"
|
||||||
|
# ):
|
||||||
|
# return bl_object.data
|
||||||
|
#
|
||||||
|
# msg = f"Requested VOLUME data from `bl_object` of type {bl_object.type}"
|
||||||
|
# raise ValueError(msg)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,41 +6,41 @@ 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(
|
||||||
plus=x_pos,
|
plus=x_pos,
|
||||||
|
@ -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,39 +4,36 @@ 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,36 +7,33 @@ 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,61 +5,61 @@ 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
|
||||||
}
|
}
|
||||||
output_sockets = {}
|
output_sockets = {}
|
||||||
output_socket_sets = input_socket_sets
|
output_socket_sets = input_socket_sets
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,89 +8,86 @@ 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,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,
|
||||||
|
@ -98,15 +95,15 @@ 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,43 +111,42 @@ 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:
|
||||||
msg = f"Active socket set invalid for wave constant: {props['active_socket_set']}"
|
msg = f"Active socket set invalid for wave constant: {props['active_socket_set']}"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
@base.on_init()
|
@base.on_init()
|
||||||
def on_init(self):
|
def on_init(self):
|
||||||
self.on_value_changed__active_socket_set()
|
self.on_value_changed__active_socket_set()
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
|
@ -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,109 +17,108 @@ 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))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
sim_data = td_web.api.webapi.load(
|
sim_data = td_web.api.webapi.load(
|
||||||
cloud_task.task_id,
|
cloud_task.task_id,
|
||||||
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,
|
||||||
path=str(path_tmp),
|
path=str(path_tmp),
|
||||||
) ## TODO: Don't use td_web directly. Only through tdcloud
|
) ## TODO: Don't use td_web directly. Only through tdcloud
|
||||||
Path(path_tmp).unlink()
|
Path(path_tmp).unlink()
|
||||||
|
|
||||||
return sim
|
return sim
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
|
|
||||||
self.loose_output_sockets = {}
|
self.loose_output_sockets = {}
|
||||||
|
|
||||||
@base.on_init()
|
@base.on_init()
|
||||||
def on_init(self):
|
def on_init(self):
|
||||||
self.on_value_changed__cloud_task()
|
self.on_value_changed__cloud_task()
|
||||||
|
|
|
@ -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(
|
||||||
for i in [1, 2, 3]
|
label=f'Δεr_{i}',
|
||||||
} | {
|
)
|
||||||
f"f{i}": sockets.PhysicalFreqSocketDef(
|
for i in [1, 2, 3]
|
||||||
label=f"f_{i}",
|
}
|
||||||
)
|
| {
|
||||||
for i in [1, 2, 3]
|
f'f{i}': sockets.PhysicalFreqSocketDef(
|
||||||
} | {
|
label=f'f_{i}',
|
||||||
f"delta{i}": sockets.PhysicalFreqSocketDef(
|
)
|
||||||
label=f"δ_{i}",
|
for i in [1, 2, 3]
|
||||||
)
|
}
|
||||||
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.convert_to(
|
/ spu.hertz,
|
||||||
self.compute_input(f"delta{i}"),
|
spu.convert_to(
|
||||||
spu.hertz,
|
self.compute_input(f'delta{i}'),
|
||||||
) / spu.hertz,
|
spu.hertz,
|
||||||
)
|
)
|
||||||
for i in [1, 2, 3]
|
/ spu.hertz,
|
||||||
]
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -3,4 +3,3 @@
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = []
|
||||||
BL_NODES = {}
|
BL_NODES = {}
|
||||||
|
|
||||||
|
|
|
@ -14,55 +14,55 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
[
|
||||||
for ref in td.material_library[mat_key].variants[
|
ref.journal
|
||||||
td.material_library[mat_key].default
|
for ref in td.material_library[mat_key]
|
||||||
].reference
|
.variants[td.material_library[mat_key].default]
|
||||||
])
|
.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
|
||||||
def freq_range_str(self) -> tuple[sp.Expr, sp.Expr]:
|
def freq_range_str(self) -> tuple[sp.Expr, sp.Expr]:
|
||||||
## TODO: Cache (node instances don't seem able to keep data outside of properties, not even cached_property)
|
## TODO: Cache (node instances don't seem able to keep data outside of properties, not even cached_property)
|
||||||
|
@ -71,14 +71,14 @@ 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
|
||||||
def nm_range_str(self) -> str:
|
def nm_range_str(self) -> str:
|
||||||
## TODO: Cache (node instances don't seem able to keep data outside of properties, not even cached_property)
|
## TODO: Cache (node instances don't seem able to keep data outside of properties, not even cached_property)
|
||||||
|
@ -87,47 +87,47 @@ 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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 = [
|
|
||||||
(
|
|
||||||
self.compute_input(f"B{i}"),
|
|
||||||
spu.convert_to(
|
|
||||||
self.compute_input(f"C{i}"),
|
|
||||||
spu.um**2,
|
|
||||||
) / spu.um**2
|
|
||||||
)
|
|
||||||
for i in [1, 2, 3]
|
|
||||||
])
|
|
||||||
|
|
||||||
|
return td.Sellmeier(
|
||||||
|
coeffs=[
|
||||||
|
(
|
||||||
|
self.compute_input(f'B{i}'),
|
||||||
|
spu.convert_to(
|
||||||
|
self.compute_input(f'C{i}'),
|
||||||
|
spu.um**2,
|
||||||
|
)
|
||||||
|
/ spu.um**2,
|
||||||
|
)
|
||||||
|
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,90 +15,98 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw_info(self, context, col):
|
def draw_info(self, context, col):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,91 +114,86 @@ 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
|
||||||
|
|
||||||
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,
|
||||||
interval_space=samples_space,
|
interval_space=samples_space,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
float(el)
|
)
|
||||||
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,93 +15,102 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw_info(self, context, col):
|
def draw_info(self, context, col):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,84 +119,85 @@ 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
|
||||||
|
|
||||||
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,
|
||||||
interval_space=samples_space,
|
interval_space=samples_space,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
float(el)
|
)
|
||||||
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,28 +28,29 @@ 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(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI Layout
|
# - UI Layout
|
||||||
####################
|
####################
|
||||||
|
@ -57,37 +59,39 @@ 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()
|
||||||
elif isinstance(data, pyd.BaseModel):
|
elif isinstance(data, pyd.BaseModel):
|
||||||
return data.model_dump_json()
|
return data.model_dump_json()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
json.dumps(data)
|
json.dumps(data)
|
||||||
|
|
||||||
|
|
|
@ -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 (
|
||||||
context.node.tracked_task_id
|
task_info := tdcloud.TidyCloudTasks.task_info(
|
||||||
)) is not None
|
context.node.tracked_task_id
|
||||||
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
|
||||||
)
|
)
|
||||||
|
@ -90,22 +93,22 @@ class ReloadTrackedTask(bpy.types.Operator):
|
||||||
) is None:
|
) is None:
|
||||||
msg = "Tried to reload tracked task, but it doesn't exist"
|
msg = "Tried to reload tracked task, but it doesn't exist"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
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,142 +116,145 @@ 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,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Sync Methods
|
# - Sync Methods
|
||||||
####################
|
####################
|
||||||
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
|
||||||
if self.tracked_task_id:
|
if self.tracked_task_id:
|
||||||
cloud_task = tdcloud.TidyCloudTasks.task(self.tracked_task_id)
|
cloud_task = tdcloud.TidyCloudTasks.task(self.tracked_task_id)
|
||||||
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
|
||||||
cloud_task = tdcloud.TidyCloudTasks.mk_task(
|
cloud_task = tdcloud.TidyCloudTasks.mk_task(
|
||||||
task_name=new_task[0],
|
task_name=new_task[0],
|
||||||
|
@ -257,25 +263,27 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
upload_progress_cb=lambda uploaded_bytes: None, ## TODO: Use!
|
upload_progress_cb=lambda uploaded_bytes: None, ## TODO: Use!
|
||||||
verbose=True,
|
verbose=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
def run_tracked_task(self):
|
def run_tracked_task(self):
|
||||||
if (
|
if (
|
||||||
cloud_task := tdcloud.TidyCloudTasks.task(self.tracked_task_id)
|
cloud_task := tdcloud.TidyCloudTasks.task(self.tracked_task_id)
|
||||||
) is None:
|
) is None:
|
||||||
msg = "Tried to run tracked task, but it doesn't exist"
|
msg = "Tried to run tracked task, but it doesn't exist"
|
||||||
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,146 +292,156 @@ 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
|
||||||
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="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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,93 +38,96 @@ 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
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_operators(self, context, layout):
|
def draw_operators(self, context, layout):
|
||||||
split = layout.split(factor=0.4)
|
split = layout.split(factor=0.4)
|
||||||
|
|
||||||
# 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):
|
||||||
sp.pprint(data, use_unicode=True)
|
sp.pprint(data, use_unicode=True)
|
||||||
|
|
||||||
print(str(data))
|
print(str(data))
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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(
|
||||||
managed_bl_object.PREVIEW_COLLECTION_NAME,
|
managed_bl_object.PREVIEW_COLLECTION_NAME,
|
||||||
|
@ -131,14 +135,14 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
for bl_object in preview_collection.objects.values():
|
for bl_object in preview_collection.objects.values():
|
||||||
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
|
||||||
|
@ -148,10 +152,10 @@ class ViewerNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
for bl_object in preview_collection.objects.values():
|
for bl_object in preview_collection.objects.values():
|
||||||
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,54 +6,53 @@ 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(
|
||||||
**sim_domain, ## run_time=, size=, grid=, medium=
|
**sim_domain, ## run_time=, size=, grid=, medium=
|
||||||
structures=structures,
|
structures=structures,
|
||||||
|
@ -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,48 +9,51 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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)
|
||||||
|
@ -61,72 +64,67 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
grid_spec=grid,
|
grid_spec=grid,
|
||||||
medium=medium,
|
medium=medium,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
float(el)
|
)
|
||||||
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,88 +13,89 @@ 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,
|
||||||
) -> tuple[str, str, sp.Expr, sp.Expr]:
|
) -> tuple[str, str, sp.Expr, sp.Expr]:
|
||||||
"""Converts a vector (maybe normalized) to spherical coordinates from an arbitrary choice of injection axis.
|
"""Converts a vector (maybe normalized) to spherical coordinates from an arbitrary choice of injection axis.
|
||||||
|
|
||||||
Injection axis is chosen to minimize `theta`
|
Injection axis is chosen to minimize `theta`
|
||||||
"""
|
"""
|
||||||
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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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)
|
||||||
|
|
||||||
# Display the results
|
# Display the results
|
||||||
return td.PlaneWave(
|
return td.PlaneWave(
|
||||||
center=center,
|
center=center,
|
||||||
|
@ -105,74 +106,65 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
angle_phi=phi,
|
angle_phi=phi,
|
||||||
pol_angle=pol_angle,
|
pol_angle=pol_angle,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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([float(el) for el in _direction])
|
||||||
direction = tuple([
|
|
||||||
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,79 +10,82 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_props(self, context, layout):
|
def draw_props(self, context, layout):
|
||||||
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)
|
||||||
|
|
||||||
_res = td.PointDipole(
|
_res = td.PointDipole(
|
||||||
center=center,
|
center=center,
|
||||||
source_time=temporal_shape,
|
source_time=temporal_shape,
|
||||||
|
@ -90,41 +93,42 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
|
||||||
polarization=pol_axis,
|
polarization=pol_axis,
|
||||||
)
|
)
|
||||||
return _res
|
return _res
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,54 +6,55 @@ 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
|
||||||
freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz
|
freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz
|
||||||
freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz
|
freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz
|
||||||
|
|
||||||
return td.ContinuousWave(
|
return td.ContinuousWave(
|
||||||
amplitude=cheating_amplitude,
|
amplitude=cheating_amplitude,
|
||||||
phase=phase,
|
phase=phase,
|
||||||
|
@ -63,7 +64,6 @@ class ContinuousWaveTemporalShapeNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -13,98 +13,107 @@ 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_',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz
|
freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz
|
||||||
phase = spu.convert_to(_phase, spu.radian) / spu.radian
|
phase = spu.convert_to(_phase, spu.radian) / spu.radian
|
||||||
|
|
||||||
return td.GaussianPulse(
|
return td.GaussianPulse(
|
||||||
amplitude=cheating_amplitude,
|
amplitude=cheating_amplitude,
|
||||||
phase=phase,
|
phase=phase,
|
||||||
|
@ -113,11 +122,11 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimNode):
|
||||||
offset=time_delay_rel_ang_freq,
|
offset=time_delay_rel_ang_freq,
|
||||||
remove_dc_component=remove_dc_component,
|
remove_dc_component=remove_dc_component,
|
||||||
)
|
)
|
||||||
|
|
||||||
@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,36 +16,37 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,28 +54,27 @@ 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
|
||||||
|
|
||||||
# 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,
|
||||||
|
@ -82,20 +82,20 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
input_sockets: dict[str, typ.Any],
|
input_sockets: dict[str, typ.Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called whenever the GeoNodes socket is changed.
|
"""Called whenever the GeoNodes socket is changed.
|
||||||
|
|
||||||
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
|
||||||
## Retrieve the appropriate SocketDef for the Blender Interface Socket
|
## Retrieve the appropriate SocketDef for the Blender Interface Socket
|
||||||
self.loose_input_sockets = {
|
self.loose_input_sockets = {
|
||||||
|
@ -104,21 +104,20 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
)() ## === <SocketType>SocketDef(), but with dynamic SocketDef
|
)() ## === <SocketType>SocketDef(), but with dynamic SocketDef
|
||||||
for socket_name, bl_interface_socket in geonodes_interface.items()
|
for socket_name, bl_interface_socket in geonodes_interface.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
## Set Loose `socket.value` from Interface `default_value`
|
## Set Loose `socket.value` from Interface `default_value`
|
||||||
for socket_name in self.loose_input_sockets:
|
for socket_name in self.loose_input_sockets:
|
||||||
socket = self.inputs[socket_name]
|
socket = self.inputs[socket_name]
|
||||||
bl_interface_socket = geonodes_interface[socket_name]
|
bl_interface_socket = geonodes_interface[socket_name]
|
||||||
|
|
||||||
socket.value = bl_socket_map.value_from_bl(bl_interface_socket)
|
socket.value = bl_socket_map.value_from_bl(bl_interface_socket)
|
||||||
|
|
||||||
## Implicitly triggers the loose-input `on_value_changed` for each.
|
## Implicitly triggers the loose-input `on_value_changed` for each.
|
||||||
|
|
||||||
@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,
|
||||||
|
@ -127,26 +126,27 @@ class GeoNodesStructureNode(base.MaxwellSimNode):
|
||||||
loose_input_sockets: dict[str, typ.Any],
|
loose_input_sockets: dict[str, typ.Any],
|
||||||
):
|
):
|
||||||
"""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.
|
||||||
"""
|
"""
|
||||||
# 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
|
||||||
## - If the user deletes an interface socket, bad things will happen.
|
## - If the user deletes an interface socket, bad things will happen.
|
||||||
## - We will try to set an identifier that doesn't exist!
|
## - We will try to set an identifier that doesn't exist!
|
||||||
## - Instead, this should update the loose input sockets.
|
## - Instead, this should update the loose input sockets.
|
||||||
|
|
||||||
## Push Values to the GeoNodes Modifier
|
## Push Values to the GeoNodes Modifier
|
||||||
mobj.sync_geonodes_modifier(
|
mobj.sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
|
@ -159,24 +159,24 @@ 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,
|
||||||
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.
|
||||||
"""
|
"""
|
||||||
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,39 +10,40 @@ 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()
|
||||||
|
|
||||||
# Triangulate Object Mesh
|
# Triangulate Object Mesh
|
||||||
bmesh_mesh = bmesh.new()
|
bmesh_mesh = bmesh.new()
|
||||||
bmesh_mesh.from_object(
|
bmesh_mesh.from_object(
|
||||||
|
@ -50,26 +51,24 @@ class ObjectStructureNode(base.MaxwellSimTreeNode):
|
||||||
bpy.context.evaluated_depsgraph_get(),
|
bpy.context.evaluated_depsgraph_get(),
|
||||||
)
|
)
|
||||||
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
|
|
||||||
bpy.data.meshes.remove(mesh)
|
|
||||||
|
|
||||||
return td.Structure(
|
|
||||||
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
|
||||||
medium=self.compute_input("medium")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Remove Temporary Mesh
|
||||||
|
bpy.data.meshes.remove(mesh)
|
||||||
|
|
||||||
|
return td.Structure(
|
||||||
|
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
||||||
|
medium=self.compute_input('medium'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -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,48 +10,49 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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)
|
||||||
|
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.Box(
|
geometry=td.Box(
|
||||||
center=center,
|
center=center,
|
||||||
|
@ -59,69 +60,66 @@ class BoxStructureNode(base.MaxwellSimNode):
|
||||||
),
|
),
|
||||||
medium=medium,
|
medium=medium,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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) for el in spu.convert_to(_size, spu.um) / spu.um]
|
||||||
float(el)
|
)
|
||||||
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,48 +6,49 @@ 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
|
||||||
height = spu.convert_to(_height, spu.um) / spu.um
|
height = spu.convert_to(_height, spu.um) / spu.um
|
||||||
|
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.Cylinder(
|
geometry=td.Cylinder(
|
||||||
radius=radius,
|
radius=radius,
|
||||||
|
@ -58,7 +59,6 @@ class CylinderStructureNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -10,48 +10,49 @@ 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='',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
|
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.Sphere(
|
geometry=td.Sphere(
|
||||||
radius=radius,
|
radius=radius,
|
||||||
|
@ -59,66 +60,64 @@ class SphereStructureNode(base.MaxwellSimNode):
|
||||||
),
|
),
|
||||||
medium=medium,
|
medium=medium,
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,68 +7,72 @@ 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',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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,
|
||||||
spu.meter,
|
spu.meter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -16,177 +16,197 @@ 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= {
|
output_sockets = {'Preview': sockets.AnySocketDef()}
|
||||||
"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='',
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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 [
|
||||||
(
|
(
|
||||||
monitor_name,
|
monitor_name,
|
||||||
|
@ -195,48 +215,47 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
)
|
)
|
||||||
for monitor_name in monitor_names
|
for monitor_name in monitor_names
|
||||||
]
|
]
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
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,
|
||||||
|
@ -244,30 +263,36 @@ class FDTDSimDataVizNode(base.MaxwellSimNode):
|
||||||
input_sockets: dict[str, typ.Any],
|
input_sockets: dict[str, typ.Any],
|
||||||
) -> 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,47 +301,47 @@ 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(
|
|
||||||
# managed_objs={"viz_object"},
|
# @base.on_show_preview(
|
||||||
#)
|
# managed_objs={"viz_object"},
|
||||||
#def on_show_preview(
|
# )
|
||||||
# self,
|
# def on_show_preview(
|
||||||
# managed_objs: dict[str, ct.schemas.ManagedObj],
|
# self,
|
||||||
#):
|
# 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.
|
||||||
# managed_objs["viz_object"].show_preview("MESH")
|
# """
|
||||||
|
# managed_objs["viz_object"].show_preview("MESH")
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -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,15 +9,20 @@ 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
|
||||||
bl_label: str
|
bl_label: str
|
||||||
|
|
||||||
# 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.
|
||||||
|
@ -25,266 +30,288 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
## - DIAMOND: Pointer Value.
|
## - DIAMOND: Pointer Value.
|
||||||
## - +DOT: Uses Units
|
## - +DOT: Uses Units
|
||||||
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
|
||||||
|
|
||||||
# Computed
|
# Computed
|
||||||
bl_idname: str
|
bl_idname: str
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Initialization
|
# - Initialization
|
||||||
####################
|
####################
|
||||||
def __init_subclass__(cls, **kwargs: typ.Any):
|
def __init_subclass__(cls, **kwargs: typ.Any):
|
||||||
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,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup Style
|
# Setup Style
|
||||||
cls.socket_color = ct.SOCKET_COLORS[cls.socket_type]
|
cls.socket_color = ct.SOCKET_COLORS[cls.socket_type]
|
||||||
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'],
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Action Chain
|
# - Action Chain
|
||||||
####################
|
####################
|
||||||
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.
|
||||||
|
|
||||||
This also invalidates any of the socket's caches.
|
This also invalidates any of the socket's caches.
|
||||||
|
|
||||||
When called on an input node, the containing node's
|
When called on an input node, the containing node's
|
||||||
`trigger_action` method will be called with this socket.
|
`trigger_action` method will be called with this socket.
|
||||||
|
|
||||||
When called on a linked output node, the linked socket's
|
When called on a linked output node, the linked socket's
|
||||||
`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)
|
||||||
|
|
||||||
## Linked Output Socket
|
## Linked Output Socket
|
||||||
elif self.is_output and self.is_linked:
|
elif self.is_output and self.is_linked:
|
||||||
for link in self.links:
|
for link in self.links:
|
||||||
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
|
||||||
if self.is_output:
|
if self.is_output:
|
||||||
self.node.trigger_action(action, socket_name=self.name)
|
self.node.trigger_action(action, socket_name=self.name)
|
||||||
|
|
||||||
## Linked Input Socket
|
## Linked Input Socket
|
||||||
elif not self.is_output and self.is_linked:
|
elif not self.is_output and self.is_linked:
|
||||||
for link in self.links:
|
for link in self.links:
|
||||||
link.from_socket.trigger_action(action)
|
link.from_socket.trigger_action(action)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
|
|
||||||
def sync_link_removed(self, from_socket) -> bool:
|
def sync_link_removed(self, from_socket) -> bool:
|
||||||
"""Called when a link has been removed from this (input) socket.
|
"""Called when a link has been removed from 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Data Chain
|
# - Data Chain
|
||||||
####################
|
####################
|
||||||
@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
|
||||||
|
|
||||||
@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 (
|
||||||
self.value,
|
spu.convert_to(
|
||||||
unit_system_unit,
|
self.value,
|
||||||
) / 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
|
||||||
|
|
||||||
@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
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def capabilities(self) -> None:
|
def capabilities(self) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _compute_data(
|
def _compute_data(
|
||||||
self,
|
self,
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
) -> typ.Any:
|
) -> typ.Any:
|
||||||
"""Computes the internal data of this socket, ONLY.
|
"""Computes the internal data of this socket, ONLY.
|
||||||
|
|
||||||
**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
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def compute_data(
|
def compute_data(
|
||||||
self,
|
self,
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
):
|
):
|
||||||
"""Computes the value of this socket, including all relevant factors:
|
"""Computes the value of this socket, including all relevant factors:
|
||||||
- If input socket, and unlinked, compute internal data.
|
- If input socket, and unlinked, compute internal data.
|
||||||
- If input socket, and linked, compute linked socket data.
|
- If input socket, and linked, compute linked socket data.
|
||||||
- If output socket, ask node for data.
|
- If output socket, ask node for data.
|
||||||
"""
|
"""
|
||||||
# Compute Output Socket
|
# Compute Output Socket
|
||||||
## 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Unit Properties
|
# - Unit Properties
|
||||||
####################
|
####################
|
||||||
|
@ -293,26 +320,24 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
if not self.use_units:
|
if not self.use_units:
|
||||||
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:
|
||||||
return self.possible_units[self.active_unit]
|
return self.possible_units[self.active_unit]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def prev_unit(self) -> sp.Expr:
|
def prev_unit(self) -> sp.Expr:
|
||||||
return self.possible_units[self.prev_active_unit]
|
return self.possible_units[self.prev_active_unit]
|
||||||
|
|
||||||
@unit.setter
|
@unit.setter
|
||||||
def unit(self, value: str | sp.Expr) -> None:
|
def unit(self, value: str | sp.Expr) -> None:
|
||||||
# Retrieve Unit by String
|
# Retrieve Unit by String
|
||||||
if isinstance(value, str) and value in self.possible_units:
|
if isinstance(value, str) and value in self.possible_units:
|
||||||
self.active_unit = self.possible_units[value]
|
self.active_unit = self.possible_units[value]
|
||||||
return
|
return
|
||||||
|
|
||||||
# Retrieve =1 Matching Unit Name
|
# Retrieve =1 Matching Unit Name
|
||||||
matching_unit_names = [
|
matching_unit_names = [
|
||||||
unit_name
|
unit_name
|
||||||
|
@ -322,34 +347,33 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
if len(matching_unit_names) == 0:
|
if len(matching_unit_names) == 0:
|
||||||
msg = f"Tried to set unit for socket {self} with value {value}, but it is not one of possible units {''.join(possible.units.values())} for this socket (as defined in `contracts.SOCKET_UNITS`)"
|
msg = f"Tried to set unit for socket {self} with value {value}, but it is not one of possible units {''.join(possible.units.values())} for this socket (as defined in `contracts.SOCKET_UNITS`)"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
if len(matching_unit_names) > 1:
|
if len(matching_unit_names) > 1:
|
||||||
msg = f"Tried to set unit for socket {self} with value {value}, but multiple possible matching units {''.join(possible.units.values())} for this socket (as defined in `contracts.SOCKET_UNITS`); there may only be one"
|
msg = f"Tried to set unit for socket {self} with value {value}, but multiple possible matching units {''.join(possible.units.values())} for this socket (as defined in `contracts.SOCKET_UNITS`); there may only be one"
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
self.active_unit = matching_unit_names[0]
|
self.active_unit = matching_unit_names[0]
|
||||||
|
|
||||||
def sync_unit_change(self) -> None:
|
def sync_unit_change(self) -> None:
|
||||||
"""In unit-aware sockets, the internal `value()` property multiplies the Blender property value by the current active unit.
|
"""In unit-aware sockets, the internal `value()` property multiplies the Blender property value by the current active unit.
|
||||||
|
|
||||||
When the unit is changed, `value()` will display the old scalar with the new unit.
|
When the unit is changed, `value()` will display the old scalar with the new unit.
|
||||||
To fix this, we need to update the scalar to use the new unit.
|
To fix this, we need to update the scalar to use the new unit.
|
||||||
|
|
||||||
Can be overridden if more specific logic is required.
|
Can be overridden if more specific logic is required.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
prev_value = self.value / self.unit * self.prev_unit
|
prev_value = self.value / self.unit * self.prev_unit
|
||||||
## After changing units, self.value is expressed in the wrong unit.
|
## After changing units, self.value is expressed in the wrong unit.
|
||||||
## - Therefore, we removing the new unit, and re-add the prev unit.
|
## - Therefore, we removing the new unit, and re-add the prev unit.
|
||||||
## - 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Style
|
# - Style
|
||||||
####################
|
####################
|
||||||
|
@ -358,16 +382,14 @@ 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI Methods
|
# - UI Methods
|
||||||
####################
|
####################
|
||||||
|
@ -378,14 +400,13 @@ 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)
|
||||||
else:
|
else:
|
||||||
self.draw_input(context, layout, node, text)
|
self.draw_input(context, layout, node, text)
|
||||||
|
|
||||||
def draw_prelock(
|
def draw_prelock(
|
||||||
self,
|
self,
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
|
@ -394,7 +415,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw_input(
|
def draw_input(
|
||||||
self,
|
self,
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
|
@ -402,51 +423,52 @@ 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:
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
return
|
return
|
||||||
|
|
||||||
## User Label Row (incl. Units)
|
## User Label Row (incl. Units)
|
||||||
if self.use_units:
|
if self.use_units:
|
||||||
split = row.split(factor=0.6, align=True)
|
split = row.split(factor=0.6, align=True)
|
||||||
|
|
||||||
_row = split.row(align=True)
|
_row = split.row(align=True)
|
||||||
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)
|
||||||
|
|
||||||
# Prelock Row
|
# Prelock Row
|
||||||
row = col.row(align=False)
|
row = col.row(align=False)
|
||||||
if self.use_prelock:
|
if self.use_prelock:
|
||||||
_col = row.column(align=False)
|
_col = row.column(align=False)
|
||||||
_col.enabled = True
|
_col.enabled = True
|
||||||
self.draw_prelock(context, _col, node, text)
|
self.draw_prelock(context, _col, node, text)
|
||||||
|
|
||||||
if self.locked:
|
if self.locked:
|
||||||
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)
|
||||||
if self.is_list:
|
if self.is_list:
|
||||||
self.draw_value_list(col)
|
self.draw_value_list(col)
|
||||||
else:
|
else:
|
||||||
self.draw_value(col)
|
self.draw_value(col)
|
||||||
|
|
||||||
def draw_output(
|
def draw_output(
|
||||||
self,
|
self,
|
||||||
context: bpy.types.Context,
|
context: bpy.types.Context,
|
||||||
|
@ -454,10 +476,9 @@ 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)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI Methods
|
# - UI Methods
|
||||||
####################
|
####################
|
||||||
|
@ -467,22 +488,21 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Called to draw the label row (same height as socket shape).
|
"""Called to draw the label row (same height as socket shape).
|
||||||
|
|
||||||
Can be overridden.
|
Can be overridden.
|
||||||
"""
|
"""
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
|
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
"""Called to draw the value column in unlinked input sockets.
|
"""Called to draw the value column in unlinked input sockets.
|
||||||
|
|
||||||
Can be overridden.
|
Can be overridden.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw_value_list(self, col: bpy.types.UILayout) -> None:
|
def draw_value_list(self, col: bpy.types.UILayout) -> None:
|
||||||
"""Called to draw the value list column in unlinked input sockets.
|
"""Called to draw the value list column in unlinked input sockets.
|
||||||
|
|
||||||
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,22 +7,25 @@ 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
|
||||||
####################
|
####################
|
||||||
class AnySocketDef(pyd.BaseModel):
|
class AnySocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.Any
|
socket_type: ct.SocketType = ct.SocketType.Any
|
||||||
|
|
||||||
def init(self, bl_socket: AnyBLSocket) -> None:
|
def init(self, bl_socket: AnyBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -7,52 +7,57 @@ 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bool:
|
def value(self) -> bool:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value: bool) -> None:
|
def value(self, value: bool) -> None:
|
||||||
self.raw_value = value
|
self.raw_value = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
####################
|
####################
|
||||||
class BoolSocketDef(pyd.BaseModel):
|
class BoolSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.Bool
|
socket_type: ct.SocketType = ct.SocketType.Bool
|
||||||
|
|
||||||
default_value: bool = False
|
default_value: bool = False
|
||||||
|
|
||||||
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,52 +8,55 @@ 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)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket UI
|
# - Socket UI
|
||||||
####################
|
####################
|
||||||
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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> Path:
|
def value(self) -> Path:
|
||||||
return Path(bpy.path.abspath(self.raw_value))
|
return Path(bpy.path.abspath(self.raw_value))
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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,51 +7,56 @@ 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> str:
|
def value(self) -> str:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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,52 +6,53 @@ 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bpy.types.Collection | None:
|
def value(self) -> bpy.types.Collection | None:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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
|
||||||
####################
|
####################
|
||||||
class BlenderCollectionSocketDef(pyd.BaseModel):
|
class BlenderCollectionSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.BlenderCollection
|
socket_type: ct.SocketType = ct.SocketType.BlenderCollection
|
||||||
|
|
||||||
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,25 +6,26 @@ 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]
|
||||||
node = node_tree.nodes[self.node_name]
|
node = node_tree.nodes[self.node_name]
|
||||||
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,61 +34,63 @@ 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
|
||||||
#
|
#
|
||||||
# op = label_col_row.operator(
|
# op = label_col_row.operator(
|
||||||
# BlenderMaxwellResetGeoNodesSocket.bl_idname,
|
# BlenderMaxwellResetGeoNodesSocket.bl_idname,
|
||||||
# text="",
|
# text="",
|
||||||
# icon="FILE_REFRESH",
|
# icon="FILE_REFRESH",
|
||||||
# )
|
# )
|
||||||
# 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
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bpy.types.NodeTree | None:
|
def value(self) -> bpy.types.NodeTree | None:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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
|
||||||
####################
|
####################
|
||||||
class BlenderGeoNodesSocketDef(pyd.BaseModel):
|
class BlenderGeoNodesSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.BlenderGeoNodes
|
socket_type: ct.SocketType = ct.SocketType.BlenderGeoNodes
|
||||||
|
|
||||||
def init(self, bl_socket: BlenderGeoNodesBLSocket) -> None:
|
def init(self, bl_socket: BlenderGeoNodesBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -6,52 +6,53 @@ 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bpy.types.Image | None:
|
def value(self) -> bpy.types.Image | None:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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
|
||||||
####################
|
####################
|
||||||
class BlenderImageSocketDef(pyd.BaseModel):
|
class BlenderImageSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.BlenderImage
|
socket_type: ct.SocketType = ct.SocketType.BlenderImage
|
||||||
|
|
||||||
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,93 +6,97 @@ 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]
|
||||||
node = node_tree.nodes[self.node_name]
|
node = node_tree.nodes[self.node_name]
|
||||||
socket = node.inputs[self.socket_name]
|
socket = node.inputs[self.socket_name]
|
||||||
|
|
||||||
socket.create_and_assign_bl_object()
|
socket.create_and_assign_bl_object()
|
||||||
|
|
||||||
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)),
|
||||||
)
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - 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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
self.value = new_bl_object
|
self.value = new_bl_object
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bpy.types.Object | None:
|
def value(self) -> bpy.types.Object | None:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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
|
||||||
####################
|
####################
|
||||||
class BlenderObjectSocketDef(pyd.BaseModel):
|
class BlenderObjectSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.BlenderObject
|
socket_type: ct.SocketType = ct.SocketType.BlenderObject
|
||||||
|
|
||||||
def init(self, bl_socket: BlenderObjectBLSocket) -> None:
|
def init(self, bl_socket: BlenderObjectBLSocket) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -6,52 +6,53 @@ 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
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> bpy.types.Text:
|
def value(self) -> bpy.types.Text:
|
||||||
return self.raw_value
|
return self.raw_value
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
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
|
||||||
####################
|
####################
|
||||||
class BlenderTextSocketDef(pyd.BaseModel):
|
class BlenderTextSocketDef(pyd.BaseModel):
|
||||||
socket_type: ct.SocketType = ct.SocketType.BlenderText
|
socket_type: ct.SocketType = ct.SocketType.BlenderText
|
||||||
|
|
||||||
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