from pathlib import Path import bpy 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 (ImportAsLabel, ImportAsScalar, ImportAsColor) from .operators.misc import (CleanAllCaches, ReLinkNodes, RenderSettingPreset, SaveStagedData) class PickFromContainerMenu(bpy.types.Menu): bl_idname = "BIOXELNODES_MT_PICK" bl_label = "Pick from Container" def draw(self, context): layout = self.layout layout.operator(PickMesh.bl_idname) layout.operator(PickVolume.bl_idname) layout.operator(PickBboxWire.bl_idname) class AddCutterMenu(bpy.types.Menu): bl_idname = "BIOXELNODES_MT_CUTTERS" bl_label = "Add a Object Cutter" def draw(self, context): layout = self.layout layout.operator(AddPlaneCutter.bl_idname, text="Plane Cutter") layout.operator(AddCylinderCutter.bl_idname, text="Cylinder Cutter") layout.operator(AddCubeCutter.bl_idname, text="Cube Cutter") layout.operator(AddSphereCutter.bl_idname, text="Sphere Cutter") layout.operator(AddPieCutter.bl_idname, text="Pie Cutter") class ImportLayerMenu(bpy.types.Menu): bl_idname = "BIOXELNODES_MT_IMPORTLAYER" bl_label = "Import Volumetric Data (Init)" bl_icon = "FILE_NEW" def draw(self, context): layout = self.layout 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 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 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 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 for k, v in RenderSettingPreset.PRESETS.items(): op = layout.operator(RenderSettingPreset.bl_idname, text=v) op.preset = k class BioxelNodesTopbarMenu(bpy.types.Menu): bl_idname = "BIOXELNODES_MT_TOPBAR" bl_label = "Bioxel Nodes" def draw(self, context): layout = self.layout layout.menu(ImportLayerMenu.bl_idname, icon=ImportLayerMenu.bl_icon) layout.operator(LoadContainer.bl_idname) layout.separator() layout.operator(SaveStagedData.bl_idname) layout.operator(ReLinkNodes.bl_idname) 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.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.NODE_PT_node_tree_properties.remove(NODE_PT) bpy.types.TOPBAR_MT_editor_menus.remove(TOPBAR) bpy.types.NODE_MT_editor_menus.remove(NODE)