oscillode/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/blender/target_socket.py

269 lines
7.8 KiB
Python
Raw Normal View History

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,
]