feat: Various features (some very prototype).
It's very prototype-y. Cleanup pending.main
parent
0f1465768b
commit
28e6760dfb
|
@ -97,6 +97,7 @@ class SocketType(BlenderTypeEnum):
|
||||||
Complex3DVector = enum.auto()
|
Complex3DVector = enum.auto()
|
||||||
|
|
||||||
# Physical
|
# Physical
|
||||||
|
PhysicalUnitSystem = enum.auto()
|
||||||
PhysicalTime = enum.auto()
|
PhysicalTime = enum.auto()
|
||||||
|
|
||||||
PhysicalAngle = enum.auto()
|
PhysicalAngle = enum.auto()
|
||||||
|
@ -122,6 +123,7 @@ class SocketType(BlenderTypeEnum):
|
||||||
PhysicalPol = enum.auto()
|
PhysicalPol = enum.auto()
|
||||||
|
|
||||||
PhysicalFreq = enum.auto()
|
PhysicalFreq = enum.auto()
|
||||||
|
PhysicalVacWL = enum.auto()
|
||||||
PhysicalSpecPowerDist = enum.auto()
|
PhysicalSpecPowerDist = enum.auto()
|
||||||
PhysicalSpecRelPermDist = enum.auto()
|
PhysicalSpecRelPermDist = enum.auto()
|
||||||
|
|
||||||
|
@ -135,6 +137,8 @@ class SocketType(BlenderTypeEnum):
|
||||||
BlenderGeoNodes = enum.auto()
|
BlenderGeoNodes = enum.auto()
|
||||||
BlenderText = enum.auto()
|
BlenderText = enum.auto()
|
||||||
|
|
||||||
|
BlenderPreviewTarget = enum.auto()
|
||||||
|
|
||||||
# Maxwell
|
# Maxwell
|
||||||
MaxwellSource = enum.auto()
|
MaxwellSource = enum.auto()
|
||||||
MaxwellTemporalShape = enum.auto()
|
MaxwellTemporalShape = enum.auto()
|
||||||
|
@ -376,14 +380,19 @@ SocketType_to_units = {
|
||||||
"GHZ": spuex.gigahertz,
|
"GHZ": spuex.gigahertz,
|
||||||
"THZ": spuex.terahertz,
|
"THZ": spuex.terahertz,
|
||||||
"PHZ": spuex.petahertz,
|
"PHZ": spuex.petahertz,
|
||||||
#"EHZ": spu.exahertz,
|
"EHZ": spuex.exahertz,
|
||||||
"VAC_PM": spu.picometer, ## c(vac) = wl*freq
|
},
|
||||||
"VAC_A": spu.angstrom,
|
},
|
||||||
"VAC_NM": spu.nanometer,
|
SocketType.PhysicalVacWL: {
|
||||||
"VAC_UM": spu.micrometer,
|
"default": "NM",
|
||||||
"VAC_MM": spu.millimeter,
|
"values": {
|
||||||
"VAC_CM": spu.centimeter,
|
"PM": spu.picometer, ## c(vac) = wl*freq
|
||||||
"VAC_M": spu.meter,
|
"A": spu.angstrom,
|
||||||
|
"NM": spu.nanometer,
|
||||||
|
"UM": spu.micrometer,
|
||||||
|
"MM": spu.millimeter,
|
||||||
|
"CM": spu.centimeter,
|
||||||
|
"M": spu.meter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -408,6 +417,7 @@ SocketType_to_color = {
|
||||||
SocketType.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
SocketType.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
||||||
|
|
||||||
# Physical
|
# Physical
|
||||||
|
SocketType.PhysicalUnitSystem: (1.0, 0.5, 0.5, 1.0), # Light Red
|
||||||
SocketType.PhysicalTime: (1.0, 0.5, 0.5, 1.0), # Light Red
|
SocketType.PhysicalTime: (1.0, 0.5, 0.5, 1.0), # Light Red
|
||||||
SocketType.PhysicalAngle: (0.9, 0.45, 0.45, 1.0), # Medium Light Red
|
SocketType.PhysicalAngle: (0.9, 0.45, 0.45, 1.0), # Medium Light Red
|
||||||
SocketType.PhysicalLength: (0.8, 0.4, 0.4, 1.0), # Medium Red
|
SocketType.PhysicalLength: (0.8, 0.4, 0.4, 1.0), # Medium Red
|
||||||
|
@ -425,6 +435,7 @@ SocketType_to_color = {
|
||||||
SocketType.PhysicalForce3DVector: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange
|
SocketType.PhysicalForce3DVector: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange
|
||||||
SocketType.PhysicalPol: (0.5, 0.4, 0.2, 1.0), # Dark Orange
|
SocketType.PhysicalPol: (0.5, 0.4, 0.2, 1.0), # Dark Orange
|
||||||
SocketType.PhysicalFreq: (1.0, 0.7, 0.5, 1.0), # Light Peach
|
SocketType.PhysicalFreq: (1.0, 0.7, 0.5, 1.0), # Light Peach
|
||||||
|
SocketType.PhysicalVacWL: (1.0, 0.7, 0.5, 1.0), # Light Peach
|
||||||
SocketType.PhysicalSpecPowerDist: (0.9, 0.65, 0.45, 1.0), # Medium Light Peach
|
SocketType.PhysicalSpecPowerDist: (0.9, 0.65, 0.45, 1.0), # Medium Light Peach
|
||||||
SocketType.PhysicalSpecRelPermDist: (0.8, 0.6, 0.4, 1.0), # Medium Peach
|
SocketType.PhysicalSpecRelPermDist: (0.8, 0.6, 0.4, 1.0), # Medium Peach
|
||||||
|
|
||||||
|
@ -435,6 +446,7 @@ SocketType_to_color = {
|
||||||
SocketType.BlenderVolume: (0.4, 0.35, 0.7, 1.0), # Medium Dark Purple
|
SocketType.BlenderVolume: (0.4, 0.35, 0.7, 1.0), # Medium Dark Purple
|
||||||
SocketType.BlenderGeoNodes: (0.3, 0.3, 0.6, 1.0), # Dark Purple
|
SocketType.BlenderGeoNodes: (0.3, 0.3, 0.6, 1.0), # Dark Purple
|
||||||
SocketType.BlenderText: (0.5, 0.5, 0.75, 1.0), # Light Lavender
|
SocketType.BlenderText: (0.5, 0.5, 0.75, 1.0), # Light Lavender
|
||||||
|
SocketType.BlenderPreviewTarget: (0.5, 0.5, 0.75, 1.0), # Light Lavender
|
||||||
|
|
||||||
# Maxwell
|
# Maxwell
|
||||||
SocketType.MaxwellSource: (1.0, 1.0, 0.5, 1.0), # Light Yellow
|
SocketType.MaxwellSource: (1.0, 1.0, 0.5, 1.0), # Light Yellow
|
||||||
|
@ -451,40 +463,104 @@ SocketType_to_color = {
|
||||||
}
|
}
|
||||||
|
|
||||||
BLNodeSocket_to_SocketType = {
|
BLNodeSocket_to_SocketType = {
|
||||||
"NodeSocketBool": SocketType.Bool,
|
1: {
|
||||||
"NodeSocketCollection": SocketType.BlenderCollection,
|
"NodeSocketStandard": SocketType.Any,
|
||||||
"NodeSocketColor": SocketType.Real3DVector,
|
"NodeSocketVirtual": SocketType.Any,
|
||||||
"NodeSocketFloat": SocketType.RealNumber,
|
"NodeSocketGeometry": SocketType.Any,
|
||||||
"NodeSocketFloatAngle": SocketType.RealNumber,
|
"NodeSocketTexture": SocketType.Any,
|
||||||
"NodeSocketFloatDistance": SocketType.RealNumber,
|
"NodeSocketShader": SocketType.Any,
|
||||||
"NodeSocketFloatFactor": SocketType.RealNumber,
|
"NodeSocketMaterial": SocketType.Any,
|
||||||
"NodeSocketFloatPercentage": SocketType.RealNumber,
|
|
||||||
"NodeSocketFloatTime": SocketType.RealNumber,
|
"NodeSocketString": SocketType.Text,
|
||||||
"NodeSocketFloatTimeAbsolute": SocketType.RealNumber,
|
"NodeSocketBool": SocketType.Bool,
|
||||||
"NodeSocketFloatUnsigned": SocketType.RealNumber,
|
"NodeSocketCollection": SocketType.BlenderCollection,
|
||||||
"NodeSocketGeometry": SocketType.Any,
|
"NodeSocketImage": SocketType.BlenderImage,
|
||||||
"NodeSocketImage": SocketType.BlenderImage,
|
"NodeSocketObject": SocketType.BlenderObject,
|
||||||
"NodeSocketInt": SocketType.IntegerNumber,
|
|
||||||
"NodeSocketIntFactor": SocketType.IntegerNumber,
|
"NodeSocketFloat": SocketType.RealNumber,
|
||||||
"NodeSocketIntPercentage": SocketType.IntegerNumber,
|
"NodeSocketFloatAngle": SocketType.PhysicalAngle,
|
||||||
"NodeSocketIntUnsigned": SocketType.IntegerNumber,
|
"NodeSocketFloatDistance": SocketType.PhysicalLength,
|
||||||
"NodeSocketMaterial": SocketType.Any,
|
"NodeSocketFloatFactor": SocketType.RealNumber,
|
||||||
"NodeSocketObject": SocketType.BlenderObject,
|
"NodeSocketFloatPercentage": SocketType.RealNumber,
|
||||||
"NodeSocketRotation": SocketType.Real3DVector,
|
"NodeSocketFloatTime": SocketType.PhysicalTime,
|
||||||
"NodeSocketShader": SocketType.Any,
|
"NodeSocketFloatTimeAbsolute": SocketType.RealNumber,
|
||||||
"NodeSocketStandard": SocketType.Any,
|
"NodeSocketFloatUnsigned": SocketType.RealNumber,
|
||||||
"NodeSocketString": SocketType.Text,
|
|
||||||
"NodeSocketTexture": SocketType.Any,
|
"NodeSocketInt": SocketType.IntegerNumber,
|
||||||
"NodeSocketVector": SocketType.Real3DVector,
|
"NodeSocketIntFactor": SocketType.IntegerNumber,
|
||||||
"NodeSocketVectorAcceleration": SocketType.Real3DVector,
|
"NodeSocketIntPercentage": SocketType.IntegerNumber,
|
||||||
"NodeSocketVectorDirection": SocketType.Real3DVector,
|
"NodeSocketIntUnsigned": SocketType.IntegerNumber,
|
||||||
"NodeSocketVectorEuler": SocketType.Real3DVector,
|
},
|
||||||
"NodeSocketVectorTranslation": SocketType.Real3DVector,
|
2: {
|
||||||
"NodeSocketVectorVelocity": SocketType.Real3DVector,
|
"NodeSocketVector": SocketType.Real3DVector,
|
||||||
"NodeSocketVectorXYZ": SocketType.Real3DVector,
|
"NodeSocketVectorAcceleration": SocketType.Real3DVector,
|
||||||
"NodeSocketVirtual": SocketType.Any,
|
"NodeSocketVectorDirection": SocketType.Real3DVector,
|
||||||
|
"NodeSocketVectorEuler": SocketType.Real3DVector,
|
||||||
|
"NodeSocketVectorTranslation": SocketType.Real3DVector,
|
||||||
|
"NodeSocketVectorVelocity": SocketType.Real3DVector,
|
||||||
|
"NodeSocketVectorXYZ": SocketType.Real3DVector,
|
||||||
|
#"NodeSocketVector": SocketType.Real2DVector,
|
||||||
|
#"NodeSocketVectorAcceleration": SocketType.PhysicalAccel2D,
|
||||||
|
#"NodeSocketVectorDirection": SocketType.PhysicalDir2D,
|
||||||
|
#"NodeSocketVectorEuler": SocketType.PhysicalEuler2D,
|
||||||
|
#"NodeSocketVectorTranslation": SocketType.PhysicalDispl2D,
|
||||||
|
#"NodeSocketVectorVelocity": SocketType.PhysicalVel2D,
|
||||||
|
#"NodeSocketVectorXYZ": SocketType.Real2DPoint,
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"NodeSocketRotation": SocketType.Real3DVector,
|
||||||
|
|
||||||
|
"NodeSocketColor": SocketType.Any,
|
||||||
|
|
||||||
|
"NodeSocketVector": SocketType.Real3DVector,
|
||||||
|
#"NodeSocketVectorAcceleration": SocketType.PhysicalAccel3D,
|
||||||
|
#"NodeSocketVectorDirection": SocketType.PhysicalDir3D,
|
||||||
|
#"NodeSocketVectorEuler": SocketType.PhysicalEuler3D,
|
||||||
|
#"NodeSocketVectorTranslation": SocketType.PhysicalDispl3D,
|
||||||
|
"NodeSocketVectorTranslation": SocketType.PhysicalPoint3D,
|
||||||
|
#"NodeSocketVectorVelocity": SocketType.PhysicalVel3D,
|
||||||
|
"NodeSocketVectorXYZ": SocketType.PhysicalPoint3D,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLNodeSocket_to_SocketType_by_desc = {
|
||||||
|
1: {
|
||||||
|
"Angle": SocketType.PhysicalAngle,
|
||||||
|
|
||||||
|
"Length": SocketType.PhysicalLength,
|
||||||
|
"Area": SocketType.PhysicalArea,
|
||||||
|
"Volume": SocketType.PhysicalVolume,
|
||||||
|
|
||||||
|
"Mass": SocketType.PhysicalMass,
|
||||||
|
|
||||||
|
"Speed": SocketType.PhysicalSpeed,
|
||||||
|
"Accel": SocketType.PhysicalAccelScalar,
|
||||||
|
"Force": SocketType.PhysicalForceScalar,
|
||||||
|
|
||||||
|
"Freq": SocketType.PhysicalFreq,
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
#"2DCount": SocketType.Int2DVector,
|
||||||
|
|
||||||
|
#"2DPoint": SocketType.PhysicalPoint2D,
|
||||||
|
#"2DSize": SocketType.PhysicalSize2D,
|
||||||
|
#"2DPol": SocketType.PhysicalPol,
|
||||||
|
"2DPoint": SocketType.PhysicalPoint3D,
|
||||||
|
"2DSize": SocketType.PhysicalSize3D,
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
#"Count": SocketType.Int3DVector,
|
||||||
|
|
||||||
|
"Point": SocketType.PhysicalPoint3D,
|
||||||
|
"Size": SocketType.PhysicalSize3D,
|
||||||
|
|
||||||
|
#"Force": SocketType.PhysicalForce3D,
|
||||||
|
|
||||||
|
"Freq": SocketType.PhysicalSize3D,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node Types
|
# - Node Types
|
||||||
####################
|
####################
|
||||||
|
@ -493,15 +569,17 @@ class NodeType(BlenderTypeEnum):
|
||||||
KitchenSink = enum.auto()
|
KitchenSink = enum.auto()
|
||||||
|
|
||||||
# Inputs
|
# Inputs
|
||||||
|
UnitSystem = enum.auto()
|
||||||
|
|
||||||
## Inputs / Scene
|
## Inputs / Scene
|
||||||
Time = enum.auto()
|
Time = enum.auto()
|
||||||
UnitSystem = 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()
|
||||||
ScientificConstant = enum.auto()
|
ScientificConstant = enum.auto()
|
||||||
NumberConstant = enum.auto()
|
NumberConstant = enum.auto()
|
||||||
PhysicalConstant = enum.auto()
|
PhysicalConstant = enum.auto()
|
||||||
|
@ -517,6 +595,7 @@ class NodeType(BlenderTypeEnum):
|
||||||
|
|
||||||
# Outputs
|
# Outputs
|
||||||
## Outputs / Viewers
|
## Outputs / Viewers
|
||||||
|
Viewer3D = enum.auto()
|
||||||
ValueViewer = enum.auto()
|
ValueViewer = enum.auto()
|
||||||
ConsoleViewer = enum.auto()
|
ConsoleViewer = enum.auto()
|
||||||
|
|
||||||
|
@ -612,8 +691,13 @@ class NodeType(BlenderTypeEnum):
|
||||||
|
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
Combine = enum.auto()
|
||||||
|
Separate = enum.auto()
|
||||||
Math = enum.auto()
|
Math = enum.auto()
|
||||||
|
|
||||||
|
## Utilities / Converters
|
||||||
|
WaveConverter = enum.auto()
|
||||||
|
|
||||||
## Utilities / Operations
|
## Utilities / Operations
|
||||||
ArrayOperation = enum.auto()
|
ArrayOperation = enum.auto()
|
||||||
|
|
||||||
|
@ -663,6 +747,7 @@ class NodeCategory(BlenderTypeEnum):
|
||||||
|
|
||||||
# Utilities/
|
# Utilities/
|
||||||
MAXWELLSIM_UTILITIES = enum.auto()
|
MAXWELLSIM_UTILITIES = enum.auto()
|
||||||
|
MAXWELLSIM_UTILITIES_CONVERTERS = enum.auto()
|
||||||
MAXWELLSIM_UTILITIES_OPERATIONS = enum.auto()
|
MAXWELLSIM_UTILITIES_OPERATIONS = enum.auto()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -727,6 +812,7 @@ NodeCategory_to_category_label = {
|
||||||
|
|
||||||
# Utilities/
|
# Utilities/
|
||||||
NodeCategory.MAXWELLSIM_UTILITIES: "Utilities",
|
NodeCategory.MAXWELLSIM_UTILITIES: "Utilities",
|
||||||
|
NodeCategory.MAXWELLSIM_UTILITIES_CONVERTERS: "Converters",
|
||||||
NodeCategory.MAXWELLSIM_UTILITIES_OPERATIONS: "Operations",
|
NodeCategory.MAXWELLSIM_UTILITIES_OPERATIONS: "Operations",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,25 @@ from . import contracts
|
||||||
|
|
||||||
ICON_SIM_TREE = 'MOD_SIMPLEDEFORM'
|
ICON_SIM_TREE = 'MOD_SIMPLEDEFORM'
|
||||||
|
|
||||||
|
|
||||||
|
class BLENDER_MAXWELL_PT_MaxwellSimTreePanel(bpy.types.Panel):
|
||||||
|
bl_label = "Node Tree Custom Prop"
|
||||||
|
bl_idname = "NODE_PT_custom_prop"
|
||||||
|
bl_space_type = 'NODE_EDITOR'
|
||||||
|
bl_region_type = 'UI'
|
||||||
|
bl_category = 'Item'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.space_data.tree_type == contracts.TreeType.MaxwellSim.value
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
node_tree = context.space_data.node_tree
|
||||||
|
|
||||||
|
layout.prop(node_tree, "preview_collection")
|
||||||
|
layout.prop(node_tree, "non_preview_collection")
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Node Tree Definition
|
# - Node Tree Definition
|
||||||
####################
|
####################
|
||||||
|
@ -12,6 +31,22 @@ class MaxwellSimTree(bpy.types.NodeTree):
|
||||||
bl_label = "Maxwell Sim Editor"
|
bl_label = "Maxwell Sim Editor"
|
||||||
bl_icon = contracts.Icon.MaxwellSimTree
|
bl_icon = contracts.Icon.MaxwellSimTree
|
||||||
|
|
||||||
|
preview_collection: bpy.props.PointerProperty(
|
||||||
|
name="Preview Collection",
|
||||||
|
description="Collection of Blender objects that will be previewed",
|
||||||
|
type=bpy.types.Collection,
|
||||||
|
update=(lambda self, context: self.trigger_updates())
|
||||||
|
)
|
||||||
|
non_preview_collection: bpy.props.PointerProperty(
|
||||||
|
name="Non-Preview Collection",
|
||||||
|
description="Collection of Blender objects that will NOT be previewed",
|
||||||
|
type=bpy.types.Collection,
|
||||||
|
update=(lambda self, context: self.trigger_updates())
|
||||||
|
)
|
||||||
|
|
||||||
|
def trigger_updates(self):
|
||||||
|
pass
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -165,14 +165,19 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
if output_socket_set_key not in socket_set_keys
|
if output_socket_set_key not in socket_set_keys
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def labeller(socket_set_key):
|
||||||
|
return " ".join(
|
||||||
|
word.capitalize()
|
||||||
|
for word in socket_set_key.split("_")
|
||||||
|
)
|
||||||
cls.__annotations__["socket_set"] = bpy.props.EnumProperty(
|
cls.__annotations__["socket_set"] = bpy.props.EnumProperty(
|
||||||
name="",
|
name="",
|
||||||
description="Select a node socket configuration",
|
description="Select a node socket configuration",
|
||||||
items=[
|
items=[
|
||||||
(
|
(
|
||||||
socket_set_key,
|
socket_set_key,
|
||||||
socket_set_key.capitalize(),
|
labeller(socket_set_key),
|
||||||
socket_set_key.capitalize(),
|
labeller(socket_set_key),
|
||||||
)
|
)
|
||||||
for socket_set_key in socket_set_keys
|
for socket_set_key in socket_set_keys
|
||||||
],
|
],
|
||||||
|
@ -217,32 +222,28 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
`NodeTypeProtocol` specification, and initializes each as described
|
`NodeTypeProtocol` specification, and initializes each as described
|
||||||
by user-provided `SocketDefProtocol`s.
|
by user-provided `SocketDefProtocol`s.
|
||||||
"""
|
"""
|
||||||
# Initialize Input Sockets
|
# Create Input Sockets
|
||||||
for socket_name, socket_def in self.input_sockets.items():
|
for socket_name, socket_def in self.input_sockets.items():
|
||||||
self.inputs.new(
|
self.inputs.new(
|
||||||
socket_def.socket_type.value, ## strenum.value => a real str
|
socket_def.socket_type.value,
|
||||||
socket_def.label,
|
socket_def.label,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Retrieve the Blender Socket (bpy.types.NodeSocket)
|
# Create Output Sockets
|
||||||
## We could use self.g_input_bl_socket()...
|
|
||||||
## ...but that would rely on implicit semi-initialized state.
|
|
||||||
bl_socket = self.inputs[
|
|
||||||
self.input_sockets[socket_name].label
|
|
||||||
]
|
|
||||||
|
|
||||||
# Initialize the Socket from the Socket Definition
|
|
||||||
## `bl_socket` knows whether it's an input or output socket...
|
|
||||||
## ...via its `.is_output` attribute.
|
|
||||||
socket_def.init(bl_socket)
|
|
||||||
|
|
||||||
# Initialize Output Sockets
|
|
||||||
for socket_name, socket_def in self.output_sockets.items():
|
for socket_name, socket_def in self.output_sockets.items():
|
||||||
self.outputs.new(
|
self.outputs.new(
|
||||||
socket_def.socket_type.value,
|
socket_def.socket_type.value,
|
||||||
socket_def.label,
|
socket_def.label,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Initialize Sockets
|
||||||
|
for socket_name, socket_def in self.input_sockets.items():
|
||||||
|
bl_socket = self.inputs[
|
||||||
|
self.input_sockets[socket_name].label
|
||||||
|
]
|
||||||
|
socket_def.init(bl_socket)
|
||||||
|
|
||||||
|
for socket_name, socket_def in self.output_sockets.items():
|
||||||
bl_socket = self.outputs[
|
bl_socket = self.outputs[
|
||||||
self.output_sockets[socket_name].label
|
self.output_sockets[socket_name].label
|
||||||
]
|
]
|
||||||
|
@ -274,6 +275,9 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
if self.preset is not None:
|
if self.preset is not None:
|
||||||
sync_selected_preset(self)
|
sync_selected_preset(self)
|
||||||
|
|
||||||
|
if hasattr(self, "init_cb"):
|
||||||
|
self.init_cb()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, ntree: bpy.types.NodeTree) -> bool:
|
def poll(cls, ntree: bpy.types.NodeTree) -> bool:
|
||||||
"""This class method controls whether a node can be instantiated
|
"""This class method controls whether a node can be instantiated
|
||||||
|
@ -366,6 +370,12 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
if hasattr(self, "draw_operators"):
|
if hasattr(self, "draw_operators"):
|
||||||
self.draw_operators(context, layout)
|
self.draw_operators(context, layout)
|
||||||
|
|
||||||
|
if hasattr(self, "draw_props"):
|
||||||
|
self.draw_props(context, layout)
|
||||||
|
|
||||||
|
if hasattr(self, "draw_info"):
|
||||||
|
self.draw_info(context, layout)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Getters
|
# - Socket Getters
|
||||||
####################
|
####################
|
||||||
|
@ -392,13 +402,12 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
return self.inputs[self.input_sockets[input_socket_name].label]
|
return self.inputs[self.input_sockets[input_socket_name].label]
|
||||||
|
|
||||||
elif hasattr(self, "socket_set"):
|
elif hasattr(self, "socket_set"):
|
||||||
# You're on your own, chump
|
|
||||||
|
|
||||||
return self.inputs[next(
|
return self.inputs[next(
|
||||||
socket_def.label
|
socket_def.label
|
||||||
for socket_set, socket_dict in self.input_socket_sets.items()
|
for socket_set, socket_dict in self.input_socket_sets.items()
|
||||||
for socket_name, socket_def in socket_dict.items()
|
for socket_name, socket_def in socket_dict.items()
|
||||||
if socket_name == input_socket_name
|
if socket_name == input_socket_name
|
||||||
|
if socket_set == self.socket_set
|
||||||
)]
|
)]
|
||||||
|
|
||||||
def g_output_bl_socket(
|
def g_output_bl_socket(
|
||||||
|
@ -436,21 +445,21 @@ class MaxwellSimTreeNode(bpy.types.Node):
|
||||||
self,
|
self,
|
||||||
output_bl_socket_name: contracts.BLSocketName,
|
output_bl_socket_name: contracts.BLSocketName,
|
||||||
) -> contracts.SocketName:
|
) -> contracts.SocketName:
|
||||||
|
output_socket_names = [
|
||||||
|
output_socket_name
|
||||||
|
for output_socket_name in self.output_sockets.keys()
|
||||||
|
if self.output_sockets[
|
||||||
|
output_socket_name
|
||||||
|
].label == output_bl_socket_name
|
||||||
|
]
|
||||||
if hasattr(self, "socket_set"):
|
if hasattr(self, "socket_set"):
|
||||||
return next(
|
output_socket_names += [
|
||||||
socket_name
|
socket_name
|
||||||
for socket_set, socket_dict in self.output_socket_sets.items()
|
for socket_set, socket_dict in self.output_socket_sets.items()
|
||||||
for socket_name, socket_def in socket_dict.items()
|
for socket_name, socket_def in socket_dict.items()
|
||||||
if socket_def.label == output_bl_socket_name
|
if socket_def.label == output_bl_socket_name
|
||||||
)
|
]
|
||||||
else:
|
return output_socket_names[0]
|
||||||
return next(
|
|
||||||
output_socket_name
|
|
||||||
for output_socket_name in self.output_sockets.keys()
|
|
||||||
if self.output_sockets[
|
|
||||||
output_socket_name
|
|
||||||
].label == output_bl_socket_name
|
|
||||||
)
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Setters
|
# - Socket Setters
|
||||||
|
|
|
@ -1,5 +1,82 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class BoundBoxNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.BoundBox
|
||||||
|
bl_label = "Bound Box"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"x_pos": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="+x",
|
||||||
|
),
|
||||||
|
"x_neg": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="-x",
|
||||||
|
),
|
||||||
|
"y_pos": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="+y",
|
||||||
|
),
|
||||||
|
"y_neg": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="-y",
|
||||||
|
),
|
||||||
|
"z_pos": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="+z",
|
||||||
|
),
|
||||||
|
"z_neg": sockets.MaxwellBoundFaceSocketDef(
|
||||||
|
label="-z",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"bound": sockets.MaxwellBoundBoxSocketDef(
|
||||||
|
label="Bound",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("bound")
|
||||||
|
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.BoundarySpec:
|
||||||
|
x_pos = self.compute_input("x_pos")
|
||||||
|
x_neg = self.compute_input("x_neg")
|
||||||
|
y_pos = self.compute_input("x_pos")
|
||||||
|
y_neg = self.compute_input("x_neg")
|
||||||
|
z_pos = self.compute_input("x_pos")
|
||||||
|
z_neg = self.compute_input("x_neg")
|
||||||
|
|
||||||
|
return td.BoundarySpec(
|
||||||
|
x=td.Boundary(
|
||||||
|
plus=x_pos,
|
||||||
|
minus=x_neg,
|
||||||
|
),
|
||||||
|
y=td.Boundary(
|
||||||
|
plus=y_pos,
|
||||||
|
minus=y_neg,
|
||||||
|
),
|
||||||
|
z=td.Boundary(
|
||||||
|
plus=z_pos,
|
||||||
|
minus=z_neg,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
BoundBoxNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.BoundBox: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_BOUNDS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
|
from . import unit_system
|
||||||
|
|
||||||
from . import constants
|
from . import constants
|
||||||
from . import lists
|
from . import lists
|
||||||
from . import parameters
|
|
||||||
from . import scene
|
from . import scene
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
*unit_system.BL_REGISTER,
|
||||||
|
|
||||||
*scene.BL_REGISTER,
|
*scene.BL_REGISTER,
|
||||||
*constants.BL_REGISTER,
|
*constants.BL_REGISTER,
|
||||||
*parameters.BL_REGISTER,
|
|
||||||
*lists.BL_REGISTER,
|
*lists.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
|
**unit_system.BL_NODES,
|
||||||
|
|
||||||
**scene.BL_NODES,
|
**scene.BL_NODES,
|
||||||
**constants.BL_NODES,
|
**constants.BL_NODES,
|
||||||
**parameters.BL_NODES,
|
|
||||||
**lists.BL_NODES,
|
**lists.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
from . import number_constant
|
from . import wave_constant
|
||||||
from . import blender_constant
|
|
||||||
from . import physical_constant
|
|
||||||
from . import scientific_constant
|
from . import scientific_constant
|
||||||
|
|
||||||
|
from . import number_constant
|
||||||
|
from . import physical_constant
|
||||||
|
from . import blender_constant
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
*wave_constant.BL_REGISTER,
|
||||||
*scientific_constant.BL_REGISTER,
|
*scientific_constant.BL_REGISTER,
|
||||||
|
|
||||||
*number_constant.BL_REGISTER,
|
*number_constant.BL_REGISTER,
|
||||||
*blender_constant.BL_REGISTER,
|
|
||||||
*physical_constant.BL_REGISTER,
|
*physical_constant.BL_REGISTER,
|
||||||
|
*blender_constant.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
|
**wave_constant.BL_NODES,
|
||||||
**scientific_constant.BL_NODES,
|
**scientific_constant.BL_NODES,
|
||||||
|
|
||||||
**number_constant.BL_NODES,
|
**number_constant.BL_NODES,
|
||||||
**blender_constant.BL_NODES,
|
|
||||||
**physical_constant.BL_NODES,
|
**physical_constant.BL_NODES,
|
||||||
|
**blender_constant.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,68 @@
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class BlenderConstantNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.BlenderConstant
|
||||||
|
|
||||||
|
bl_label = "Blender Constant"
|
||||||
|
#bl_icon = constants.ICON_SIM_INPUT
|
||||||
|
|
||||||
|
input_sockets = {}
|
||||||
|
input_socket_sets = {
|
||||||
|
"object": {
|
||||||
|
"value": sockets.BlenderObjectSocketDef(
|
||||||
|
label="Object",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"collection": {
|
||||||
|
"value": sockets.BlenderCollectionSocketDef(
|
||||||
|
label="Collection",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"value": sockets.BlenderImageSocketDef(
|
||||||
|
label="Image",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"value": sockets.BlenderVolumeSocketDef(
|
||||||
|
label="Volume",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"value": sockets.BlenderTextSocketDef(
|
||||||
|
label="Text",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"geonodes": {
|
||||||
|
"value": sockets.BlenderGeoNodesSocketDef(
|
||||||
|
label="GeoNodes",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets = {}
|
||||||
|
output_socket_sets = input_socket_sets
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Callbacks
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("value")
|
||||||
|
def compute_value(self: contracts.NodeTypeProtocol) -> typ.Any:
|
||||||
|
return self.compute_input("value")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
BlenderConstantNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.BlenderConstant: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,11 @@ class NumberConstantNode(base.MaxwellSimTreeNode):
|
||||||
|
|
||||||
input_sockets = {}
|
input_sockets = {}
|
||||||
input_socket_sets = {
|
input_socket_sets = {
|
||||||
|
"integer": {
|
||||||
|
"value": sockets.IntegerNumberSocketDef(
|
||||||
|
label="Integer",
|
||||||
|
),
|
||||||
|
},
|
||||||
"real": {
|
"real": {
|
||||||
"value": sockets.RealNumberSocketDef(
|
"value": sockets.RealNumberSocketDef(
|
||||||
label="Real",
|
label="Real",
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
vac_speed_of_light = (
|
||||||
|
sc.constants.speed_of_light
|
||||||
|
* spu.meter/spu.second
|
||||||
|
)
|
||||||
|
|
||||||
|
class WaveConstantNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.WaveConstant
|
||||||
|
|
||||||
|
bl_label = "Wave Constant"
|
||||||
|
|
||||||
|
input_sockets = {}
|
||||||
|
input_socket_sets = {
|
||||||
|
"vac_wl": {
|
||||||
|
"vac_wl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"freq": {
|
||||||
|
"freq": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"vac_wl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
"freq": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_socket_sets = {}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Callbacks
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("vac_wl")
|
||||||
|
def compute_vac_wl(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
if self.socket_set == "vac_wl":
|
||||||
|
return self.compute_input("vac_wl")
|
||||||
|
|
||||||
|
elif self.socket_set == "freq":
|
||||||
|
freq = self.compute_input("freq")
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / freq,
|
||||||
|
spu.meter,
|
||||||
|
)
|
||||||
|
|
||||||
|
raise ValueError("No valid socket set.")
|
||||||
|
|
||||||
|
@base.computes_output_socket("freq")
|
||||||
|
def compute_freq(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
if self.socket_set == "vac_wl":
|
||||||
|
vac_wl = self.compute_input("vac_wl")
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / vac_wl,
|
||||||
|
spu.hertz,
|
||||||
|
)
|
||||||
|
|
||||||
|
elif self.socket_set == "freq":
|
||||||
|
return self.compute_input("freq")
|
||||||
|
|
||||||
|
raise ValueError("No valid socket set.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
WaveConstantNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.WaveConstant: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
from . import number_parameter
|
|
||||||
from . import physical_parameter
|
|
||||||
|
|
||||||
BL_REGISTER = [
|
|
||||||
*number_parameter.BL_REGISTER,
|
|
||||||
*physical_parameter.BL_REGISTER,
|
|
||||||
]
|
|
||||||
BL_NODES = {
|
|
||||||
**number_parameter.BL_NODES,
|
|
||||||
**physical_parameter.BL_NODES,
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class PhysicalUnitSystemNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.UnitSystem
|
||||||
|
|
||||||
|
bl_label = "Unit System Constant"
|
||||||
|
|
||||||
|
input_sockets = {
|
||||||
|
"unit_system": sockets.PhysicalUnitSystemSocketDef(
|
||||||
|
label="Unit System",
|
||||||
|
show_by_default=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"unit_system": sockets.PhysicalUnitSystemSocketDef(
|
||||||
|
label="Unit System",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Callbacks
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("unit_system")
|
||||||
|
def compute_value(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
return self.compute_input("unit_system")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
PhysicalUnitSystemNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.UnitSystem: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_INPUTS
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,6 +1,80 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class DrudeLorentzMediumNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.DrudeLorentzMedium
|
||||||
|
|
||||||
|
bl_label = "Drude-Lorentz Medium"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"eps_inf": sockets.RealNumberSocketDef(
|
||||||
|
label=f"εr_∞",
|
||||||
|
),
|
||||||
|
} | {
|
||||||
|
f"del_eps{i}": sockets.RealNumberSocketDef(
|
||||||
|
label=f"Δεr_{i}",
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
} | {
|
||||||
|
f"f{i}": sockets.PhysicalFreqSocketDef(
|
||||||
|
label=f"f_{i}",
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
} | {
|
||||||
|
f"delta{i}": sockets.PhysicalFreqSocketDef(
|
||||||
|
label=f"δ_{i}",
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"medium": sockets.MaxwellMediumSocketDef(
|
||||||
|
label="Medium"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("medium")
|
||||||
|
def compute_medium(self: contracts.NodeTypeProtocol) -> td.Sellmeier:
|
||||||
|
## Retrieval
|
||||||
|
return td.Lorentz(
|
||||||
|
eps_inf=self.compute_input(f"eps_inf"),
|
||||||
|
coeffs = [
|
||||||
|
(
|
||||||
|
self.compute_input(f"del_eps{i}"),
|
||||||
|
spu.convert_to(
|
||||||
|
self.compute_input(f"f{i}"),
|
||||||
|
spu.hertz,
|
||||||
|
) / spu.hertz,
|
||||||
|
spu.convert_to(
|
||||||
|
self.compute_input(f"delta{i}"),
|
||||||
|
spu.hertz,
|
||||||
|
) / spu.hertz,
|
||||||
|
)
|
||||||
|
for i in [1, 2, 3]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
DrudeLorentzMediumNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.DrudeLorentzMedium: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_MEDIUMS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,161 @@
|
||||||
|
import bpy
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import numpy as np
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from .....utils import extra_sympy_units as spuex
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class ExperimentOperator00(bpy.types.Operator):
|
||||||
|
bl_idname = "blender_maxwell.experiment_operator_00"
|
||||||
|
bl_label = "exp"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
node = context.node
|
||||||
|
node.invoke_matplotlib_and_update_image()
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class LibraryMediumNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.LibraryMedium
|
||||||
|
|
||||||
|
bl_label = "Library Medium"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {}
|
||||||
|
output_sockets = {
|
||||||
|
"medium": sockets.MaxwellMediumSocketDef(
|
||||||
|
label="Medium"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
material: bpy.props.EnumProperty(
|
||||||
|
name="",
|
||||||
|
description="",
|
||||||
|
#icon="NODE_MATERIAL",
|
||||||
|
items=[
|
||||||
|
(
|
||||||
|
mat_key,
|
||||||
|
td.material_library[mat_key].name,
|
||||||
|
", ".join([
|
||||||
|
ref.journal
|
||||||
|
for ref in td.material_library[mat_key].variants[
|
||||||
|
td.material_library[mat_key].default
|
||||||
|
].reference
|
||||||
|
])
|
||||||
|
)
|
||||||
|
for mat_key in td.material_library
|
||||||
|
if mat_key != "graphene" ## For some reason, it's unique...
|
||||||
|
],
|
||||||
|
default="Au",
|
||||||
|
update=(lambda self,context: self.update()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_props(self, context, layout):
|
||||||
|
layout.prop(self, "material", text="")
|
||||||
|
|
||||||
|
def draw_info(self, context, layout):
|
||||||
|
layout.operator(ExperimentOperator00.bl_idname, text="Experiment")
|
||||||
|
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
||||||
|
|
||||||
|
mat = td.material_library[self.material]
|
||||||
|
freq_range = [
|
||||||
|
spu.convert_to(
|
||||||
|
val * spu.hertz,
|
||||||
|
spuex.terahertz,
|
||||||
|
) / spuex.terahertz
|
||||||
|
for val in mat.medium.frequency_range
|
||||||
|
]
|
||||||
|
nm_range = [
|
||||||
|
spu.convert_to(
|
||||||
|
vac_speed_of_light / (val * spu.hertz),
|
||||||
|
spu.nanometer,
|
||||||
|
) / spu.nanometer
|
||||||
|
for val in mat.medium.frequency_range
|
||||||
|
]
|
||||||
|
|
||||||
|
layout.label(text=f"nm: [{nm_range[1].n(2)}, {nm_range[0].n(2)}]")
|
||||||
|
layout.label(text=f"THz: [{freq_range[0].n(2)}, {freq_range[1].n(2)}]")
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("medium")
|
||||||
|
def compute_medium(self: contracts.NodeTypeProtocol) -> td.AbstractMedium:
|
||||||
|
return td.material_library[self.material].medium
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Experiment
|
||||||
|
####################
|
||||||
|
def invoke_matplotlib_and_update_image(self):
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
mat = td.material_library[self.material]
|
||||||
|
|
||||||
|
aspect_ratio = 1.0
|
||||||
|
for area in bpy.context.screen.areas:
|
||||||
|
if area.type == 'IMAGE_EDITOR':
|
||||||
|
width = area.width
|
||||||
|
height = area.height
|
||||||
|
aspect_ratio = width / height
|
||||||
|
|
||||||
|
# Generate a plot with matplotlib
|
||||||
|
fig_width = 6
|
||||||
|
fig_height = fig_width / aspect_ratio
|
||||||
|
fig, ax = plt.subplots(figsize=(fig_width, fig_height))
|
||||||
|
ax.set_aspect(aspect_ratio)
|
||||||
|
mat.medium.plot(
|
||||||
|
np.linspace(*mat.medium.frequency_range[:2], 50),
|
||||||
|
ax=ax,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Save the plot to a temporary file
|
||||||
|
temp_plot_file = bpy.path.abspath('//temp_plot.png')
|
||||||
|
fig.savefig(temp_plot_file, bbox_inches='tight')
|
||||||
|
plt.close(fig) # Close the figure to free up memory
|
||||||
|
|
||||||
|
# Load or reload the image in Blender
|
||||||
|
if "matplotlib_plot" in bpy.data.images:
|
||||||
|
image = bpy.data.images["matplotlib_plot"]
|
||||||
|
image.reload()
|
||||||
|
else:
|
||||||
|
image = bpy.data.images.load(temp_plot_file)
|
||||||
|
image.name = "matplotlib_plot"
|
||||||
|
|
||||||
|
# Write the plot to an image datablock in Blender
|
||||||
|
for area in bpy.context.screen.areas:
|
||||||
|
if area.type == 'IMAGE_EDITOR':
|
||||||
|
for space in area.spaces:
|
||||||
|
if space.type == 'IMAGE_EDITOR':
|
||||||
|
space.image = image
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
ExperimentOperator00,
|
||||||
|
LibraryMediumNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.LibraryMedium: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_MEDIUMS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ from pathlib import Path
|
||||||
import bpy
|
import bpy
|
||||||
import sympy as sp
|
import sympy as sp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
import tidy3d as td
|
||||||
|
|
||||||
from .... import contracts
|
from .... import contracts
|
||||||
from .... import sockets
|
from .... import sockets
|
||||||
|
@ -26,6 +27,19 @@ class JSONFileExporterPrintJSON(bpy.types.Operator):
|
||||||
print(node.linked_data_as_json())
|
print(node.linked_data_as_json())
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class JSONFileExporterMeshData(bpy.types.Operator):
|
||||||
|
bl_idname = "blender_maxwell.json_file_exporter_mesh_data"
|
||||||
|
bl_label = "Print any mesh data linked into a JSONFileExporterNode."
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
node = context.node
|
||||||
|
print(node.linked_mesh_data())
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
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."
|
||||||
|
@ -69,6 +83,7 @@ class JSONFileExporterNode(base.MaxwellSimTreeNode):
|
||||||
) -> None:
|
) -> None:
|
||||||
layout.operator(JSONFileExporterPrintJSON.bl_idname, text="Print")
|
layout.operator(JSONFileExporterPrintJSON.bl_idname, text="Print")
|
||||||
layout.operator(JSONFileExporterSaveJSON.bl_idname, text="Save")
|
layout.operator(JSONFileExporterSaveJSON.bl_idname, text="Save")
|
||||||
|
layout.operator(JSONFileExporterMeshData.bl_idname, text="Mesh Info")
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Methods
|
# - Methods
|
||||||
|
@ -85,10 +100,16 @@ class JSONFileExporterNode(base.MaxwellSimTreeNode):
|
||||||
elif isinstance(data, pyd.BaseModel):
|
elif isinstance(data, pyd.BaseModel):
|
||||||
return data.model_dump_json()
|
return data.model_dump_json()
|
||||||
|
|
||||||
# Finally: Try json.dumps (might fail)
|
|
||||||
else:
|
else:
|
||||||
json.dumps(data)
|
json.dumps(data)
|
||||||
|
|
||||||
|
def linked_mesh_data(self) -> str | None:
|
||||||
|
if self.g_input_bl_socket("data").is_linked:
|
||||||
|
data: typ.Any = self.compute_input("data")
|
||||||
|
|
||||||
|
if isinstance(data, td.Structure):
|
||||||
|
return data.geometry
|
||||||
|
|
||||||
def export_data_as_json(self) -> None:
|
def export_data_as_json(self) -> None:
|
||||||
if (data := self.linked_data_as_json()):
|
if (data := self.linked_data_as_json()):
|
||||||
data_dict = json.loads(data)
|
data_dict = json.loads(data)
|
||||||
|
@ -101,8 +122,9 @@ class JSONFileExporterNode(base.MaxwellSimTreeNode):
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
JSONFileExporterPrintJSON,
|
JSONFileExporterPrintJSON,
|
||||||
JSONFileExporterNode,
|
JSONFileExporterMeshData,
|
||||||
JSONFileExporterSaveJSON,
|
JSONFileExporterSaveJSON,
|
||||||
|
JSONFileExporterNode,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
contracts.NodeType.JSONFileExporter: (
|
contracts.NodeType.JSONFileExporter: (
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
from . import viewer_3d
|
||||||
from . import value_viewer
|
from . import value_viewer
|
||||||
from . import console_viewer
|
from . import console_viewer
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
*viewer_3d.BL_REGISTER,
|
||||||
*value_viewer.BL_REGISTER,
|
*value_viewer.BL_REGISTER,
|
||||||
*console_viewer.BL_REGISTER,
|
*console_viewer.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
|
**viewer_3d.BL_NODES,
|
||||||
**value_viewer.BL_NODES,
|
**value_viewer.BL_NODES,
|
||||||
**console_viewer.BL_NODES,
|
**console_viewer.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import typing as typ
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import pydantic as pyd
|
||||||
|
import tidy3d as td
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
INTERNAL_GEONODES = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Node
|
||||||
|
####################
|
||||||
|
class Viewer3DNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.Viewer3D
|
||||||
|
|
||||||
|
bl_label = "3D Viewer"
|
||||||
|
|
||||||
|
input_sockets = {
|
||||||
|
"data": sockets.AnySocketDef(
|
||||||
|
label="Data",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Update
|
||||||
|
####################
|
||||||
|
def update_cb(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
Viewer3DNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.Viewer3D: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_OUTPUTS_VIEWERS
|
||||||
|
)
|
||||||
|
}
|
|
@ -19,8 +19,8 @@ class FDTDSimNode(base.MaxwellSimTreeNode):
|
||||||
"run_time": sockets.PhysicalTimeSocketDef(
|
"run_time": sockets.PhysicalTimeSocketDef(
|
||||||
label="Run Time",
|
label="Run Time",
|
||||||
),
|
),
|
||||||
"size": sockets.PhysicalSize3DSocketDef(
|
"domain": sockets.PhysicalSize3DSocketDef(
|
||||||
label="Size",
|
label="Domain",
|
||||||
),
|
),
|
||||||
"ambient_medium": sockets.MaxwellMediumSocketDef(
|
"ambient_medium": sockets.MaxwellMediumSocketDef(
|
||||||
label="Ambient Medium",
|
label="Ambient Medium",
|
||||||
|
@ -37,7 +37,7 @@ class FDTDSimNode(base.MaxwellSimTreeNode):
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"fdtd_sim": sockets.MaxwellFDTDSimSocketDef(
|
"fdtd_sim": sockets.MaxwellFDTDSimSocketDef(
|
||||||
label="Medium",
|
label="FDTD Sim",
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,17 +47,17 @@ class FDTDSimNode(base.MaxwellSimTreeNode):
|
||||||
@base.computes_output_socket("fdtd_sim")
|
@base.computes_output_socket("fdtd_sim")
|
||||||
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Simulation:
|
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Simulation:
|
||||||
_run_time = self.compute_input("run_time")
|
_run_time = self.compute_input("run_time")
|
||||||
_size = self.compute_input("size")
|
_domain = self.compute_input("domain")
|
||||||
ambient_medium = self.compute_input("ambient_medium")
|
ambient_medium = self.compute_input("ambient_medium")
|
||||||
structures = [self.compute_input("structure")]
|
structures = [self.compute_input("structure")]
|
||||||
sources = [self.compute_input("source")]
|
sources = [self.compute_input("source")]
|
||||||
bound = self.compute_input("bound")
|
bound = self.compute_input("bound")
|
||||||
|
|
||||||
run_time = spu.convert_to(_run_time, spu.second) / spu.second
|
run_time = spu.convert_to(_run_time, spu.second) / spu.second
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
domain = tuple(spu.convert_to(_domain, spu.um) / spu.um)
|
||||||
|
|
||||||
return td.Simulation(
|
return td.Simulation(
|
||||||
size=size,
|
size=domain,
|
||||||
medium=ambient_medium,
|
medium=ambient_medium,
|
||||||
structures=structures,
|
structures=structures,
|
||||||
sources=sources,
|
sources=sources,
|
||||||
|
|
|
@ -1,6 +1,94 @@
|
||||||
|
import math
|
||||||
|
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class PlaneWaveSourceNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.PlaneWaveSource
|
||||||
|
|
||||||
|
bl_label = "Plane Wave Source"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"temporal_shape": sockets.MaxwellTemporalShapeSocketDef(
|
||||||
|
label="Temporal Shape",
|
||||||
|
),
|
||||||
|
"center": sockets.PhysicalPoint3DSocketDef(
|
||||||
|
label="Center",
|
||||||
|
),
|
||||||
|
"size": sockets.PhysicalSize3DSocketDef(
|
||||||
|
label="Size",
|
||||||
|
),
|
||||||
|
"direction": sockets.BoolSocketDef(
|
||||||
|
label="+ Direction?",
|
||||||
|
default_value=True,
|
||||||
|
),
|
||||||
|
"angle_theta": sockets.PhysicalAngleSocketDef(
|
||||||
|
label="θ",
|
||||||
|
),
|
||||||
|
"angle_phi": sockets.PhysicalAngleSocketDef(
|
||||||
|
label="φ",
|
||||||
|
),
|
||||||
|
"angle_pol": sockets.PhysicalAngleSocketDef(
|
||||||
|
label="Pol Angle",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"source": sockets.MaxwellSourceSocketDef(
|
||||||
|
label="Source",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("source")
|
||||||
|
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
||||||
|
temporal_shape = self.compute_input("temporal_shape")
|
||||||
|
_center = self.compute_input("center")
|
||||||
|
_size = self.compute_input("size")
|
||||||
|
_direction = self.compute_input("direction")
|
||||||
|
_angle_theta = self.compute_input("angle_theta")
|
||||||
|
_angle_phi = self.compute_input("angle_phi")
|
||||||
|
_angle_pol = self.compute_input("angle_pol")
|
||||||
|
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
size = tuple(
|
||||||
|
0 if val == 1.0 else math.inf
|
||||||
|
for val in spu.convert_to(_size, spu.um) / spu.um
|
||||||
|
)
|
||||||
|
angle_theta = spu.convert_to(_angle_theta, spu.rad) / spu.rad
|
||||||
|
angle_phi = spu.convert_to(_angle_phi, spu.rad) / spu.rad
|
||||||
|
angle_pol = spu.convert_to(_angle_pol, spu.rad) / spu.rad
|
||||||
|
|
||||||
|
return td.PlaneWave(
|
||||||
|
center=center,
|
||||||
|
size=size,
|
||||||
|
source_time=temporal_shape,
|
||||||
|
direction="+" if _direction else "-",
|
||||||
|
angle_theta=angle_theta,
|
||||||
|
angle_phi=angle_phi,
|
||||||
|
pol_angle=angle_pol,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
PlaneWaveSourceNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.PlaneWaveSource: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_SOURCES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -16,15 +16,19 @@ class PointDipoleSourceNode(base.MaxwellSimTreeNode):
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
#"polarization": sockets.PhysicalPolSocketDef(
|
"polarization": sockets.PhysicalPolSocketDef(
|
||||||
# label="Polarization",
|
label="Polarization",
|
||||||
#), ## TODO: Exactly how to go about this...
|
),
|
||||||
"temporal_shape": sockets.MaxwellTemporalShapeSocketDef(
|
"temporal_shape": sockets.MaxwellTemporalShapeSocketDef(
|
||||||
label="Temporal Shape",
|
label="Temporal Shape",
|
||||||
),
|
),
|
||||||
"center": sockets.PhysicalPoint3DSocketDef(
|
"center": sockets.PhysicalPoint3DSocketDef(
|
||||||
label="Center",
|
label="Center",
|
||||||
),
|
),
|
||||||
|
"interpolate": sockets.BoolSocketDef(
|
||||||
|
label="Interpolate",
|
||||||
|
default_value=True,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"source": sockets.MaxwellSourceSocketDef(
|
"source": sockets.MaxwellSourceSocketDef(
|
||||||
|
@ -37,19 +41,18 @@ class PointDipoleSourceNode(base.MaxwellSimTreeNode):
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket("source")
|
@base.computes_output_socket("source")
|
||||||
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
||||||
|
polarization = self.compute_input("polarization")
|
||||||
temporal_shape = self.compute_input("temporal_shape")
|
temporal_shape = self.compute_input("temporal_shape")
|
||||||
|
|
||||||
_center = self.compute_input("center")
|
_center = self.compute_input("center")
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
interpolate = self.compute_input("interpolate")
|
||||||
|
|
||||||
cheating_pol = "Ex"
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
## TODO: Fix
|
|
||||||
|
|
||||||
return td.PointDipole(
|
return td.PointDipole(
|
||||||
center=center,
|
center=center,
|
||||||
source_time=temporal_shape,
|
source_time=temporal_shape,
|
||||||
interpolate=True,
|
interpolate=interpolate,
|
||||||
polarization=cheating_pol,
|
polarization=polarization,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,77 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class ContinuousWaveTemporalShapeNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.ContinuousWaveTemporalShape
|
||||||
|
|
||||||
|
bl_label = "Continuous Wave Temporal Shape"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
#"amplitude": sockets.RealNumberSocketDef(
|
||||||
|
# label="Temporal Shape",
|
||||||
|
#), ## Should have a unit of some kind...
|
||||||
|
"phase": sockets.PhysicalAngleSocketDef(
|
||||||
|
label="Phase",
|
||||||
|
),
|
||||||
|
"freq_center": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq Center",
|
||||||
|
),
|
||||||
|
"freq_std": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq STD",
|
||||||
|
),
|
||||||
|
"time_delay_rel_ang_freq": sockets.RealNumberSocketDef(
|
||||||
|
label="Time Delay rel. Ang. Freq",
|
||||||
|
default_value=5.0,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"temporal_shape": sockets.MaxwellTemporalShapeSocketDef(
|
||||||
|
label="Temporal Shape",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("temporal_shape")
|
||||||
|
def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole:
|
||||||
|
_phase = self.compute_input("phase")
|
||||||
|
_freq_center = self.compute_input("freq_center")
|
||||||
|
_freq_std = self.compute_input("freq_std")
|
||||||
|
time_delay_rel_ang_freq = self.compute_input("time_delay_rel_ang_freq")
|
||||||
|
|
||||||
|
cheating_amplitude = 1.0
|
||||||
|
phase = spu.convert_to(_phase, spu.radian) / spu.radian
|
||||||
|
freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz
|
||||||
|
freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz
|
||||||
|
|
||||||
|
return td.ContinuousWave(
|
||||||
|
amplitude=cheating_amplitude,
|
||||||
|
phase=phase,
|
||||||
|
freq0=freq_center,
|
||||||
|
fwidth=freq_std,
|
||||||
|
offset=time_delay_rel_ang_freq,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
ContinuousWaveTemporalShapeNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.ContinuousWaveTemporalShape: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_SOURCES_TEMPORALSHAPES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ class GaussianPulseTemporalShapeNode(base.MaxwellSimTreeNode):
|
||||||
),
|
),
|
||||||
"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,
|
||||||
),
|
),
|
||||||
"remove_dc_component": sockets.BoolSocketDef(
|
"remove_dc_component": sockets.BoolSocketDef(
|
||||||
label="Remove DC",
|
label="Remove DC",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import sympy as sp
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
from bpy_types import bpy_types
|
||||||
import bmesh
|
import bmesh
|
||||||
|
|
||||||
from ... import contracts
|
from ... import contracts
|
||||||
|
@ -12,6 +13,26 @@ from .. import base
|
||||||
|
|
||||||
GEONODES_MODIFIER_NAME = "BLMaxwell_GeoNodes"
|
GEONODES_MODIFIER_NAME = "BLMaxwell_GeoNodes"
|
||||||
|
|
||||||
|
# Monkey-Patch Sympy Types
|
||||||
|
## TODO: This needs to be a more generic thing, this isn't the only place we're setting blender interface values.
|
||||||
|
def parse_scalar(scalar):
|
||||||
|
if isinstance(scalar, sp.Integer):
|
||||||
|
return int(scalar)
|
||||||
|
elif isinstance(scalar, sp.Float):
|
||||||
|
return float(scalar)
|
||||||
|
elif isinstance(scalar, sp.Rational):
|
||||||
|
return float(scalar)
|
||||||
|
elif isinstance(scalar, sp.Expr):
|
||||||
|
return float(scalar.n())
|
||||||
|
|
||||||
|
return scalar
|
||||||
|
|
||||||
|
def parse_bl_to_sp(scalar):
|
||||||
|
if isinstance(scalar, bpy_types.bpy_prop_array):
|
||||||
|
return sp.Matrix(tuple(scalar))
|
||||||
|
|
||||||
|
return scalar
|
||||||
|
|
||||||
class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
node_type = contracts.NodeType.GeoNodesStructure
|
node_type = contracts.NodeType.GeoNodesStructure
|
||||||
bl_label = "GeoNodes Structure"
|
bl_label = "GeoNodes Structure"
|
||||||
|
@ -21,12 +42,15 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
# - Sockets
|
# - Sockets
|
||||||
####################
|
####################
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
|
"preview_target": sockets.BlenderPreviewTargetSocketDef(
|
||||||
|
label="Preview Target",
|
||||||
|
),
|
||||||
|
"blender_unit_system": sockets.PhysicalUnitSystemSocketDef(
|
||||||
|
label="Blender Units",
|
||||||
|
),
|
||||||
"medium": sockets.MaxwellMediumSocketDef(
|
"medium": sockets.MaxwellMediumSocketDef(
|
||||||
label="Medium",
|
label="Medium",
|
||||||
),
|
),
|
||||||
"object": sockets.BlenderObjectSocketDef(
|
|
||||||
label="Object",
|
|
||||||
),
|
|
||||||
"geo_nodes": sockets.BlenderGeoNodesSocketDef(
|
"geo_nodes": sockets.BlenderGeoNodesSocketDef(
|
||||||
label="GeoNodes",
|
label="GeoNodes",
|
||||||
),
|
),
|
||||||
|
@ -50,7 +74,10 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
|
|
||||||
# Triangulate Object Mesh
|
# Triangulate Object Mesh
|
||||||
bmesh_mesh = bmesh.new()
|
bmesh_mesh = bmesh.new()
|
||||||
bmesh_mesh.from_mesh(bl_object.data)
|
bmesh_mesh.from_object(
|
||||||
|
bl_object,
|
||||||
|
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")
|
||||||
|
@ -75,8 +102,13 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
####################
|
####################
|
||||||
# - Update Function
|
# - Update Function
|
||||||
####################
|
####################
|
||||||
|
def free(self) -> None:
|
||||||
|
bl_socket = self.g_input_bl_socket("preview_target")
|
||||||
|
|
||||||
|
bl_socket.free()
|
||||||
|
|
||||||
def update_cb(self) -> None:
|
def update_cb(self) -> None:
|
||||||
bl_object = self.compute_input("object")
|
bl_object = self.compute_input("preview_target")
|
||||||
if bl_object is None: return
|
if bl_object is None: return
|
||||||
|
|
||||||
geo_nodes = self.compute_input("geo_nodes")
|
geo_nodes = self.compute_input("geo_nodes")
|
||||||
|
@ -91,9 +123,12 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
):
|
):
|
||||||
if idx == 0: continue ## Always-on "Geometry" Input (from Object)
|
if idx == 0: continue ## Always-on "Geometry" Input (from Object)
|
||||||
|
|
||||||
|
# Retrieve Input Socket
|
||||||
bl_socket = self.inputs[
|
bl_socket = self.inputs[
|
||||||
interface_item.name
|
interface_item.name
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Retrieve Linked/Unlinked Input Socket Value
|
||||||
if bl_socket.is_linked:
|
if bl_socket.is_linked:
|
||||||
linked_bl_socket = bl_socket.links[0].from_socket
|
linked_bl_socket = bl_socket.links[0].from_socket
|
||||||
linked_bl_node = bl_socket.links[0].from_node
|
linked_bl_node = bl_socket.links[0].from_node
|
||||||
|
@ -103,13 +138,33 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
) ## What a bunch of spaghetti
|
) ## What a bunch of spaghetti
|
||||||
else:
|
else:
|
||||||
val = self.inputs[
|
val = bl_socket.default_value
|
||||||
interface_item.name
|
|
||||||
].default_value
|
# Retrieve Unit-System Corrected Modifier Value
|
||||||
|
bl_unit_system = self.compute_input("blender_unit_system")
|
||||||
|
|
||||||
|
socket_type = contracts.SocketType[
|
||||||
|
bl_socket.bl_idname.removesuffix("SocketType")
|
||||||
|
]
|
||||||
|
if socket_type in bl_unit_system:
|
||||||
|
unitless_val = spu.convert_to(
|
||||||
|
val,
|
||||||
|
bl_unit_system[socket_type],
|
||||||
|
) / bl_unit_system[socket_type]
|
||||||
|
else:
|
||||||
|
unitless_val = val
|
||||||
|
|
||||||
|
if isinstance(unitless_val, sp.matrices.MatrixBase):
|
||||||
|
unitless_val = tuple(
|
||||||
|
parse_scalar(scalar)
|
||||||
|
for scalar in unitless_val
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
unitless_val = parse_scalar(unitless_val)
|
||||||
|
|
||||||
# Conservatively Set Differing Values
|
# Conservatively Set Differing Values
|
||||||
if bl_modifier[interface_item.identifier] != val:
|
if bl_modifier[interface_item.identifier] != unitless_val:
|
||||||
bl_modifier[interface_item.identifier] = val
|
bl_modifier[interface_item.identifier] = unitless_val
|
||||||
|
|
||||||
# Update DepGraph
|
# Update DepGraph
|
||||||
bl_object.data.update()
|
bl_object.data.update()
|
||||||
|
@ -134,23 +189,77 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
self.inputs.remove(bl_socket)
|
self.inputs.remove(bl_socket)
|
||||||
|
|
||||||
# Query for Blender Object / Geo Nodes
|
# Query for Blender Object / Geo Nodes
|
||||||
bl_object = self.compute_input("object")
|
bl_object = self.compute_input("preview_target")
|
||||||
if bl_object is None: return
|
if bl_object is None: return
|
||||||
## TODO: Make object? Gray out geonodes if object not defined?
|
|
||||||
|
|
||||||
|
# Remove Existing GeoNodes Modifier
|
||||||
|
if GEONODES_MODIFIER_NAME in bl_object.modifiers:
|
||||||
|
modifier_to_remove = bl_object.modifiers[GEONODES_MODIFIER_NAME]
|
||||||
|
bl_object.modifiers.remove(modifier_to_remove)
|
||||||
|
|
||||||
|
# Retrieve GeoNodes Tree
|
||||||
geo_nodes = self.compute_input("geo_nodes")
|
geo_nodes = self.compute_input("geo_nodes")
|
||||||
if geo_nodes is None: return
|
if geo_nodes is None: return
|
||||||
|
|
||||||
|
|
||||||
# Add Non-Static Sockets from GeoNodes
|
# Add Non-Static Sockets from GeoNodes
|
||||||
for bl_socket_name, bl_socket in geo_nodes.interface.items_tree.items():
|
for bl_socket_name, bl_socket in geo_nodes.interface.items_tree.items():
|
||||||
# For now, don't allow Geometry inputs.
|
# For now, don't allow Geometry inputs.
|
||||||
if bl_socket.socket_type == "NodeSocketGeometry": continue
|
if bl_socket.socket_type == "NodeSocketGeometry": continue
|
||||||
|
|
||||||
self.inputs.new(
|
# Establish Dimensions of GeoNodes Input Sockets
|
||||||
contracts.BLNodeSocket_to_SocketType[bl_socket.socket_type],
|
if (
|
||||||
bl_socket_name,
|
bl_socket.description.startswith("2D")
|
||||||
)
|
):
|
||||||
|
dimensions = 2
|
||||||
|
elif (
|
||||||
|
bl_socket.socket_type.startswith("NodeSocketVector")
|
||||||
|
or bl_socket.socket_type.startswith("NodeSocketColor")
|
||||||
|
or bl_socket.socket_type.startswith("NodeSocketRotation")
|
||||||
|
):
|
||||||
|
dimensions = 3
|
||||||
|
else:
|
||||||
|
dimensions = 1
|
||||||
|
|
||||||
|
# Choose Socket via. Description Hint (if exists)
|
||||||
|
if (
|
||||||
|
":" in bl_socket.description
|
||||||
|
and "(" in (desc_hint := bl_socket.description.split(":")[0])
|
||||||
|
and ")" in desc_hint
|
||||||
|
):
|
||||||
|
for tag in contracts.BLNodeSocket_to_SocketType_by_desc[
|
||||||
|
dimensions
|
||||||
|
]:
|
||||||
|
if desc_hint.startswith(tag):
|
||||||
|
self.inputs.new(
|
||||||
|
contracts.BLNodeSocket_to_SocketType_by_desc[
|
||||||
|
dimensions
|
||||||
|
][tag],
|
||||||
|
bl_socket_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if len([
|
||||||
|
(unit := _unit)
|
||||||
|
for _unit in contracts.SocketType_to_units[
|
||||||
|
contracts.SocketType[
|
||||||
|
self.inputs[bl_socket_name].bl_idname.removesuffix("SocketType")
|
||||||
|
]
|
||||||
|
]["values"].values()
|
||||||
|
if desc_hint[
|
||||||
|
desc_hint.find("(")+1 : desc_hint.find(")")
|
||||||
|
] == str(_unit)
|
||||||
|
]) > 0:
|
||||||
|
self.inputs[bl_socket_name].unit = unit
|
||||||
|
|
||||||
|
elif bl_socket.socket_type in contracts.BLNodeSocket_to_SocketType[
|
||||||
|
dimensions
|
||||||
|
]:
|
||||||
|
self.inputs.new(
|
||||||
|
contracts.BLNodeSocket_to_SocketType[
|
||||||
|
dimensions
|
||||||
|
][bl_socket.socket_type],
|
||||||
|
bl_socket_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Create New GeoNodes Modifier
|
# Create New GeoNodes Modifier
|
||||||
if GEONODES_MODIFIER_NAME not in bl_object.modifiers:
|
if GEONODES_MODIFIER_NAME not in bl_object.modifiers:
|
||||||
|
@ -160,7 +269,27 @@ class GeoNodesStructureNode(base.MaxwellSimTreeNode):
|
||||||
)
|
)
|
||||||
modifier.node_group = geo_nodes
|
modifier.node_group = geo_nodes
|
||||||
|
|
||||||
self.update()
|
# Set Default Values
|
||||||
|
for interface_item in geo_nodes.interface.items_tree.values():
|
||||||
|
if (
|
||||||
|
interface_item.name in self.inputs
|
||||||
|
and hasattr(interface_item, "default_value")
|
||||||
|
):
|
||||||
|
bl_socket = self.inputs[
|
||||||
|
interface_item.name
|
||||||
|
]
|
||||||
|
if hasattr(bl_socket, "use_units"):
|
||||||
|
bl_unit_system = self.compute_input("blender_unit_system")
|
||||||
|
socket_type = contracts.SocketType[
|
||||||
|
bl_socket.bl_idname.removesuffix("SocketType")
|
||||||
|
]
|
||||||
|
|
||||||
|
bl_socket.default_value = (
|
||||||
|
parse_bl_to_sp(interface_item.default_value)
|
||||||
|
* bl_unit_system[socket_type]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bl_socket.default_value = parse_bl_to_sp(interface_item.default_value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,10 @@ class ObjectStructureNode(base.MaxwellSimTreeNode):
|
||||||
|
|
||||||
# Triangulate Object Mesh
|
# Triangulate Object Mesh
|
||||||
bmesh_mesh = bmesh.new()
|
bmesh_mesh = bmesh.new()
|
||||||
bmesh_mesh.from_mesh(bl_object.data)
|
bmesh_mesh.from_object(
|
||||||
|
bl_object,
|
||||||
|
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")
|
||||||
|
@ -62,7 +65,6 @@ class ObjectStructureNode(base.MaxwellSimTreeNode):
|
||||||
# Remove Temporary Mesh
|
# Remove Temporary Mesh
|
||||||
bpy.data.meshes.remove(mesh)
|
bpy.data.meshes.remove(mesh)
|
||||||
|
|
||||||
print(vertices)
|
|
||||||
return td.Structure(
|
return td.Structure(
|
||||||
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
geometry=td.TriangleMesh.from_vertices_faces(vertices, faces),
|
||||||
medium=self.compute_input("medium")
|
medium=self.compute_input("medium")
|
||||||
|
|
|
@ -61,6 +61,6 @@ BL_REGISTER = [
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
contracts.NodeType.BoxStructure: (
|
contracts.NodeType.BoxStructure: (
|
||||||
contracts.NodeCategory.MAXWELLSIM_STRUCTURES
|
contracts.NodeCategory.MAXWELLSIM_STRUCTURES_PRIMITIVES
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,72 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class CylinderStructureNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.CylinderStructure
|
||||||
|
bl_label = "Cylinder Structure"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"medium": sockets.MaxwellMediumSocketDef(
|
||||||
|
label="Medium",
|
||||||
|
),
|
||||||
|
"center": sockets.PhysicalPoint3DSocketDef(
|
||||||
|
label="Center",
|
||||||
|
),
|
||||||
|
"radius": sockets.PhysicalLengthSocketDef(
|
||||||
|
label="Radius",
|
||||||
|
),
|
||||||
|
"height": sockets.PhysicalLengthSocketDef(
|
||||||
|
label="Height",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"structure": sockets.MaxwellStructureSocketDef(
|
||||||
|
label="Structure",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("structure")
|
||||||
|
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Box:
|
||||||
|
medium = self.compute_input("medium")
|
||||||
|
_center = self.compute_input("center")
|
||||||
|
_radius = self.compute_input("radius")
|
||||||
|
_height = self.compute_input("height")
|
||||||
|
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
radius = spu.convert_to(_radius, spu.um) / spu.um
|
||||||
|
height = spu.convert_to(_height, spu.um) / spu.um
|
||||||
|
|
||||||
|
return td.Structure(
|
||||||
|
geometry=td.Cylinder(
|
||||||
|
radius=radius,
|
||||||
|
center=center,
|
||||||
|
length=height,
|
||||||
|
),
|
||||||
|
medium=medium,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
CylinderStructureNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.CylinderStructure: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_STRUCTURES_PRIMITIVES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,66 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class SphereStructureNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.SphereStructure
|
||||||
|
bl_label = "Sphere Structure"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"medium": sockets.MaxwellMediumSocketDef(
|
||||||
|
label="Medium",
|
||||||
|
),
|
||||||
|
"center": sockets.PhysicalPoint3DSocketDef(
|
||||||
|
label="Center",
|
||||||
|
),
|
||||||
|
"radius": sockets.PhysicalLengthSocketDef(
|
||||||
|
label="Radius",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"structure": sockets.MaxwellStructureSocketDef(
|
||||||
|
label="Structure",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("structure")
|
||||||
|
def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Box:
|
||||||
|
medium = self.compute_input("medium")
|
||||||
|
_center = self.compute_input("center")
|
||||||
|
_radius = self.compute_input("radius")
|
||||||
|
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
radius = spu.convert_to(_radius, spu.um) / spu.um
|
||||||
|
|
||||||
|
return td.Structure(
|
||||||
|
geometry=td.Sphere(
|
||||||
|
radius=radius,
|
||||||
|
center=center,
|
||||||
|
),
|
||||||
|
medium=medium,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
SphereStructureNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.SphereStructure: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_STRUCTURES_PRIMITIVES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
|
from . import combine
|
||||||
|
#from . import separate
|
||||||
|
|
||||||
from . import math
|
from . import math
|
||||||
from . import operations
|
from . import operations
|
||||||
|
from . import converter
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
*combine.BL_REGISTER,
|
||||||
|
#*separate.BL_REGISTER,
|
||||||
|
|
||||||
|
*converter.BL_REGISTER,
|
||||||
*math.BL_REGISTER,
|
*math.BL_REGISTER,
|
||||||
*operations.BL_REGISTER,
|
*operations.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
|
**combine.BL_NODES,
|
||||||
|
#**separate.BL_NODES,
|
||||||
|
|
||||||
|
**converter.BL_NODES,
|
||||||
**math.BL_NODES,
|
**math.BL_NODES,
|
||||||
**operations.BL_NODES,
|
**operations.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from ... import contracts
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
class CombineNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.Combine
|
||||||
|
bl_label = "Combine"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {}
|
||||||
|
input_socket_sets = {
|
||||||
|
"real_3d_vector": {
|
||||||
|
f"x_{i}": sockets.RealNumberSocketDef(
|
||||||
|
label=f"x_{i}"
|
||||||
|
)
|
||||||
|
for i in range(3)
|
||||||
|
},
|
||||||
|
"point_3d": {
|
||||||
|
axis: sockets.PhysicalLengthSocketDef(
|
||||||
|
label=axis
|
||||||
|
)
|
||||||
|
for i, axis in zip(
|
||||||
|
range(3),
|
||||||
|
["x", "y", "z"]
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"size_3d": {
|
||||||
|
axis_key: sockets.PhysicalLengthSocketDef(
|
||||||
|
label=axis_label
|
||||||
|
)
|
||||||
|
for i, axis_key, axis_label in zip(
|
||||||
|
range(3),
|
||||||
|
["x_size", "y_size", "z_size"],
|
||||||
|
["X Size", "Y Size", "Z Size"],
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets = {}
|
||||||
|
output_socket_sets = {
|
||||||
|
"real_3d_vector": {
|
||||||
|
"real_3d_vector": sockets.Real3DVectorSocketDef(
|
||||||
|
label="Real 3D Vector",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"point_3d": {
|
||||||
|
"point_3d": sockets.PhysicalPoint3DSocketDef(
|
||||||
|
label="3D Point",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"size_3d": {
|
||||||
|
"size_3d": sockets.PhysicalSize3DSocketDef(
|
||||||
|
label="3D Size",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("real_3d_vector")
|
||||||
|
def compute_real_3d_vector(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
x1, x2, x3 = [
|
||||||
|
self.compute_input(f"x_{i}")
|
||||||
|
for i in range(3)
|
||||||
|
]
|
||||||
|
|
||||||
|
return (x1, x2, x3)
|
||||||
|
|
||||||
|
@base.computes_output_socket("point_3d")
|
||||||
|
def compute_point_3d(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
x, y, z = [
|
||||||
|
self.compute_input(axis)
|
||||||
|
#spu.convert_to(
|
||||||
|
# self.compute_input(axis),
|
||||||
|
# spu.meter,
|
||||||
|
#) / spu.meter
|
||||||
|
for axis in ["x", "y", "z"]
|
||||||
|
]
|
||||||
|
|
||||||
|
return sp.Matrix([x, y, z])# * spu.meter
|
||||||
|
|
||||||
|
@base.computes_output_socket("size_3d")
|
||||||
|
def compute_size_3d(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
x_size, y_size, z_size = [
|
||||||
|
self.compute_input(axis)
|
||||||
|
#spu.convert_to(
|
||||||
|
# self.compute_input(axis),
|
||||||
|
# spu.meter,
|
||||||
|
#) / spu.meter
|
||||||
|
for axis in ["x_size", "y_size", "z_size"]
|
||||||
|
]
|
||||||
|
|
||||||
|
return sp.Matrix([x_size, y_size, z_size])# * spu.meter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
CombineNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.Combine: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_UTILITIES
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
from . import wave_converter
|
||||||
|
|
||||||
|
BL_REGISTER = [
|
||||||
|
*wave_converter.BL_REGISTER,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
**wave_converter.BL_NODES,
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class WaveConverterNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.WaveConverter
|
||||||
|
bl_label = "Wave Converter"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {}
|
||||||
|
input_socket_sets = {
|
||||||
|
"freq_to_vacwl": {
|
||||||
|
"freq": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"vacwl_to_freq": {
|
||||||
|
"vacwl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets = {}
|
||||||
|
output_socket_sets = {
|
||||||
|
"freq_to_vacwl": {
|
||||||
|
"vacwl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"vacwl_to_freq": {
|
||||||
|
"freq": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("freq")
|
||||||
|
def compute_freq(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
||||||
|
|
||||||
|
vacwl = self.compute_input("vacwl")
|
||||||
|
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / vacwl,
|
||||||
|
spu.hertz,
|
||||||
|
)
|
||||||
|
|
||||||
|
@base.computes_output_socket("vacwl")
|
||||||
|
def compute_vacwl(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
||||||
|
|
||||||
|
freq = self.compute_input("freq")
|
||||||
|
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / freq,
|
||||||
|
spu.meter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
WaveConverterNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.WaveConverter: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_UTILITIES_CONVERTERS
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from .... import contracts
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base
|
||||||
|
|
||||||
|
class WaveConverterNode(base.MaxwellSimTreeNode):
|
||||||
|
node_type = contracts.NodeType.WaveConverter
|
||||||
|
bl_label = "Wave Converter"
|
||||||
|
#bl_icon = ...
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {}
|
||||||
|
input_socket_sets = {
|
||||||
|
"freq_to_vacwl": {
|
||||||
|
"freq": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"vacwl_to_freq": {
|
||||||
|
"vacwl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets = {}
|
||||||
|
output_socket_sets = {
|
||||||
|
"freq_to_vacwl": {
|
||||||
|
"vacwl": sockets.PhysicalVacWLSocketDef(
|
||||||
|
label="Vac WL",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"vacwl_to_freq": {
|
||||||
|
"freq": sockets.PhysicalFreqSocketDef(
|
||||||
|
label="Freq",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket("freq")
|
||||||
|
def compute_freq(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
||||||
|
|
||||||
|
vacwl = self.compute_input("vacwl")
|
||||||
|
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / vacwl,
|
||||||
|
spu.hertz,
|
||||||
|
)
|
||||||
|
|
||||||
|
@base.computes_output_socket("vacwl")
|
||||||
|
def compute_vacwl(self: contracts.NodeTypeProtocol) -> sp.Expr:
|
||||||
|
vac_speed_of_light = sc.constants.speed_of_light * spu.meter/spu.second
|
||||||
|
|
||||||
|
freq = self.compute_input("freq")
|
||||||
|
|
||||||
|
return spu.convert_to(
|
||||||
|
vac_speed_of_light / freq,
|
||||||
|
spu.meter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
WaveConverterNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
contracts.NodeType.WaveConverter: (
|
||||||
|
contracts.NodeCategory.MAXWELLSIM_UTILITIES_CONVERTERS
|
||||||
|
)
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ Real3DVectorSocketDef = vector.Real3DVectorSocketDef
|
||||||
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
||||||
|
|
||||||
from . import physical
|
from . import physical
|
||||||
|
PhysicalUnitSystemSocketDef = physical.PhysicalUnitSystemSocketDef
|
||||||
PhysicalTimeSocketDef = physical.PhysicalTimeSocketDef
|
PhysicalTimeSocketDef = physical.PhysicalTimeSocketDef
|
||||||
PhysicalAngleSocketDef = physical.PhysicalAngleSocketDef
|
PhysicalAngleSocketDef = physical.PhysicalAngleSocketDef
|
||||||
PhysicalLengthSocketDef = physical.PhysicalLengthSocketDef
|
PhysicalLengthSocketDef = physical.PhysicalLengthSocketDef
|
||||||
|
@ -30,6 +31,7 @@ PhysicalAccelScalarSocketDef = physical.PhysicalAccelScalarSocketDef
|
||||||
PhysicalForceScalarSocketDef = physical.PhysicalForceScalarSocketDef
|
PhysicalForceScalarSocketDef = physical.PhysicalForceScalarSocketDef
|
||||||
PhysicalPolSocketDef = physical.PhysicalPolSocketDef
|
PhysicalPolSocketDef = physical.PhysicalPolSocketDef
|
||||||
PhysicalFreqSocketDef = physical.PhysicalFreqSocketDef
|
PhysicalFreqSocketDef = physical.PhysicalFreqSocketDef
|
||||||
|
PhysicalVacWLSocketDef = physical.PhysicalVacWLSocketDef
|
||||||
PhysicalSpecRelPermDistSocketDef = physical.PhysicalSpecRelPermDistSocketDef
|
PhysicalSpecRelPermDistSocketDef = physical.PhysicalSpecRelPermDistSocketDef
|
||||||
PhysicalSpecPowerDistSocketDef = physical.PhysicalSpecPowerDistSocketDef
|
PhysicalSpecPowerDistSocketDef = physical.PhysicalSpecPowerDistSocketDef
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ BlenderImageSocketDef = blender.BlenderImageSocketDef
|
||||||
BlenderVolumeSocketDef = blender.BlenderVolumeSocketDef
|
BlenderVolumeSocketDef = blender.BlenderVolumeSocketDef
|
||||||
BlenderGeoNodesSocketDef = blender.BlenderGeoNodesSocketDef
|
BlenderGeoNodesSocketDef = blender.BlenderGeoNodesSocketDef
|
||||||
BlenderTextSocketDef = blender.BlenderTextSocketDef
|
BlenderTextSocketDef = blender.BlenderTextSocketDef
|
||||||
|
BlenderPreviewTargetSocketDef = blender.BlenderPreviewTargetSocketDef
|
||||||
|
|
||||||
from . import maxwell
|
from . import maxwell
|
||||||
MaxwellBoundBoxSocketDef = maxwell.MaxwellBoundBoxSocketDef
|
MaxwellBoundBoxSocketDef = maxwell.MaxwellBoundBoxSocketDef
|
||||||
|
|
|
@ -235,4 +235,23 @@ class BLSocket(bpy.types.NodeSocket):
|
||||||
node: bpy.types.Node,
|
node: bpy.types.Node,
|
||||||
text: str,
|
text: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
layout.label(text=text)
|
col = layout.column()
|
||||||
|
row_col = col.row()
|
||||||
|
row_col.alignment = "RIGHT"
|
||||||
|
# Row: Label & Preview Toggle
|
||||||
|
if hasattr(self, "draw_preview"):
|
||||||
|
row_col.prop(
|
||||||
|
self,
|
||||||
|
"preview_active",
|
||||||
|
toggle=True,
|
||||||
|
text="",
|
||||||
|
icon="SEQ_PREVIEW",
|
||||||
|
)
|
||||||
|
|
||||||
|
row_col.label(text=text)
|
||||||
|
|
||||||
|
# Row: Preview (in box)
|
||||||
|
if hasattr(self, "draw_preview"):
|
||||||
|
if self.preview_active:
|
||||||
|
col_box = col.box()
|
||||||
|
self.draw_preview(col_box)
|
||||||
|
|
|
@ -13,6 +13,8 @@ from . import text_socket
|
||||||
BlenderGeoNodesSocketDef = geonodes_socket.BlenderGeoNodesSocketDef
|
BlenderGeoNodesSocketDef = geonodes_socket.BlenderGeoNodesSocketDef
|
||||||
BlenderTextSocketDef = text_socket.BlenderTextSocketDef
|
BlenderTextSocketDef = text_socket.BlenderTextSocketDef
|
||||||
|
|
||||||
|
from . import target_socket
|
||||||
|
BlenderPreviewTargetSocketDef = target_socket.BlenderPreviewTargetSocketDef
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*object_socket.BL_REGISTER,
|
*object_socket.BL_REGISTER,
|
||||||
|
@ -20,6 +22,7 @@ BL_REGISTER = [
|
||||||
|
|
||||||
*image_socket.BL_REGISTER,
|
*image_socket.BL_REGISTER,
|
||||||
*volume_socket.BL_REGISTER,
|
*volume_socket.BL_REGISTER,
|
||||||
|
*target_socket.BL_REGISTER,
|
||||||
|
|
||||||
*geonodes_socket.BL_REGISTER,
|
*geonodes_socket.BL_REGISTER,
|
||||||
*text_socket.BL_REGISTER,
|
*text_socket.BL_REGISTER,
|
||||||
|
|
|
@ -6,6 +6,19 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts
|
from ... import contracts
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Operators
|
||||||
|
####################
|
||||||
|
class BlenderMaxwellResetGeoNodesSocket(bpy.types.Operator):
|
||||||
|
bl_idname = "blender_maxwell.reset_geo_nodes_socket"
|
||||||
|
bl_label = "Reset GeoNodes Socket"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
context.socket.update_geonodes_node()
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
|
@ -33,6 +46,18 @@ class BlenderGeoNodesBLSocket(base.BLSocket):
|
||||||
update=(lambda self, context: self.update_geonodes_node()),
|
update=(lambda self, context: self.update_geonodes_node()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_label_row(self, label_col_row, text):
|
||||||
|
label_col_row.label(text=text)
|
||||||
|
if self.raw_value:
|
||||||
|
label_col_row.operator(
|
||||||
|
"blender_maxwell.reset_geo_nodes_socket",
|
||||||
|
text="",
|
||||||
|
icon="FILE_REFRESH",
|
||||||
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
####################
|
####################
|
||||||
|
@ -58,5 +83,6 @@ class BlenderGeoNodesSocketDef(pyd.BaseModel):
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
BlenderGeoNodesBLSocket
|
BlenderMaxwellResetGeoNodesSocket,
|
||||||
|
BlenderGeoNodesBLSocket,
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,6 +6,29 @@ import pydantic as pyd
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts
|
from ... import contracts
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Socket
|
||||||
|
####################
|
||||||
|
class BlenderMaxwellCreateAndAssignBLObject(bpy.types.Operator):
|
||||||
|
bl_idname = "blender_maxwell.create_and_assign_bl_object"
|
||||||
|
bl_label = "Create and Assign BL Object"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
mesh = bpy.data.meshes.new("GenMesh")
|
||||||
|
new_bl_object = bpy.data.objects.new("GenObj", mesh)
|
||||||
|
|
||||||
|
context.collection.objects.link(new_bl_object)
|
||||||
|
|
||||||
|
node = context.node
|
||||||
|
for bl_socket_name, bl_socket in node.inputs.items():
|
||||||
|
if isinstance(bl_socket, BlenderObjectBLSocket):
|
||||||
|
bl_socket.default_value = new_bl_object
|
||||||
|
|
||||||
|
if hasattr(node, "update_sockets_from_geonodes"):
|
||||||
|
node.update_sockets_from_geonodes()
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Socket
|
# - Blender Socket
|
||||||
####################
|
####################
|
||||||
|
@ -23,6 +46,17 @@ class BlenderObjectBLSocket(base.BLSocket):
|
||||||
update=(lambda self, context: self.trigger_updates()),
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_label_row(self, label_col_row, text):
|
||||||
|
label_col_row.label(text=text)
|
||||||
|
label_col_row.operator(
|
||||||
|
"blender_maxwell.create_and_assign_bl_object",
|
||||||
|
text="",
|
||||||
|
icon="ADD",
|
||||||
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
####################
|
####################
|
||||||
|
@ -48,5 +82,6 @@ class BlenderObjectSocketDef(pyd.BaseModel):
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
BlenderObjectBLSocket
|
BlenderMaxwellCreateAndAssignBLObject,
|
||||||
|
BlenderObjectBLSocket,
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import pydantic as pyd
|
||||||
|
|
||||||
|
from .. import base
|
||||||
|
from ... import contracts
|
||||||
|
|
||||||
|
def mk_and_assign_target_bl_obj(bl_socket, node, node_tree):
|
||||||
|
# Create Mesh and Object
|
||||||
|
mesh = bpy.data.meshes.new("Mesh" + bl_socket.node.name)
|
||||||
|
new_bl_object = bpy.data.objects.new(bl_socket.node.name, mesh)
|
||||||
|
|
||||||
|
# Create Preview Collection and Object
|
||||||
|
if bl_socket.show_preview:
|
||||||
|
#if not node_tree.preview_collection:
|
||||||
|
# new_collection = bpy.data.collections.new("BLMaxwellPreview")
|
||||||
|
# node_tree.preview_collection = new_collection
|
||||||
|
#
|
||||||
|
# bpy.context.scene.collection.children.link(new_collection)
|
||||||
|
|
||||||
|
node_tree.preview_collection.objects.link(new_bl_object)
|
||||||
|
|
||||||
|
# Create Non-Preview Collection and Object
|
||||||
|
else:
|
||||||
|
#if not node_tree.non_preview_collection:
|
||||||
|
# new_collection = bpy.data.collections.new("BLMaxwellNonPreview")
|
||||||
|
# node_tree.non_preview_collection = new_collection
|
||||||
|
#
|
||||||
|
# bpy.context.scene.collection.children.link(new_collection)
|
||||||
|
|
||||||
|
node_tree.non_preview_collection.objects.link(new_bl_object)
|
||||||
|
|
||||||
|
bl_socket.local_target_object = new_bl_object
|
||||||
|
|
||||||
|
if hasattr(node, "update_sockets_from_geonodes"):
|
||||||
|
node.update_sockets_from_geonodes()
|
||||||
|
|
||||||
|
class BlenderMaxwellCreateAndAssignTargetBLObject(bpy.types.Operator):
|
||||||
|
bl_idname = "blender_maxwell.create_and_assign_target_bl_object"
|
||||||
|
bl_label = "Create and Assign Target BL Object"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bl_socket = context.socket
|
||||||
|
node = bl_socket.node
|
||||||
|
node_tree = node.id_data
|
||||||
|
|
||||||
|
mk_and_assign_target_bl_obj(bl_socket, node, node_tree)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Socket
|
||||||
|
####################
|
||||||
|
class BlenderPreviewTargetBLSocket(base.BLSocket):
|
||||||
|
socket_type = contracts.SocketType.BlenderPreviewTarget
|
||||||
|
bl_label = "BlenderPreviewTarget"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
show_preview: bpy.props.BoolProperty(
|
||||||
|
name="Target Object Included in Preview",
|
||||||
|
description="Whether or not Blender will preview the target object",
|
||||||
|
default=True,
|
||||||
|
update=(lambda self, context: self.update_preview()),
|
||||||
|
)
|
||||||
|
show_definition: bpy.props.BoolProperty(
|
||||||
|
name="Show Unit System Definition",
|
||||||
|
description="Toggle to show unit system definition",
|
||||||
|
default=False,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
target_object_pinned: bpy.props.BoolProperty(
|
||||||
|
name="Target Object Pinned",
|
||||||
|
description="Whether or not Blender will manage the target object",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
preview_collection_pinned: bpy.props.BoolProperty(
|
||||||
|
name="Global Preview Collection Pinned",
|
||||||
|
description="Whether or not Blender will use the global preview collection",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
non_preview_collection_pinned: bpy.props.BoolProperty(
|
||||||
|
name="Global Non-Preview Collection Pinned",
|
||||||
|
description="Whether or not Blender will use the global non-preview collection",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
local_target_object: bpy.props.PointerProperty(
|
||||||
|
name="Local Target Blender Object",
|
||||||
|
description="Represents a Blender object to apply a preview to",
|
||||||
|
type=bpy.types.Object,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
local_preview_collection: bpy.props.PointerProperty(
|
||||||
|
name="Local Preview Collection",
|
||||||
|
description="Collection of Blender objects that will be previewed",
|
||||||
|
type=bpy.types.Collection,
|
||||||
|
update=(lambda self, context: self.trigger_updates())
|
||||||
|
)
|
||||||
|
local_non_preview_collection: bpy.props.PointerProperty(
|
||||||
|
name="Local Non-Preview Collection",
|
||||||
|
description="Collection of Blender objects that will NOT be previewed",
|
||||||
|
type=bpy.types.Collection,
|
||||||
|
update=(lambda self, context: self.trigger_updates())
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Methods
|
||||||
|
####################
|
||||||
|
def update_preview(self):
|
||||||
|
node_tree = self.node.id_data
|
||||||
|
|
||||||
|
# Target Object Pinned
|
||||||
|
if (
|
||||||
|
self.show_preview
|
||||||
|
and self.local_target_object
|
||||||
|
and self.target_object_pinned
|
||||||
|
):
|
||||||
|
node_tree.non_preview_collection.objects.unlink(self.local_target_object)
|
||||||
|
node_tree.preview_collection.objects.link(self.local_target_object)
|
||||||
|
|
||||||
|
elif (
|
||||||
|
not self.show_preview
|
||||||
|
and self.local_target_object
|
||||||
|
and self.target_object_pinned
|
||||||
|
):
|
||||||
|
node_tree.preview_collection.objects.unlink(self.local_target_object)
|
||||||
|
node_tree.non_preview_collection.objects.link(self.local_target_object)
|
||||||
|
|
||||||
|
# Target Object Not Pinned
|
||||||
|
if (
|
||||||
|
self.show_preview
|
||||||
|
and self.local_target_object
|
||||||
|
and not self.target_object_pinned
|
||||||
|
and self.local_target_object.name in (
|
||||||
|
node_tree.non_preview_collection.objects.keys()
|
||||||
|
)
|
||||||
|
):
|
||||||
|
node_tree.non_preview_collection.objects.unlink(self.local_target_object)
|
||||||
|
node_tree.preview_collection.objects.link(self.local_target_object)
|
||||||
|
elif (
|
||||||
|
not self.show_preview
|
||||||
|
and self.local_target_object
|
||||||
|
and not self.target_object_pinned
|
||||||
|
and self.local_target_object.name in (
|
||||||
|
node_tree.preview_collection.objects.keys()
|
||||||
|
)
|
||||||
|
):
|
||||||
|
node_tree.preview_collection.objects.unlink(self.local_target_object)
|
||||||
|
node_tree.non_preview_collection.objects.link(self.local_target_object)
|
||||||
|
|
||||||
|
self.trigger_updates()
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_label_row(self, label_col_row: bpy.types.UILayout, text) -> None:
|
||||||
|
label_col_row.label(text=text)
|
||||||
|
label_col_row.prop(self, "show_preview", toggle=True, text="", icon="SEQ_PREVIEW")
|
||||||
|
label_col_row.prop(self, "show_definition", toggle=True, text="", icon="MOD_LENGTH")
|
||||||
|
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
node_tree = self.node.id_data
|
||||||
|
|
||||||
|
if self.show_definition:
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Target", icon="OBJECT_DATA")
|
||||||
|
col_row.prop(
|
||||||
|
self,
|
||||||
|
"target_object_pinned",
|
||||||
|
toggle=True,
|
||||||
|
icon="EVENT_A",
|
||||||
|
icon_only=True,
|
||||||
|
)
|
||||||
|
#col_row.operator(
|
||||||
|
# "blender_maxwell.create_and_assign_target_bl_object",
|
||||||
|
# text="",
|
||||||
|
# icon="ADD",
|
||||||
|
#)
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
if not self.target_object_pinned:
|
||||||
|
col_row.prop(self, "local_target_object", text="")
|
||||||
|
|
||||||
|
# Non-Preview Collection
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Enabled", icon="COLLECTION_COLOR_04")
|
||||||
|
col_row.prop(
|
||||||
|
self,
|
||||||
|
"preview_collection_pinned",
|
||||||
|
toggle=True,
|
||||||
|
icon="PINNED",
|
||||||
|
icon_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
if not self.preview_collection_pinned:
|
||||||
|
col_row.prop(self, "local_preview_collection", text="")
|
||||||
|
|
||||||
|
# Non-Preview Collection
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Disabled", icon="COLLECTION_COLOR_01")
|
||||||
|
col_row.prop(
|
||||||
|
self,
|
||||||
|
"non_preview_collection_pinned",
|
||||||
|
toggle=True,
|
||||||
|
icon="PINNED",
|
||||||
|
icon_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
if not self.non_preview_collection_pinned:
|
||||||
|
col_row.prop(self, "local_non_preview_collection", text="")
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Default Value
|
||||||
|
####################
|
||||||
|
@property
|
||||||
|
def default_value(self) -> bpy.types.Object:
|
||||||
|
node_tree = self.node.id_data
|
||||||
|
if not self.local_target_object and self.target_object_pinned:
|
||||||
|
mk_and_assign_target_bl_obj(self, self.node, node_tree)
|
||||||
|
return self.local_target_object
|
||||||
|
|
||||||
|
return self.local_target_object
|
||||||
|
|
||||||
|
@default_value.setter
|
||||||
|
def default_value(self, value: typ.Any) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Cleanup
|
||||||
|
####################
|
||||||
|
def free(self) -> None:
|
||||||
|
if self.local_target_object:
|
||||||
|
bpy.data.meshes.remove(self.local_target_object.data, do_unlink=True)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Socket Configuration
|
||||||
|
####################
|
||||||
|
class BlenderPreviewTargetSocketDef(pyd.BaseModel):
|
||||||
|
socket_type: contracts.SocketType = contracts.SocketType.BlenderPreviewTarget
|
||||||
|
label: str
|
||||||
|
|
||||||
|
show_preview: bool = True
|
||||||
|
|
||||||
|
def init(self, bl_socket: BlenderPreviewTargetBLSocket) -> None:
|
||||||
|
pass
|
||||||
|
#bl_socket.show_preview = self.show_preview
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
BlenderMaxwellCreateAndAssignTargetBLObject,
|
||||||
|
BlenderPreviewTargetBLSocket,
|
||||||
|
]
|
|
@ -7,6 +7,13 @@ import tidy3d as td
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import contracts
|
from ... import contracts
|
||||||
|
|
||||||
|
BOUND_FACE_ITEMS = [
|
||||||
|
("PML", "PML", "Perfectly matched layer"),
|
||||||
|
("PEC", "PEC", "Perfect electrical conductor"),
|
||||||
|
("PMC", "PMC", "Perfect magnetic conductor"),
|
||||||
|
("PERIODIC", "Periodic", "Infinitely periodic layer"),
|
||||||
|
]
|
||||||
|
|
||||||
class MaxwellBoundBoxBLSocket(base.BLSocket):
|
class MaxwellBoundBoxBLSocket(base.BLSocket):
|
||||||
socket_type = contracts.SocketType.MaxwellBoundBox
|
socket_type = contracts.SocketType.MaxwellBoundBox
|
||||||
bl_label = "Maxwell Bound Box"
|
bl_label = "Maxwell Bound Box"
|
||||||
|
@ -15,6 +22,72 @@ class MaxwellBoundBoxBLSocket(base.BLSocket):
|
||||||
td.BoundarySpec: {}
|
td.BoundarySpec: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
x_pos: bpy.props.EnumProperty(
|
||||||
|
name="+x Bound Face",
|
||||||
|
description="+x choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
x_neg: bpy.props.EnumProperty(
|
||||||
|
name="-x Bound Face",
|
||||||
|
description="-x choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
y_pos: bpy.props.EnumProperty(
|
||||||
|
name="+y Bound Face",
|
||||||
|
description="+y choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
y_neg: bpy.props.EnumProperty(
|
||||||
|
name="-y Bound Face",
|
||||||
|
description="-y choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
z_pos: bpy.props.EnumProperty(
|
||||||
|
name="+z Bound Face",
|
||||||
|
description="+z choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
z_neg: bpy.props.EnumProperty(
|
||||||
|
name="-z Bound Face",
|
||||||
|
description="-z choice of default boundary face",
|
||||||
|
items=BOUND_FACE_ITEMS,
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
col.label(text="-/+ x")
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.prop(self, "x_neg", text="")
|
||||||
|
col_row.prop(self, "x_pos", text="")
|
||||||
|
|
||||||
|
col.label(text="-/+ y")
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.prop(self, "y_neg", text="")
|
||||||
|
col_row.prop(self, "y_pos", text="")
|
||||||
|
|
||||||
|
col.label(text="-/+ z")
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.prop(self, "z_neg", text="")
|
||||||
|
col_row.prop(self, "z_pos", text="")
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -11,16 +11,40 @@ class MaxwellBoundFaceBLSocket(base.BLSocket):
|
||||||
socket_type = contracts.SocketType.MaxwellBoundFace
|
socket_type = contracts.SocketType.MaxwellBoundFace
|
||||||
bl_label = "Maxwell Bound Face"
|
bl_label = "Maxwell Bound Face"
|
||||||
|
|
||||||
compatible_types = {
|
####################
|
||||||
td.BoundarySpec: {}
|
# - Properties
|
||||||
}
|
####################
|
||||||
|
default_choice: bpy.props.EnumProperty(
|
||||||
|
name="Bound Face",
|
||||||
|
description="A choice of default boundary face",
|
||||||
|
items=[
|
||||||
|
("PML", "PML", "Perfectly matched layer"),
|
||||||
|
("PEC", "PEC", "Perfect electrical conductor"),
|
||||||
|
("PMC", "PMC", "Perfect magnetic conductor"),
|
||||||
|
("PERIODIC", "Periodic", "Infinitely periodic layer"),
|
||||||
|
],
|
||||||
|
default="PML",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.prop(self, "default_choice", text="")
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def default_value(self) -> td.BoundarySpec:
|
def default_value(self) -> td.BoundarySpec:
|
||||||
return td.BoundarySpec()
|
return {
|
||||||
|
"PML": td.PML(num_layers=12),
|
||||||
|
"PEC": td.PECBoundary(),
|
||||||
|
"PMC": td.PMCBoundary(),
|
||||||
|
"PERIODIC": td.Periodic(),
|
||||||
|
}[self.default_choice]
|
||||||
|
|
||||||
@default_value.setter
|
@default_value.setter
|
||||||
def default_value(self, value: typ.Any) -> None:
|
def default_value(self, value: typ.Any) -> None:
|
||||||
|
@ -33,8 +57,10 @@ class MaxwellBoundFaceSocketDef(pyd.BaseModel):
|
||||||
socket_type: contracts.SocketType = contracts.SocketType.MaxwellBoundFace
|
socket_type: contracts.SocketType = contracts.SocketType.MaxwellBoundFace
|
||||||
label: str
|
label: str
|
||||||
|
|
||||||
|
default_choice: str = "PML"
|
||||||
|
|
||||||
def init(self, bl_socket: MaxwellBoundFaceBLSocket) -> None:
|
def init(self, bl_socket: MaxwellBoundFaceBLSocket) -> None:
|
||||||
pass
|
bl_socket.default_choice = self.default_choice
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from .. import base
|
from .. import base
|
||||||
|
@ -12,16 +13,26 @@ class IntegerNumberBLSocket(base.BLSocket):
|
||||||
socket_type = contracts.SocketType.IntegerNumber
|
socket_type = contracts.SocketType.IntegerNumber
|
||||||
bl_label = "IntegerNumber"
|
bl_label = "IntegerNumber"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
raw_value: bpy.props.IntProperty(
|
||||||
|
name="Integer",
|
||||||
|
description="Represents an integer",
|
||||||
|
default=0,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def default_value(self) -> None:
|
def default_value(self) -> None:
|
||||||
pass
|
return self.raw_value
|
||||||
|
|
||||||
@default_value.setter
|
@default_value.setter
|
||||||
def default_value(self, value: typ.Any) -> None:
|
def default_value(self, value: typ.Any) -> None:
|
||||||
pass
|
self.raw_value = int(value)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
|
@ -30,8 +41,10 @@ class IntegerNumberSocketDef(pyd.BaseModel):
|
||||||
socket_type: contracts.SocketType = contracts.SocketType.IntegerNumber
|
socket_type: contracts.SocketType = contracts.SocketType.IntegerNumber
|
||||||
label: str
|
label: str
|
||||||
|
|
||||||
|
default_value: int = 0
|
||||||
|
|
||||||
def init(self, bl_socket: IntegerNumberBLSocket) -> None:
|
def init(self, bl_socket: IntegerNumberBLSocket) -> None:
|
||||||
pass
|
bl_socket.raw_value = self.default_value
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from . import unit_system_socket
|
||||||
|
PhysicalUnitSystemSocketDef = unit_system_socket.PhysicalUnitSystemSocketDef
|
||||||
|
|
||||||
from . import time_socket
|
from . import time_socket
|
||||||
PhysicalTimeSocketDef = time_socket.PhysicalTimeSocketDef
|
PhysicalTimeSocketDef = time_socket.PhysicalTimeSocketDef
|
||||||
|
|
||||||
|
@ -31,7 +34,9 @@ from . import pol_socket
|
||||||
PhysicalPolSocketDef = pol_socket.PhysicalPolSocketDef
|
PhysicalPolSocketDef = pol_socket.PhysicalPolSocketDef
|
||||||
|
|
||||||
from . import freq_socket
|
from . import freq_socket
|
||||||
|
from . import vac_wl_socket
|
||||||
PhysicalFreqSocketDef = freq_socket.PhysicalFreqSocketDef
|
PhysicalFreqSocketDef = freq_socket.PhysicalFreqSocketDef
|
||||||
|
PhysicalVacWLSocketDef = vac_wl_socket.PhysicalVacWLSocketDef
|
||||||
|
|
||||||
from . import spec_rel_permit_dist_socket
|
from . import spec_rel_permit_dist_socket
|
||||||
from . import spec_power_dist_socket
|
from . import spec_power_dist_socket
|
||||||
|
@ -40,6 +45,8 @@ PhysicalSpecPowerDistSocketDef = spec_power_dist_socket.PhysicalSpecPowerDistSoc
|
||||||
|
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
|
*unit_system_socket.BL_REGISTER,
|
||||||
|
|
||||||
*time_socket.BL_REGISTER,
|
*time_socket.BL_REGISTER,
|
||||||
|
|
||||||
*angle_socket.BL_REGISTER,
|
*angle_socket.BL_REGISTER,
|
||||||
|
@ -61,6 +68,7 @@ BL_REGISTER = [
|
||||||
*pol_socket.BL_REGISTER,
|
*pol_socket.BL_REGISTER,
|
||||||
|
|
||||||
*freq_socket.BL_REGISTER,
|
*freq_socket.BL_REGISTER,
|
||||||
|
*vac_wl_socket.BL_REGISTER,
|
||||||
*spec_rel_permit_dist_socket.BL_REGISTER,
|
*spec_rel_permit_dist_socket.BL_REGISTER,
|
||||||
*spec_power_dist_socket.BL_REGISTER,
|
*spec_power_dist_socket.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from .. import base
|
from .. import base
|
||||||
|
@ -12,12 +13,44 @@ class PhysicalPolBLSocket(base.BLSocket):
|
||||||
socket_type = contracts.SocketType.PhysicalPol
|
socket_type = contracts.SocketType.PhysicalPol
|
||||||
bl_label = "PhysicalPol"
|
bl_label = "PhysicalPol"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
default_choice: bpy.props.EnumProperty(
|
||||||
|
name="Bound Face",
|
||||||
|
description="A choice of default boundary face",
|
||||||
|
items=[
|
||||||
|
("EX", "Ex", "Linear x-pol of E field"),
|
||||||
|
("EY", "Ey", "Linear y-pol of E field"),
|
||||||
|
("EZ", "Ez", "Linear z-pol of E field"),
|
||||||
|
("HX", "Hx", "Linear x-pol of H field"),
|
||||||
|
("HY", "Hy", "Linear x-pol of H field"),
|
||||||
|
("HZ", "Hz", "Linear x-pol of H field"),
|
||||||
|
],
|
||||||
|
default="EX",
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
col_row = col.row(align=True)
|
||||||
|
col_row.prop(self, "default_choice", text="")
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def default_value(self) -> None:
|
def default_value(self) -> str:
|
||||||
pass
|
return {
|
||||||
|
"EX": "Ex",
|
||||||
|
"EY": "Ey",
|
||||||
|
"EZ": "Ez",
|
||||||
|
"HX": "Hx",
|
||||||
|
"HY": "Hy",
|
||||||
|
"HZ": "Hz",
|
||||||
|
}[self.default_choice]
|
||||||
|
|
||||||
@default_value.setter
|
@default_value.setter
|
||||||
def default_value(self, value: typ.Any) -> None:
|
def default_value(self, value: typ.Any) -> None:
|
||||||
|
|
|
@ -13,17 +13,6 @@ class PhysicalSize3DBLSocket(base.BLSocket):
|
||||||
bl_label = "Physical Volume"
|
bl_label = "Physical Volume"
|
||||||
use_units = True
|
use_units = True
|
||||||
|
|
||||||
compatible_types = {
|
|
||||||
sp.Expr: {
|
|
||||||
lambda self, v: v.is_real,
|
|
||||||
lambda self, v: len(v.free_symbols) == 0,
|
|
||||||
lambda self, v: any(
|
|
||||||
contracts.is_exactly_expressed_as_unit(v, unit)
|
|
||||||
for unit in self.units.values()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import pydantic as pyd
|
||||||
|
|
||||||
|
from .. import base
|
||||||
|
from ... import contracts
|
||||||
|
|
||||||
|
def contract_units_to_items(socket_type):
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
unit_key,
|
||||||
|
str(unit),
|
||||||
|
f"{socket_type}-compatible unit",
|
||||||
|
)
|
||||||
|
for unit_key, unit in contracts.SocketType_to_units[
|
||||||
|
socket_type
|
||||||
|
]["values"].items()
|
||||||
|
]
|
||||||
|
def default_unit_key_for(socket_type):
|
||||||
|
return contracts.SocketType_to_units[
|
||||||
|
socket_type
|
||||||
|
]["default"]
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Socket
|
||||||
|
####################
|
||||||
|
class PhysicalUnitSystemBLSocket(base.BLSocket):
|
||||||
|
socket_type = contracts.SocketType.PhysicalUnitSystem
|
||||||
|
bl_label = "PhysicalUnitSystem"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
show_definition: bpy.props.BoolProperty(
|
||||||
|
name="Show Unit System Definition",
|
||||||
|
description="Toggle to show unit system definition",
|
||||||
|
default=False,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_time: bpy.props.EnumProperty(
|
||||||
|
name="Time Unit",
|
||||||
|
description="Unit of time",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalTime),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalTime),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_angle: bpy.props.EnumProperty(
|
||||||
|
name="Angle Unit",
|
||||||
|
description="Unit of angle",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalAngle),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalAngle),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_length: bpy.props.EnumProperty(
|
||||||
|
name="Length Unit",
|
||||||
|
description="Unit of length",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalLength),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalLength),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_area: bpy.props.EnumProperty(
|
||||||
|
name="Area Unit",
|
||||||
|
description="Unit of area",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalArea),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalArea),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_volume: bpy.props.EnumProperty(
|
||||||
|
name="Volume Unit",
|
||||||
|
description="Unit of time",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalVolume),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalVolume),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_point_2d: bpy.props.EnumProperty(
|
||||||
|
name="Point2D Unit",
|
||||||
|
description="Unit of 2D points",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalPoint2D),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalPoint2D),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_point_3d: bpy.props.EnumProperty(
|
||||||
|
name="Point3D Unit",
|
||||||
|
description="Unit of 3D points",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalPoint3D),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalPoint3D),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_size_2d: bpy.props.EnumProperty(
|
||||||
|
name="Size2D Unit",
|
||||||
|
description="Unit of 2D sizes",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalSize2D),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalSize2D),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_size_3d: bpy.props.EnumProperty(
|
||||||
|
name="Size3D Unit",
|
||||||
|
description="Unit of 3D sizes",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalSize3D),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalSize3D),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_mass: bpy.props.EnumProperty(
|
||||||
|
name="Mass Unit",
|
||||||
|
description="Unit of mass",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalMass),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalMass),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_speed: bpy.props.EnumProperty(
|
||||||
|
name="Speed Unit",
|
||||||
|
description="Unit of speed",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalSpeed),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalSpeed),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_accel_scalar: bpy.props.EnumProperty(
|
||||||
|
name="Accel Unit",
|
||||||
|
description="Unit of acceleration",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalAccelScalar),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalAccelScalar),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_force_scalar: bpy.props.EnumProperty(
|
||||||
|
name="Force Scalar Unit",
|
||||||
|
description="Unit of scalar force",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalForceScalar),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalForceScalar),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_accel_3d_vector: bpy.props.EnumProperty(
|
||||||
|
name="Accel3D Unit",
|
||||||
|
description="Unit of 3D vector acceleration",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalAccel3DVector),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalAccel3DVector),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_force_3d_vector: bpy.props.EnumProperty(
|
||||||
|
name="Force3D Unit",
|
||||||
|
description="Unit of 3D vector force",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalForce3DVector),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalForce3DVector),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
unit_freq: bpy.props.EnumProperty(
|
||||||
|
name="Freq Unit",
|
||||||
|
description="Unit of frequency",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalFreq),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalFreq),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
unit_vac_wl: bpy.props.EnumProperty(
|
||||||
|
name="VacWL Unit",
|
||||||
|
description="Unit of vacuum wavelength",
|
||||||
|
items=contract_units_to_items(contracts.SocketType.PhysicalVacWL),
|
||||||
|
default=default_unit_key_for(contracts.SocketType.PhysicalVacWL),
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_label_row(self, label_col_row: bpy.types.UILayout, text) -> None:
|
||||||
|
label_col_row.label(text=text)
|
||||||
|
label_col_row.prop(self, "show_definition", toggle=True, text="", icon="MOD_LENGTH")
|
||||||
|
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
if self.show_definition:
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.prop(self, "unit_time", text="")
|
||||||
|
col_row.prop(self, "unit_angle", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.prop(self, "unit_length", text="")
|
||||||
|
col_row.prop(self, "unit_area", text="")
|
||||||
|
col_row.prop(self, "unit_volume", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Point")
|
||||||
|
col_row.prop(self, "unit_point_2d", text="")
|
||||||
|
col_row.prop(self, "unit_point_3d", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Size")
|
||||||
|
col_row.prop(self, "unit_size_2d", text="")
|
||||||
|
col_row.prop(self, "unit_size_3d", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Mass")
|
||||||
|
col_row.prop(self, "unit_mass", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Vel")
|
||||||
|
col_row.prop(self, "unit_speed", text="")
|
||||||
|
#col_row.prop(self, "unit_vel_2d_vector", text="")
|
||||||
|
#col_row.prop(self, "unit_vel_3d_vector", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.label(text="Accel")
|
||||||
|
col_row.prop(self, "unit_accel_scalar", text="")
|
||||||
|
#col_row.prop(self, "unit_accel_2d_vector", text="")
|
||||||
|
col_row.prop(self, "unit_accel_3d_vector", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.label(text="Force")
|
||||||
|
col_row.prop(self, "unit_force_scalar", text="")
|
||||||
|
#col_row.prop(self, "unit_force_2d_vector", text="")
|
||||||
|
col_row.prop(self, "unit_force_3d_vector", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Freq")
|
||||||
|
col_row.prop(self, "unit_freq", text="")
|
||||||
|
|
||||||
|
col_row=col.row(align=True)
|
||||||
|
col_row.alignment = "EXPAND"
|
||||||
|
col_row.label(text="Vac WL")
|
||||||
|
col_row.prop(self, "unit_vac_wl", text="")
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Default Value
|
||||||
|
####################
|
||||||
|
@property
|
||||||
|
def default_value(self) -> sp.Expr:
|
||||||
|
ST = contracts.SocketType
|
||||||
|
SM = lambda socket_type: contracts.SocketType_to_units[
|
||||||
|
socket_type
|
||||||
|
]["values"]
|
||||||
|
|
||||||
|
return {
|
||||||
|
socket_type: SM(socket_type)[socket_unit_prop]
|
||||||
|
for socket_type, socket_unit_prop in [
|
||||||
|
(ST.PhysicalTime, self.unit_time),
|
||||||
|
(ST.PhysicalAngle, self.unit_angle),
|
||||||
|
|
||||||
|
(ST.PhysicalLength, self.unit_length),
|
||||||
|
(ST.PhysicalArea, self.unit_area),
|
||||||
|
(ST.PhysicalVolume, self.unit_volume),
|
||||||
|
|
||||||
|
(ST.PhysicalPoint2D, self.unit_point_2d),
|
||||||
|
(ST.PhysicalPoint3D, self.unit_point_3d),
|
||||||
|
|
||||||
|
(ST.PhysicalSize2D, self.unit_size_2d),
|
||||||
|
(ST.PhysicalSize3D, self.unit_size_3d),
|
||||||
|
|
||||||
|
(ST.PhysicalMass, self.unit_mass),
|
||||||
|
|
||||||
|
(ST.PhysicalSpeed, self.unit_speed),
|
||||||
|
(ST.PhysicalAccelScalar, self.unit_accel_scalar),
|
||||||
|
(ST.PhysicalForceScalar, self.unit_force_scalar),
|
||||||
|
(ST.PhysicalAccel3DVector, self.unit_accel_3d_vector),
|
||||||
|
(ST.PhysicalForce3DVector, self.unit_force_3d_vector),
|
||||||
|
|
||||||
|
(ST.PhysicalFreq, self.unit_freq),
|
||||||
|
(ST.PhysicalVacWL, self.unit_vac_wl),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@default_value.setter
|
||||||
|
def default_value(self, value: typ.Any) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Socket Configuration
|
||||||
|
####################
|
||||||
|
class PhysicalUnitSystemSocketDef(pyd.BaseModel):
|
||||||
|
socket_type: contracts.SocketType = contracts.SocketType.PhysicalUnitSystem
|
||||||
|
label: str
|
||||||
|
|
||||||
|
show_by_default: bool = False
|
||||||
|
|
||||||
|
def init(self, bl_socket: PhysicalUnitSystemBLSocket) -> None:
|
||||||
|
bl_socket.show_definition = self.show_by_default
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
PhysicalUnitSystemBLSocket,
|
||||||
|
]
|
|
@ -0,0 +1,54 @@
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import pydantic as pyd
|
||||||
|
|
||||||
|
from .. import base
|
||||||
|
from ... import contracts
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Socket
|
||||||
|
####################
|
||||||
|
class PhysicalVacWLBLSocket(base.BLSocket):
|
||||||
|
socket_type = contracts.SocketType.PhysicalVacWL
|
||||||
|
bl_label = "PhysicalVacWL"
|
||||||
|
use_units = True
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
raw_value: bpy.props.FloatProperty(
|
||||||
|
name="Unitless Vacuum Wavelength",
|
||||||
|
description="Represents the unitless part of the vacuum wavelength",
|
||||||
|
default=0.0,
|
||||||
|
precision=6,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Default Value
|
||||||
|
####################
|
||||||
|
@property
|
||||||
|
def default_value(self) -> None:
|
||||||
|
return self.raw_value * self.unit
|
||||||
|
|
||||||
|
@default_value.setter
|
||||||
|
def default_value(self, value: typ.Any) -> None:
|
||||||
|
self.raw_value = self.value_as_unit(value)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Socket Configuration
|
||||||
|
####################
|
||||||
|
class PhysicalVacWLSocketDef(pyd.BaseModel):
|
||||||
|
socket_type: contracts.SocketType = contracts.SocketType.PhysicalVacWL
|
||||||
|
label: str
|
||||||
|
|
||||||
|
def init(self, bl_socket: PhysicalVacWLBLSocket) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
PhysicalVacWLBLSocket,
|
||||||
|
]
|
|
@ -1,5 +1,7 @@
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from .. import base
|
from .. import base
|
||||||
|
@ -13,15 +15,27 @@ class Real2DVectorBLSocket(base.BLSocket):
|
||||||
bl_label = "Real2DVector"
|
bl_label = "Real2DVector"
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Properties
|
||||||
|
####################
|
||||||
|
raw_value: bpy.props.FloatVectorProperty(
|
||||||
|
name="Unitless 2D Vector (global coordinate system)",
|
||||||
|
description="Represents a real 2D (coordinate) vector",
|
||||||
|
size=2,
|
||||||
|
default=(0.0, 0.0),
|
||||||
|
precision=4,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def default_value(self) -> None:
|
def default_value(self) -> sp.Expr:
|
||||||
pass
|
return tuple(self.raw_value)
|
||||||
|
|
||||||
@default_value.setter
|
@default_value.setter
|
||||||
def default_value(self, value: typ.Any) -> None:
|
def default_value(self, value: typ.Any) -> None:
|
||||||
pass
|
self.raw_value = tuple(value)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import typing as typ
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
import pydantic as pyd
|
import pydantic as pyd
|
||||||
|
|
||||||
from .. import base
|
from .. import base
|
||||||
|
@ -13,15 +15,27 @@ class Real3DVectorBLSocket(base.BLSocket):
|
||||||
bl_label = "Real3DVector"
|
bl_label = "Real3DVector"
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Default Value
|
# - Properties
|
||||||
|
####################
|
||||||
|
raw_value: bpy.props.FloatVectorProperty(
|
||||||
|
name="Unitless 3D Vector (global coordinate system)",
|
||||||
|
description="Represents a real 3D (coordinate) vector",
|
||||||
|
size=3,
|
||||||
|
default=(0.0, 0.0, 0.0),
|
||||||
|
precision=4,
|
||||||
|
update=(lambda self, context: self.trigger_updates()),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def default_value(self) -> None:
|
def default_value(self) -> sp.Expr:
|
||||||
pass
|
return tuple(self.raw_value)
|
||||||
|
|
||||||
@default_value.setter
|
@default_value.setter
|
||||||
def default_value(self, value: typ.Any) -> None:
|
def default_value(self, value: typ.Any) -> None:
|
||||||
pass
|
self.raw_value = tuple(value)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
|
|
Loading…
Reference in New Issue