diff --git a/bioxelnodes/assets/Nodes.blend b/bioxelnodes/assets/Nodes/BioxelNodes.blend similarity index 100% rename from bioxelnodes/assets/Nodes.blend rename to bioxelnodes/assets/Nodes/BioxelNodes.blend diff --git a/bioxelnodes/customnodes/menu.py b/bioxelnodes/customnodes/menu.py index d9f115a..896c606 100644 --- a/bioxelnodes/customnodes/menu.py +++ b/bioxelnodes/customnodes/menu.py @@ -1,7 +1,64 @@ +import shutil import bpy from pathlib import Path from .nodes import AddCustomNode +bpy.types.Scene.custom_nodes_dir = bpy.props.StringProperty( + name="Nodes Directory", + subtype='DIR_PATH', + default="//" +) + + +class SaveAllNodes(bpy.types.Operator): + bl_idname = "customnodes.save_all_nodes" + bl_label = "Save All Custom Nodes" + bl_description = "Save All Custom Nodes to Directory." + bl_options = {'UNDO'} + + def execute(self, context): + files = [] + for classname in dir(bpy.types): + if "CUSTOMNODES_MT_NODES_" in classname: + cls = getattr(bpy.types, classname) + files.append(cls.nodes_file) + files = list(set(files)) + + for file in files: + file_name = Path(file).name + # "//" + custom_nodes_dir = bpy.path.abspath(context.scene.custom_nodes_dir) + + output_path: Path = Path(custom_nodes_dir, file_name).resolve() + source_path: Path = Path(file).resolve() + + if output_path != source_path: + shutil.copy(source_path, output_path) + + for lib in bpy.data.libraries: + if lib.filepath == file: + blend_path = Path(bpy.path.abspath("//")).resolve() + lib.filepath = bpy.path.relpath( + str(output_path), start=str(blend_path)) + + self.report({"INFO"}, f"Successfully saved to {output_path}") + + return {'FINISHED'} + + +class CUSTOMNODES_PT_CustomNodes(bpy.types.Panel): + bl_idname = "CUSTOMNODES_PT_CustomNodes" + bl_label = "Custom Nodes" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + def draw(self, context): + layout = self.layout + scene = context.scene + layout.prop(scene, 'custom_nodes_dir') + layout.operator(SaveAllNodes.bl_idname) + class CustomNodes(): def __init__( @@ -60,6 +117,7 @@ class CustomNodes(): class Menu(bpy.types.Menu): bl_idname = idname bl_label = label + nodes_file = self.nodes_file def draw(self, context): layout = self.layout diff --git a/bioxelnodes/misc.py b/bioxelnodes/misc.py index a6183a8..56d3bfc 100644 --- a/bioxelnodes/misc.py +++ b/bioxelnodes/misc.py @@ -1,22 +1,9 @@ from pathlib import Path import shutil -from bioxelnodes.utils import get_bioxels_obj +from bioxelnodes.utils import get_all_bioxels_objs, get_bioxels_obj import bpy -class BIOXELNODES_PT_Bioxels(bpy.types.Panel): - bl_idname = "BIOXELNODES_PT_Bioxels" - bl_label = "Bioxels" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "scene" - - def draw(self, context): - layout = self.layout - scene = context.scene - layout.prop(scene, 'bioxels_dir') - - class SaveBioxels(bpy.types.Operator): bl_idname = "bioxelnodes.save_bioxels" bl_label = "Save Bioxels" @@ -60,6 +47,57 @@ class SaveBioxels(bpy.types.Operator): blend_path = Path(bpy.path.abspath("//")).resolve() bioxels_obj.data.filepath = bpy.path.relpath( str(output_path), start=str(blend_path)) - self.report({"INFO"}, f"Successfully saved to {output_path}") + + self.report({"INFO"}, f"Successfully saved bioxels") return {'FINISHED'} + + +class SaveAllBioxels(bpy.types.Operator): + bl_idname = "bioxelnodes.save_all_bioxels" + bl_label = "Save All Bioxels" + bl_description = "Save All Bioxels to Directory." + bl_options = {'UNDO'} + + def execute(self, context): + + bioxels_objs = get_all_bioxels_objs() + + if len(bioxels_objs) == 0: + self.report({"WARNING"}, "Cannot find any bioxels.") + return {'FINISHED'} + + for bioxels_obj in bioxels_objs: + name = bioxels_obj.parent.name + + # "//" + bioxels_dir = bpy.path.abspath(context.scene.bioxels_dir) + source_dir = bpy.path.abspath(bioxels_obj.data.filepath) + + output_path: Path = Path(bioxels_dir, f"{name}.vdb").resolve() + source_path: Path = Path(source_dir).resolve() + + if output_path != source_path: + shutil.copy(source_path, output_path) + + blend_path = Path(bpy.path.abspath("//")).resolve() + bioxels_obj.data.filepath = bpy.path.relpath( + str(output_path), start=str(blend_path)) + + self.report({"INFO"}, f"Successfully saved bioxels") + + return {'FINISHED'} + + +class BIOXELNODES_PT_Bioxels(bpy.types.Panel): + bl_idname = "BIOXELNODES_PT_Bioxels" + bl_label = "Bioxels" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + def draw(self, context): + layout = self.layout + scene = context.scene + layout.prop(scene, 'bioxels_dir') + layout.operator(SaveAllBioxels.bl_idname) diff --git a/bioxelnodes/nodes.py b/bioxelnodes/nodes.py index a6374b7..51edcca 100644 --- a/bioxelnodes/nodes.py +++ b/bioxelnodes/nodes.py @@ -141,7 +141,7 @@ MENU_ITEMS = [ custom_nodes = CustomNodes( menu_items=MENU_ITEMS, - nodes_file=Path(__file__).parent/"assets/Nodes.blend", + nodes_file=Path(__file__).parent/"assets/Nodes/BioxelNodes.blend", root_label='Bioxel Nodes', root_icon="FILE_VOLUME", ) diff --git a/bioxelnodes/utils.py b/bioxelnodes/utils.py index f7cd674..b00b070 100644 --- a/bioxelnodes/utils.py +++ b/bioxelnodes/utils.py @@ -81,6 +81,15 @@ def get_bioxels_obj(current_obj): return bioxels_obj +def get_all_bioxels_objs(): + bioxels_objs = [] + + for obj in bpy.data.objects: + if obj.parent: + if obj.parent.get('bioxels_container') and obj.get('bioxels'): + bioxels_objs.append(obj) + + return list(set(bioxels_objs)) def extract_last_number(text): # Initialize an empty string to store the digits