diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/sim_types.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/sim_types.py index 9c60730..16eeca5 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/sim_types.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/sim_types.py @@ -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. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/combine.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/combine.py index a0a3134..b7e4a84 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/combine.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/combine.py @@ -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 diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/gaussian_beam_source.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/gaussian_beam_source.py index 85f95dc..2bbd6b0 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/gaussian_beam_source.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/gaussian_beam_source.py @@ -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 diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py index 5d3f26a..6c5f25a 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/plane_wave_source.py @@ -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), + ) #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py index dad848f..b51b5ef 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py @@ -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), + ) #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py index edd2d95..183e42a 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py @@ -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', diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/cylinder_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/cylinder_structure.py index a43540e..072756d 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/cylinder_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/cylinder_structure.py @@ -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), + ) #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_cond.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_cond.py index 29fad53..dc24404 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_cond.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_cond.py @@ -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. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_conds.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_conds.py index 97c434a..1445ee3 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_conds.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/bound_conds.py @@ -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 diff --git a/src/blender_maxwell/utils/bl_cache/bl_field.py b/src/blender_maxwell/utils/bl_cache/bl_field.py index 110a985..2f74682 100644 --- a/src/blender_maxwell/utils/bl_cache/bl_field.py +++ b/src/blender_maxwell/utils/bl_cache/bl_field.py @@ -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,