feat: layer list system

This commit is contained in:
2024-08-14 14:16:40 +08:00
parent 21e0b85662
commit 9e885865f7
21 changed files with 1451 additions and 825 deletions

View File

@@ -1,21 +1,22 @@
from pathlib import Path
import bpy
from .bioxelutils.container import get_container_objs_from_selection
from .operators.layer import (CombineLabels, SignScalar,
FillByLabel, FillByThreshold, FillByRange)
from .operators.container import (SaveContainer, LoadContainer,
from .operators.utils import get_layer_item_label
from .bioxelutils.utils import (get_container_obj,
get_container_objs_from_selection,
get_container_layer_objs,
get_layer_prop_value)
from .operators.layer import (FetchLayerMenu, FetchLayer,
RemoveLayer, RemoveMissingLayers, RenameLayer, ResampleScalar, SaveLayerCache,
SignScalar, CombineLabels,
FillByLabel, FillByThreshold, FillByRange, get_selected_objs_in_node_tree)
from .operators.container import (SaveAllLayerCaches, SaveContainer, LoadContainer,
AddPieCutter, AddPlaneCutter,
AddCylinderCutter, AddCubeCutter, AddSphereCutter,
PickBboxWire, PickMesh, PickVolume)
from .operators.io import (ExportVolumetricData,
ImportAsLabelLayer, ImportAsScalarLayer)
from .operators.io import (ImportAsLabel, ImportAsScalar, ImportAsColor)
from .operators.misc import (CleanAllCaches,
ReLinkNodes, SaveCaches, SaveStagedData)
def container_is_selected():
container_objs = get_container_objs_from_selection()
return len(container_objs) > 0
ReLinkNodes, RenderSettingPreset, SaveStagedData)
class PickFromContainerMenu(bpy.types.Menu):
@@ -29,22 +30,9 @@ class PickFromContainerMenu(bpy.types.Menu):
layout.operator(PickBboxWire.bl_idname)
class ModifyLayerMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_MODIFY_LAYERS"
bl_label = "Modify Layer"
def draw(self, context):
layout = self.layout
layout.operator(SignScalar.bl_idname)
layout.operator(FillByThreshold.bl_idname)
layout.operator(FillByRange.bl_idname)
layout.operator(FillByLabel.bl_idname)
layout.operator(CombineLabels.bl_idname)
class AddCutterMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_CUTTERS"
bl_label = "Add a Cutter to Container"
bl_label = "Add a Object Cutter"
def draw(self, context):
layout = self.layout
@@ -56,101 +44,78 @@ class AddCutterMenu(bpy.types.Menu):
class ImportLayerMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_LAYERS"
bl_label = "Import Volumetric Data"
bl_idname = "BIOXELNODES_MT_IMPORTLAYER"
bl_label = "Import Volumetric Data (Init)"
bl_icon = "FILE_NEW"
def draw(self, context):
layout = self.layout
layout.operator(ImportAsScalarLayer.bl_idname, text="as Scalar")
layout.operator(ImportAsLabelLayer.bl_idname, text="as Label")
layout.operator(ImportAsScalar.bl_idname,
text="as Scalar")
layout.operator(ImportAsLabel.bl_idname,
text="as Label")
layout.operator(ImportAsColor.bl_idname,
text="as Color")
class BioxelNodesView3DMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_VIEW3D"
bl_label = "Bioxel Nodes"
class AddLayerMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_ADDLAYER"
bl_label = "Import Volumetric Data (Add to)"
bl_icon = "FILE_NEW"
def draw(self, context):
layout = self.layout
is_selected = container_is_selected()
layout.operator(ImportAsScalarLayer.bl_idname,
text=ImportAsScalarLayer.bl_label+" (Add to)"
if is_selected else ImportAsScalarLayer.bl_label+" (Init)")
layout.operator(ImportAsLabelLayer.bl_idname,
text=ImportAsLabelLayer.bl_label+" (Add to)"
if is_selected else ImportAsLabelLayer.bl_label+" (Init)")
layout.separator()
layout.operator(AddPlaneCutter.bl_idname)
layout.operator(AddCylinderCutter.bl_idname)
layout.operator(AddCubeCutter.bl_idname)
layout.operator(AddSphereCutter.bl_idname)
layout.operator(AddPieCutter.bl_idname)
layout.separator()
layout.operator(PickMesh.bl_idname)
layout.operator(PickVolume.bl_idname)
layout.operator(PickBboxWire.bl_idname)
layout.separator()
layout.operator(SaveCaches.bl_idname)
layout.operator(ImportAsScalar.bl_idname,
text="as Scalar")
layout.operator(ImportAsLabel.bl_idname,
text="as Label")
layout.operator(ImportAsColor.bl_idname,
text="as Color")
class BioxelNodesOutlinerMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_OUTLINER"
bl_label = "Bioxel Nodes"
class ModifyLayerMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_MODIFYLAYER"
bl_label = "Modify Layer"
bl_icon = "FILE_NEW"
def draw(self, context):
layer_objs = get_selected_objs_in_node_tree(context)
if len(layer_objs) > 0:
active_obj_name = layer_objs[0].name
else:
active_obj_name = ""
layout = self.layout
op = layout.operator(ResampleScalar.bl_idname,
icon=ResampleScalar.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(SignScalar.bl_idname,
icon=SignScalar.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(FillByThreshold.bl_idname,
icon=FillByThreshold.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(FillByRange.bl_idname,
icon=FillByRange.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(FillByLabel.bl_idname,
icon=FillByLabel.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(CombineLabels.bl_idname,
icon=CombineLabels.bl_icon)
op.layer_obj_name = active_obj_name
class RenderSettingMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_RENDER"
bl_label = "Render Setting Presets"
def draw(self, context):
layout = self.layout
is_selected = container_is_selected()
layout.operator(ImportAsScalarLayer.bl_idname,
text=ImportAsScalarLayer.bl_label+" (Add to)"
if is_selected else ImportAsScalarLayer.bl_label+" (Init)")
layout.operator(ImportAsLabelLayer.bl_idname,
text=ImportAsLabelLayer.bl_label+" (Add to)"
if is_selected else ImportAsLabelLayer.bl_label+" (Init)")
layout.separator()
layout.operator(AddPlaneCutter.bl_idname)
layout.operator(AddCylinderCutter.bl_idname)
layout.operator(AddCubeCutter.bl_idname)
layout.operator(AddSphereCutter.bl_idname)
layout.operator(AddPieCutter.bl_idname)
layout.separator()
layout.operator(PickMesh.bl_idname)
layout.operator(PickVolume.bl_idname)
layout.operator(PickBboxWire.bl_idname)
layout.separator()
layout.operator(SaveCaches.bl_idname)
layout.separator()
layout.operator(SignScalar.bl_idname)
layout.operator(FillByThreshold.bl_idname)
layout.operator(FillByRange.bl_idname)
layout.operator(FillByLabel.bl_idname)
layout.operator(CombineLabels.bl_idname)
def TOPBAR_FILE_IMPORT(self, context):
layout = self.layout
is_selected = container_is_selected()
layout.separator()
layout.menu(ImportLayerMenu.bl_idname, text="Volumetric Data as Bioxel (Add to)"
if is_selected else "Volumetric Data as Bioxel (Init)")
def TOPBAR_FILE_EXPORT(self, context):
layout = self.layout
layout.separator()
layout.operator(ExportVolumetricData.bl_idname,
text="Bioxel Layer (.vdb)")
def VIEW3D_OBJECT(self, context):
layout = self.layout
layout.separator()
layout.menu(BioxelNodesView3DMenu.bl_idname, icon="FILE_VOLUME")
def OUTLINER_OBJECT(self, context):
layout = self.layout
layout.separator()
layout.menu(BioxelNodesOutlinerMenu.bl_idname, icon="FILE_VOLUME")
for k, v in RenderSettingPreset.PRESETS.items():
op = layout.operator(RenderSettingPreset.bl_idname,
text=v)
op.preset = k
class BioxelNodesTopbarMenu(bpy.types.Menu):
@@ -159,39 +124,174 @@ class BioxelNodesTopbarMenu(bpy.types.Menu):
def draw(self, context):
layout = self.layout
is_selected = container_is_selected()
layout.menu(ImportLayerMenu.bl_idname, text=ImportLayerMenu.bl_label+" (Add to)"
if is_selected else ImportLayerMenu.bl_label+" (Init)")
layout.separator()
layout.menu(ImportLayerMenu.bl_idname,
icon=ImportLayerMenu.bl_icon)
layout.operator(LoadContainer.bl_idname)
layout.operator(SaveContainer.bl_idname)
layout.separator()
layout.menu(AddCutterMenu.bl_idname)
layout.menu(PickFromContainerMenu.bl_idname)
layout.separator()
layout.operator(SaveStagedData.bl_idname)
layout.operator(ReLinkNodes.bl_idname)
layout.separator()
layout.operator(CleanAllCaches.bl_idname)
layout.separator()
layout.menu(RenderSettingMenu.bl_idname)
def TOPBAR(self, context):
layout = self.layout
layout.menu(BioxelNodesTopbarMenu.bl_idname)
class BioxelNodesNodeMenu(bpy.types.Menu):
bl_idname = "BIOXELNODES_MT_NODE"
bl_label = "Bioxel Nodes"
bl_icon = "FILE_VOLUME"
def draw(self, context):
layer_objs = get_selected_objs_in_node_tree(context)
if len(layer_objs) > 0:
active_obj_name = layer_objs[0].name
else:
active_obj_name = ""
layout = self.layout
layout.menu(AddLayerMenu.bl_idname,
icon=AddLayerMenu.bl_icon)
layout.operator(RemoveMissingLayers.bl_idname,
icon=RemoveMissingLayers.bl_icon)
layout.separator()
layout.operator(SaveContainer.bl_idname)
layout.menu(AddCutterMenu.bl_idname)
layout.menu(PickFromContainerMenu.bl_idname)
layout.operator(SaveAllLayerCaches.bl_idname,
icon=SaveAllLayerCaches.bl_icon)
layout.separator()
layout.menu(FetchLayerMenu.bl_idname)
op = layout.operator(SaveLayerCache.bl_idname,
icon=SaveLayerCache.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(RenameLayer.bl_idname,
icon=RenameLayer.bl_icon)
op.layer_obj_name = active_obj_name
op = layout.operator(RemoveLayer.bl_idname,
icon=RemoveLayer.bl_icon)
op.layer_obj_name = active_obj_name
layout.separator()
layout.menu(ModifyLayerMenu.bl_idname)
def NODE(self, context):
container_obj = context.object
is_geo_nodes = context.area.ui_type == "GeometryNodeTree"
is_container = get_container_obj(container_obj)
if not is_geo_nodes or not is_container:
return
layout = self.layout
layout.separator()
layout.menu(BioxelNodesNodeMenu.bl_idname)
def NODE_PT(self, context):
container_obj = context.object
is_geo_nodes = context.area.ui_type == "GeometryNodeTree"
is_container = get_container_obj(container_obj)
self.bl_label = "Group"
if not is_geo_nodes or not is_container:
return
if container_obj.modifiers[0].node_group != context.space_data.edit_tree:
return
self.bl_label = "Bioxel Nodes"
layer_list_UL = bpy.context.window_manager.bioxelnodes_layer_list_UL
layer_list = layer_list_UL.layer_list
layer_list_active = layer_list_UL.layer_list_active
layer_list.clear()
for layer_obj in get_container_layer_objs(container_obj):
layer_item = layer_list.add()
layer_item.label = get_layer_item_label(context, layer_obj)
layer_item.obj_name = layer_obj.name
layer_item.info_text = "\n".join([f"{prop}: {get_layer_prop_value(layer_obj, prop)}"
for prop in ["kind", "bioxel_size", "shape", "min", "max", ]])
if len(layer_list) > 0 and layer_list_active != -1 and layer_list_active < len(layer_list):
active_obj_name = layer_list[layer_list_active].obj_name
else:
active_obj_name = ""
layout = self.layout
layout.label(text="Layer List")
split = layout.row()
split.template_list(listtype_name="BIOXELNODES_UL_layer_list",
list_id="layer_list",
dataptr=layer_list_UL,
propname="layer_list",
active_dataptr=layer_list_UL,
active_propname="layer_list_active",
item_dyntip_propname="info_text",
rows=20)
sidebar = split.column(align=True)
sidebar.menu(AddLayerMenu.bl_idname,
icon=AddLayerMenu.bl_icon, text="")
sidebar.operator(RemoveMissingLayers.bl_idname,
icon=RemoveMissingLayers.bl_icon, text="")
sidebar.separator()
op = sidebar.operator(FetchLayer.bl_idname,
icon=FetchLayer.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(SaveLayerCache.bl_idname,
icon=SaveLayerCache.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(RenameLayer.bl_idname,
icon=RenameLayer.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(RemoveLayer.bl_idname,
icon=RemoveLayer.bl_icon, text="")
op.layer_obj_name = active_obj_name
sidebar.separator()
op = sidebar.operator(ResampleScalar.bl_idname,
icon=ResampleScalar.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(SignScalar.bl_idname,
icon=SignScalar.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(FillByThreshold.bl_idname,
icon=FillByThreshold.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(FillByRange.bl_idname,
icon=FillByRange.bl_icon, text="")
op.layer_obj_name = active_obj_name
op = sidebar.operator(FillByLabel.bl_idname,
icon=FillByLabel.bl_icon, text="")
op.layer_obj_name = active_obj_name
sidebar.separator()
layout.separator()
def add():
bpy.types.TOPBAR_MT_file_import.append(TOPBAR_FILE_IMPORT)
# bpy.types.TOPBAR_MT_file_export.append(TOPBAR_FILE_EXPORT)
bpy.types.OUTLINER_MT_object.append(OUTLINER_OBJECT)
bpy.types.VIEW3D_MT_object_context_menu.append(VIEW3D_OBJECT)
bpy.types.NODE_PT_node_tree_properties.prepend(NODE_PT)
bpy.types.TOPBAR_MT_editor_menus.append(TOPBAR)
bpy.types.NODE_MT_editor_menus.append(NODE)
def remove():
bpy.types.TOPBAR_MT_file_import.remove(TOPBAR_FILE_IMPORT)
# bpy.types.TOPBAR_MT_file_export.remove(TOPBAR_FILE_EXPORT)
bpy.types.OUTLINER_MT_object.remove(OUTLINER_OBJECT)
bpy.types.VIEW3D_MT_object_context_menu.remove(VIEW3D_OBJECT)
bpy.types.NODE_PT_node_tree_properties.remove(NODE_PT)
bpy.types.TOPBAR_MT_editor_menus.remove(TOPBAR)
bpy.types.NODE_MT_editor_menus.remove(NODE)