feat: more lazy sim-design support

Making real headway.
main
Sofus Albert Høgsbro Rose 2024-05-30 22:30:57 +02:00
parent c286d65193
commit 3624d2ff45
Signed by: so-rose
GPG Key ID: AD901CB0F3701434
10 changed files with 282 additions and 174 deletions

View File

@ -213,6 +213,10 @@ class SimFieldPols(enum.StrEnum):
SFP.Hz: 'Hz',
}[v]
@property
def name(self) -> str:
return SimFieldPols.to_name(self)
@staticmethod
def to_icon(_: typ.Self) -> str:
"""Convert the enum value to a Blender icon.

View File

@ -163,10 +163,19 @@ class CombineNode(base.MaxwellSimNode):
if not ct.FlowSignal.check(inp)
]
if func_flows:
return functools.reduce(
lambda a, b: a | b,
func_flows,
return func_flows
return ct.FlowSignal.FlowPending
case (ct.FlowKind.Func, ct.FlowKind.Params):
params_flows = [
params_flow
for inp_sckname in self.inputs.keys() # noqa: SIM118
if not ct.FlowSignal.check(
params_flow := self._compute_input(inp_sckname, kind='params')
)
]
if params_flows:
return params_flows
return ct.FlowSignal.FlowPending
return ct.FlowSignal.FlowPending
@ -200,6 +209,18 @@ class CombineNode(base.MaxwellSimNode):
loose_input_sockets, props['value_or_func'], ct.FlowKind.Func
)
@events.computes_output_socket(
'Sources',
kind=ct.FlowKind.Params,
all_loose_input_sockets=True,
props={'value_or_func'},
)
def compute_sources_params(self, props, loose_input_sockets) -> list[typ.Any]:
"""Compute (lazy) sources."""
return self.compute_combined(
loose_input_sockets, props['value_or_func'], ct.FlowKind.Params
)
####################
# - Output: Structures
####################
@ -227,6 +248,18 @@ class CombineNode(base.MaxwellSimNode):
loose_input_sockets, props['value_or_func'], ct.FlowKind.Func
)
@events.computes_output_socket(
'Structures',
kind=ct.FlowKind.Params,
all_loose_input_sockets=True,
props={'value_or_func'},
)
def compute_structures_params(self, props, loose_input_sockets) -> list[typ.Any]:
"""Compute (lazy) structures."""
return self.compute_combined(
loose_input_sockets, props['value_or_func'], ct.FlowKind.Params
)
####################
# - Output: Monitors
####################
@ -254,6 +287,18 @@ class CombineNode(base.MaxwellSimNode):
loose_input_sockets, props['value_or_func'], ct.FlowKind.Func
)
@events.computes_output_socket(
'Monitors',
kind=ct.FlowKind.Params,
all_loose_input_sockets=True,
props={'value_or_func'},
)
def compute_monitors_params(self, props, loose_input_sockets) -> list[typ.Any]:
"""Compute (lazy) structures."""
return self.compute_combined(
loose_input_sockets, props['value_or_func'], ct.FlowKind.Params
)
####################
# - Blender Registration

View File

@ -98,11 +98,9 @@ class GaussianBeamSourceNode(base.MaxwellSimNode):
####################
# - Properties
####################
injection_axis: ct.SimSpaceAxis = bl_cache.BLField(ct.SimSpaceAxis.X, prop_ui=True)
injection_direction: ct.SimAxisDir = bl_cache.BLField(
ct.SimAxisDir.Plus, prop_ui=True
)
num_freqs: int = bl_cache.BLField(1, abs_min=1, soft_max=20, prop_ui=True)
injection_axis: ct.SimSpaceAxis = bl_cache.BLField(ct.SimSpaceAxis.X)
injection_direction: ct.SimAxisDir = bl_cache.BLField(ct.SimAxisDir.Plus)
num_freqs: int = bl_cache.BLField(1, abs_min=1, soft_max=20)
####################
# - UI

View File

@ -81,10 +81,8 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
####################
# - Properties
####################
injection_axis: ct.SimSpaceAxis = bl_cache.BLField(ct.SimSpaceAxis.X, prop_ui=True)
injection_direction: ct.SimAxisDir = bl_cache.BLField(
ct.SimAxisDir.Plus, prop_ui=True
)
injection_axis: ct.SimSpaceAxis = bl_cache.BLField(ct.SimSpaceAxis.X)
injection_direction: ct.SimAxisDir = bl_cache.BLField(ct.SimAxisDir.Plus)
####################
# - UI
@ -94,10 +92,34 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
layout.prop(self, self.blfields['injection_direction'], expand=True)
####################
# - Output Socket Computation
# - FlowKind.Value
####################
@events.computes_output_socket(
'Angled Source',
kind=ct.FlowKind.Value,
# Loaded
output_sockets={'Angled Source'},
output_socket_kinds={'Angled Source': {ct.FlowKind.Func, ct.FlowKind.Params}},
)
def compute_value(self, output_sockets) -> ct.ParamsFlow | ct.FlowSignal:
"""Compute the particular value of the simulation domain from strictly non-symbolic inputs."""
output_func = output_sockets['Source'][ct.FlowKind.Func]
output_params = output_sockets['Source'][ct.FlowKind.Params]
has_output_func = not ct.FlowSignal.check(output_func)
has_output_params = not ct.FlowSignal.check(output_params)
if has_output_func and has_output_params and not output_params.symbols:
return output_func.realize(output_params, disallow_jax=True)
return ct.FlowSignal.FlowPending
####################
# - FlowKind.Func
####################
@events.computes_output_socket(
'Angled Source',
kind=ct.FlowKind.Func,
# Loaded
props={'sim_node_name', 'injection_axis', 'injection_direction'},
input_sockets={'Temporal Shape', 'Center', 'Spherical', 'Pol ∡'},
unit_systems={'Tidy3DUnits': ct.UNITS_TIDY3D},
@ -107,24 +129,44 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
'Pol ∡': 'Tidy3DUnits',
},
)
def compute_source(self, props, input_sockets, unit_systems):
size = {
ct.SimSpaceAxis.X: (0, td.inf, td.inf),
ct.SimSpaceAxis.Y: (td.inf, 0, td.inf),
ct.SimSpaceAxis.Z: (td.inf, td.inf, 0),
}[props['injection_axis']]
def compute_func(self, props, input_sockets) -> None:
center = input_sockets['Center']
temporal_shape = input_sockets['Temporal Shape']
spherical = input_sockets['Spherical']
pol_ang = input_sockets['Pol ∡']
# Display the results
return td.PlaneWave(
name=props['sim_node_name'],
center=input_sockets['Center'],
size=size,
source_time=input_sockets['Temporal Shape'],
direction=props['injection_direction'].plus_or_minus,
angle_theta=input_sockets['Spherical'][0],
angle_phi=input_sockets['Spherical'][1],
pol_angle=input_sockets['Pol ∡'],
)
has_center = not ct.FlowSignal.check(center)
has_temporal_shape = not ct.FlowSignal.check(temporal_shape)
has_spherical = not ct.FlowSignal.check(spherical)
has_pol_ang = not ct.FlowSignal.check(pol_ang)
if has_center and has_temporal_shape and has_spherical and has_pol_ang:
name = props['sim_node_name']
inj_dir = props['injection_direction'].plus_or_minus
size = {
ct.SimSpaceAxis.X: (0, td.inf, td.inf),
ct.SimSpaceAxis.Y: (td.inf, 0, td.inf),
ct.SimSpaceAxis.Z: (td.inf, td.inf, 0),
}[props['injection_axis']]
return (
center.scale_to_unit_system(ct.UNITS_TIDY3D)
| temporal_shape
| spherical.scale_to_unit_system(ct.UNITS_TIDY3D)
| pol_ang.scale_to_unit_system(ct.UNITS_TIDY3D)
).compose_within(
lambda els: td.PlaneWave(
name=name,
center=els[0],
size=size,
source_time=els[1],
direction=inj_dir,
angle_theta=els[2][0],
angle_phi=els[2][1],
pol_angle=els[3],
)
)
return ct.FlowSignal.FlowPending
####################
# - Preview - Changes to Input Sockets
@ -134,9 +176,16 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
kind=ct.FlowKind.Previews,
# Loaded
props={'sim_node_name'},
output_sockets={'Structure'},
output_socket_kinds={'Structure': ct.FlowKind.Params},
)
def compute_previews(self, props):
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
def compute_previews(self, props, output_sockets):
output_params = output_sockets['Structure']
has_output_params = not ct.FlowSignal.check(output_params)
if has_output_params and not output_params.symbols:
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
return ct.PreviewsFlow()
@events.on_value_changed(
# Trigger
@ -147,28 +196,43 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
managed_objs={'modifier'},
props={'injection_axis', 'injection_direction'},
input_sockets={'Temporal Shape', 'Center', 'Spherical', 'Pol ∡'},
unit_systems={'BlenderUnits': ct.UNITS_BLENDER},
scale_input_sockets={
'Center': 'BlenderUnits',
},
output_sockets={'Angled Source'},
output_socket_kinds={'Angled Source': ct.FlowKind.Params},
)
def on_inputs_changed(self, managed_objs, props, input_sockets, unit_systems):
# Push Input Values to GeoNodes Modifier
managed_objs['modifier'].bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.SourcePlaneWave),
'unit_system': unit_systems['BlenderUnits'],
'inputs': {
'Inj Axis': props['injection_axis'].axis,
'Direction': props['injection_direction'].true_or_false,
'theta': input_sockets['Spherical'][0],
'phi': input_sockets['Spherical'][1],
'Pol Angle': input_sockets['Pol ∡'],
def on_inputs_changed(self, managed_objs, props, input_sockets, output_sockets):
center = input_sockets['Center']
spherical = input_sockets['Spherical']
pol_ang = input_sockets['Pol ∡']
output_params = output_sockets['Angled Source']
has_center = not ct.FlowSignal.check(center)
has_spherical = not ct.FlowSignal.check(spherical)
has_pol_ang = not ct.FlowSignal.check(pol_ang)
has_output_params = not ct.FlowSignal.check(output_params)
if (
has_center
and has_spherical
and has_pol_ang
and has_output_params
and not output_params.symbols
):
# Push Input Values to GeoNodes Modifier
managed_objs['modifier'].bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.SourcePlaneWave),
'unit_system': ct.UNITS_BLENDER,
'inputs': {
'Inj Axis': props['injection_axis'].axis,
'Direction': props['injection_direction'].true_or_false,
'theta': spherical[0],
'phi': spherical[1],
'Pol Angle': pol_ang,
},
},
},
location=input_sockets['Center'],
)
location=spux.scale_to_unit_system(center, ct.UNITS_BLENDER),
)
####################

View File

@ -52,7 +52,7 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
),
}
output_sockets: typ.ClassVar = {
'Source': sockets.MaxwellSourceSocketDef(),
'Source': sockets.MaxwellSourceSocketDef(active_kind=ct.FlowKind.Func),
}
managed_obj_types: typ.ClassVar = {
@ -62,59 +62,34 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
####################
# - Properties
####################
pol_axis: ct.SimSpaceAxis = bl_cache.BLField(ct.SimSpaceAxis.X, prop_ui=True)
pol: ct.SimFieldPols = bl_cache.BLField(ct.SimFieldPols.Ex)
####################
# - UI
####################
def draw_props(self, _: bpy.types.Context, layout: bpy.types.UILayout):
layout.prop(self, self.blfields['pol_axis'], expand=True)
layout.prop(self, self.blfields['pol'], expand=True)
####################
# - FlowKind.Value
####################
@events.computes_output_socket(
'Source',
kind=ct.FlowKind.Value,
# Loaded
props={'pol_axis'},
input_sockets={'Temporal Shape', 'Center', 'Interpolate'},
output_sockets={'Source'},
output_socket_kinds={'Source': ct.FlowKind.Params},
output_socket_kinds={'Source': {ct.FlowKind.Func, ct.FlowKind.Params}},
)
def compute_source_value(
self, input_sockets, props, output_sockets
) -> td.PointDipole | ct.FlowSignal:
"""Compute the point dipole source, given that all inputs are non-symbolic."""
temporal_shape = input_sockets['Temporal Shape']
center = input_sockets['Center']
interpolate = input_sockets['Interpolate']
output_params = output_sockets['Source']
def compute_value(self, output_sockets) -> ct.ParamsFlow | ct.FlowSignal:
"""Compute the particular value of the simulation domain from strictly non-symbolic inputs."""
output_func = output_sockets['Source'][ct.FlowKind.Func]
output_params = output_sockets['Source'][ct.FlowKind.Params]
has_temporal_shape = not ct.FlowSignal.check(temporal_shape)
has_center = not ct.FlowSignal.check(center)
has_interpolate = not ct.FlowSignal.check(interpolate)
has_output_func = not ct.FlowSignal.check(output_func)
has_output_params = not ct.FlowSignal.check(output_params)
if (
has_temporal_shape
and has_center
and has_interpolate
and has_output_params
and not output_params.symbols
):
pol_axis = {
ct.SimSpaceAxis.X: 'Ex',
ct.SimSpaceAxis.Y: 'Ey',
ct.SimSpaceAxis.Z: 'Ez',
}[props['pol_axis']]
## TODO: Need Hx, Hy, Hz too?
return td.PointDipole(
center=spux.convert_to_unit_system(center, ct.UNITS_TIDY3D),
source_time=temporal_shape,
interpolate=interpolate,
polarization=pol_axis,
)
if has_output_func and has_output_params and not output_params.symbols:
return output_func.realize(output_params, disallow_jax=True)
return ct.FlowSignal.FlowPending
####################
@ -124,42 +99,36 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
'Source',
kind=ct.FlowKind.Func,
# Loaded
props={'pol_axis'},
props={'pol'},
input_sockets={'Temporal Shape', 'Center', 'Interpolate'},
input_socket_kinds={
'Temporal Shape': ct.FlowKind.Func,
'Center': ct.FlowKind.Func,
'Interpolate': ct.FlowKind.Func,
},
output_sockets={'Source'},
output_socket_kinds={'Source': ct.FlowKind.Params},
)
def compute_source_func(self, props, input_sockets, output_sockets) -> td.Box:
def compute_func(self, props, input_sockets) -> td.Box:
"""Compute a lazy function for the point dipole source."""
center = input_sockets['Center']
temporal_shape = input_sockets['Temporal Shape']
interpolate = input_sockets['Interpolate']
output_params = output_sockets['Source']
has_center = not ct.FlowSignal.check(center)
has_temporal_shape = not ct.FlowSignal.check(temporal_shape)
has_interpolate = not ct.FlowSignal.check(interpolate)
has_output_params = not ct.FlowSignal.check(output_params)
if has_temporal_shape and has_center and has_interpolate and has_output_params:
pol_axis = {
ct.SimSpaceAxis.X: 'Ex',
ct.SimSpaceAxis.Y: 'Ey',
ct.SimSpaceAxis.Z: 'Ez',
}[props['pol_axis']]
## TODO: Need Hx, Hy, Hz too?
return (center | temporal_shape | interpolate).compose_within(
if has_temporal_shape and has_center and has_interpolate:
pol = props['pol']
return (
center.scale_to_unit_system(ct.UNITS_TIDY3D)
| temporal_shape
| interpolate
).compose_within(
enclosing_func=lambda els: td.PointDipole(
center=els[0],
center=els[0].flatten().tolist(),
source_time=els[1],
interpolate=els[2],
polarization=pol_axis,
polarization=pol.name,
)
)
return ct.FlowSignal.FlowPending
@ -183,16 +152,16 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
input_sockets,
) -> td.PointDipole | ct.FlowSignal:
"""Compute the point dipole source, given that all inputs are non-symbolic."""
temporal_shape = input_sockets['Temporal Shape']
center = input_sockets['Center']
temporal_shape = input_sockets['Temporal Shape']
interpolate = input_sockets['Interpolate']
has_temporal_shape = not ct.FlowSignal.check(temporal_shape)
has_center = not ct.FlowSignal.check(center)
has_temporal_shape = not ct.FlowSignal.check(temporal_shape)
has_interpolate = not ct.FlowSignal.check(interpolate)
if has_temporal_shape and has_center and has_interpolate:
return temporal_shape | center | interpolate
if has_center and has_temporal_shape and has_interpolate:
return center | temporal_shape | interpolate
return ct.FlowSignal.FlowPending
####################
@ -203,42 +172,59 @@ class PointDipoleSourceNode(base.MaxwellSimNode):
kind=ct.FlowKind.Previews,
# Loaded
props={'sim_node_name'},
output_sockets={'Structure'},
output_socket_kinds={'Structure': ct.FlowKind.Params},
)
def compute_previews(self, props):
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
def compute_previews(self, props, output_sockets):
output_params = output_sockets['Structure']
has_output_params = not ct.FlowSignal.check(output_params)
if has_output_params and not output_params.symbols:
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
return ct.PreviewsFlow()
@events.on_value_changed(
socket_name={'Center'},
prop_name='pol_axis',
prop_name='pol',
run_on_init=True,
# Pass Data
# Loaded
managed_objs={'modifier'},
props={'pol_axis'},
props={'pol'},
input_sockets={'Center'},
unit_systems={'BlenderUnits': ct.UNITS_BLENDER},
scale_input_sockets={'Center': 'BlenderUnits'},
output_sockets={'Source'},
output_socket_kinds={'Source': ct.FlowKind.Params},
)
def on_inputs_changed(
self, managed_objs, props, input_sockets, unit_systems
self, managed_objs, props, input_sockets, output_sockets
) -> None:
modifier = managed_objs['modifier']
unit_system = unit_systems['BlenderUnits']
axis = {
ct.SimSpaceAxis.X: 0,
ct.SimSpaceAxis.Y: 1,
ct.SimSpaceAxis.Z: 2,
}[props['pol_axis']]
SFP = ct.SimFieldPols
# Push Loose Input Values to GeoNodes Modifier
modifier.bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.SourcePointDipole),
'inputs': {'Axis': axis},
'unit_system': unit_system,
},
location=input_sockets['Center'],
)
center = input_sockets['Center']
output_params = output_sockets['Source']
has_center = not ct.FlowSignal.check(center)
has_output_params = not ct.FlowSignal.check(output_params)
if has_center and has_output_params and not output_params.symbols:
axis = {
SFP.Ex: 0,
SFP.Ey: 1,
SFP.Ez: 2,
SFP.Hx: 0,
SFP.Hy: 1,
SFP.Hz: 2,
}[props['pol']]
# Push Loose Input Values to GeoNodes Modifier
managed_objs['modifier'].bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.SourcePointDipole),
'inputs': {'Axis': axis},
'unit_system': ct.UNITS_BLENDER,
},
location=spux.scale_to_unit_system(center, ct.UNITS_BLENDER),
)
####################

View File

@ -58,7 +58,7 @@ class BoxStructureNode(base.MaxwellSimNode):
),
}
output_sockets: typ.ClassVar = {
'Structure': sockets.MaxwellStructureSocketDef(),
'Structure': sockets.MaxwellStructureSocketDef(active_kind=ct.FlowKind.Func),
}
managed_obj_types: typ.ClassVar = {
@ -228,8 +228,6 @@ class BoxStructureNode(base.MaxwellSimNode):
has_output_params = not ct.FlowSignal.check(output_params)
if has_center and has_size and has_output_params and not output_params.symbols:
## TODO: There are strategies for handling examples of symbol values.
# Push Loose Input Values to GeoNodes Modifier
managed_objs['modifier'].bl_modifier(
'NODES',

View File

@ -58,7 +58,7 @@ class CylinderStructureNode(base.MaxwellSimNode):
),
}
output_sockets: typ.ClassVar = {
'Structure': sockets.MaxwellStructureSocketDef(),
'Structure': sockets.MaxwellStructureSocketDef(active_kind=ct.FlowKind.Func),
}
managed_obj_types: typ.ClassVar = {
@ -170,9 +170,16 @@ class CylinderStructureNode(base.MaxwellSimNode):
kind=ct.FlowKind.Previews,
# Loaded
props={'sim_node_name'},
output_sockets={'Structure'},
output_socket_kinds={'Structure': ct.FlowKind.Params},
)
def compute_previews(self, props):
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
def compute_previews(self, props, output_sockets):
output_params = output_sockets['Structure']
has_output_params = not ct.FlowSignal.check(output_params)
if has_output_params and not output_params.symbols:
return ct.PreviewsFlow(bl_object_names={props['sim_node_name']})
return ct.PreviewsFlow()
@events.on_value_changed(
# Trigger
@ -181,33 +188,40 @@ class CylinderStructureNode(base.MaxwellSimNode):
# Loaded
input_sockets={'Center', 'Radius', 'Medium', 'Height'},
managed_objs={'modifier'},
unit_systems={'BlenderUnits': ct.UNITS_BLENDER},
scale_input_sockets={
'Center': 'BlenderUnits',
},
output_sockets={'Structure'},
output_socket_kinds={'Structure': ct.FlowKind.Params},
)
def on_inputs_changed(
self,
managed_objs,
input_sockets,
unit_systems,
):
modifier = managed_objs['modifier']
unit_system = unit_systems['BlenderUnits']
def on_previewable_changed(self, managed_objs, input_sockets, output_sockets):
center = input_sockets['Center']
radius = input_sockets['Radius']
height = input_sockets['Height']
output_params = output_sockets['Structure']
# Push Loose Input Values to GeoNodes Modifier
modifier.bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.StructurePrimitiveCylinder),
'inputs': {
'Radius': input_sockets['Radius'],
'Height': input_sockets['Height'],
has_center = not ct.FlowSignal.check(center)
has_radius = not ct.FlowSignal.check(radius)
has_height = not ct.FlowSignal.check(height)
has_output_params = not ct.FlowSignal.check(output_params)
if (
has_center
and has_radius
and has_height
and has_output_params
and not output_params.symbols
):
# Push Loose Input Values to GeoNodes Modifier
managed_objs['modifier'].bl_modifier(
'NODES',
{
'node_group': import_geonodes(GeoNodes.StructurePrimitiveCylinder),
'inputs': {
'Radius': radius,
'Height': height,
},
'unit_system': ct.UNITS_BLENDER,
},
'unit_system': unit_system,
},
location=input_sockets['Center'],
)
location=spux.scale_to_unit_system(center, ct.UNITS_BLENDER),
)
####################

View File

@ -39,7 +39,7 @@ class MaxwellBoundCondBLSocket(base.MaxwellSimSocket):
####################
# - Properties
####################
default: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
default: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
# Capabilities
## Allow a boundary condition compatible with any of the following axes.

View File

@ -46,14 +46,14 @@ class MaxwellBoundCondsBLSocket(base.MaxwellSimSocket):
####################
# - Properties
####################
show_definition: bool = bl_cache.BLField(False, prop_ui=True)
show_definition: bool = bl_cache.BLField(False)
x_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
x_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
y_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
y_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
z_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
z_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
x_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
x_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
y_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
y_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
z_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
z_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml)
####################
# - UI

View File

@ -65,7 +65,6 @@ class BLField:
default_value: typ.Any = None,
use_prop_update: bool = True,
## Static
prop_ui: bool = False, ## TODO: Remove
abs_min: int | float | None = None,
abs_max: int | float | None = None,
soft_min: int | float | None = None,