From f1aaa1dfcaad17c3e786b99811ef45cfbe9c91d5 Mon Sep 17 00:00:00 2001 From: "christophe.seux" Date: Thu, 3 Oct 2024 12:07:33 +0200 Subject: [PATCH] clean + add collection --- Types.py | 30 ++++++++------------- __init__.py | 67 +++++++++++++++++++++++++--------------------- functions.py | 29 +++++++++++--------- operators.py | 22 ++++++++------- panels.py => ui.py | 17 ++++-------- utils.py | 18 ++++++++++--- 6 files changed, 96 insertions(+), 87 deletions(-) rename panels.py => ui.py (84%) diff --git a/Types.py b/Types.py index d1b9d0c..8be72be 100644 --- a/Types.py +++ b/Types.py @@ -6,12 +6,12 @@ from .properties import CustomShelfProps class Types(): - def initialyse(self,label) : + def initialyse(self, label) : package = __package__.replace('_','').replace('-','').lower() idname = label.replace(' ','_').replace('-','_').lower() self.bl_label = title(label) - self.bl_idname = '%s.%s'%(package,idname) + self.bl_idname = '%s.%s'%(package, idname) #self.bl_props = bpy.context.scene.CustomShelf #self.prefs = "" @@ -19,24 +19,23 @@ class Types(): -class CSHELF_OT_shelf_popup(Types,Operator) : +class CSHELF_OT_shelf_popup(Types, Operator): #props = None + bl_options = {'REGISTER', 'UNDO'} + @property def props(self) : #print(getattr(bpy.context.window_manager.CustomShelf,self.prop)) - return getattr(bpy.context.window_manager.CustomShelf,self.prop) + return getattr(bpy.context.window_manager.CustomShelf, self.prop) def get_props(self): properties = self.props.bl_rna.properties #props = return {k:v for k,v in self.args.items() if k in properties} - - def set_props(self,prop,value): setattr(bpy.context.window_manager.CustomShelf,prop,value) - def initialyse(self,label,info) : super().initialyse(CSHELF_OT_shelf_popup,label) @@ -46,7 +45,7 @@ class CSHELF_OT_shelf_popup(Types,Operator) : Props = type("props",(PropertyGroup,),{'__annotations__' : dict(self.args)}) bpy.utils.register_class(Props) - setattr(CustomShelfProps,arg_name(label),PointerProperty(type=Props)) + setattr(CustomShelfProps, arg_name(label), PointerProperty(type=Props)) #self.props = getattr(bpy.context.window_manager,self.bl_idname) self.info = info self.prop = arg_name(label) @@ -119,9 +118,7 @@ class CSHELF_OT_shelf_popup(Types,Operator) : print(*args) def execute(self,context): - import tempfile - - info,lines = read_info(self.script) + info, lines = read_info(self.script) values = dict(info) for arg in self.args : @@ -136,16 +133,11 @@ class CSHELF_OT_shelf_popup(Types,Operator) : else : values[arg] = value - info_str = "info = %s\n\n"%values + lines_str = '\n'.join(lines) + script = f"{info_str}\n\n{lines_str}" - tmp_folder = tempfile.gettempdir() - script_path = join(tmp_folder, "shelf.py") - - with open(script_path,"w",encoding = 'utf-8') as f : - f.write(info_str+'\n'.join(lines)) - - exec(compile(open(script_path,encoding = 'utf-8').read(), script_path, 'exec'),{'info' : values,'print':self.bl_report}) + exec(script, {'info': values, 'print': self.bl_report}) return {'FINISHED'} diff --git a/__init__.py b/__init__.py index 79da1ab..98fd004 100644 --- a/__init__.py +++ b/__init__.py @@ -3,7 +3,7 @@ bl_info = { "author": "Christophe Seux", "description": "Adds buttons to launch custom python scripts in the User panel.", "version": (0, 3, 2), - "blender": (2, 82, 0), + "blender": (4, 0, 2), "location": "View3D > User Panel", "doc_url": "https://gitlab.com/autour-de-minuit/blender/custom_shelf/-/blob/main/README.md", "tracker_url": "https://gitlab.com/autour-de-minuit/blender/custom_shelf/-/issues", @@ -19,39 +19,44 @@ if "bpy" in locals(): importlib.reload(functions) importlib.reload(properties) -from .utils import report -from .functions import read_shelves -from .import operators -#from .import shelves -from .import properties -from .import panels +from . utils import report +from . functions import read_shelves +from . import operators +from . import properties +from . import ui from .properties import CustomShelfSettings,CustomShelfProps import bpy import os -class_to_register = [ -properties.AdditionnalShelves, -properties.CustomShelfProps, -properties.CustomShelfSettings, -properties.CustomShelfPrefs, -operators.CSHELF_OT_refresh, -operators.CSHELF_OT_add_shelf_folder, -operators.CSHELF_OT_remove_shelf_folder, -operators.CSHELF_OT_open_shelf_folder, -operators.CSHELF_OT_add_script, -operators.CSHELF_OT_set_tag_filter, -panels.CSHELF_PT_text_editor +bl_classes = [ + properties.AdditionnalShelves, + properties.CustomShelfProps, + properties.CustomShelfSettings, + properties.CustomShelfPrefs, + operators.CSHELF_OT_refresh, + operators.CSHELF_OT_add_shelf_folder, + operators.CSHELF_OT_remove_shelf_folder, + operators.CSHELF_OT_open_shelf_folder, + operators.CSHELF_OT_add_script, + operators.CSHELF_OT_set_tag_filter, + ui.CSHELF_MT_text_editor ] +def draw_menu(self, context): + self.layout.menu('CSHELF_MT_text_editor') + + def register(): - for bl_classes in class_to_register : - bpy.utils.register_class(bl_classes) + for bl_class in bl_classes : + bpy.utils.register_class(bl_class) bpy.types.Scene.CustomShelf = bpy.props.PointerProperty(type=CustomShelfSettings) bpy.types.WindowManager.CustomShelf = bpy.props.PointerProperty(type=CustomShelfProps) + bpy.types.TEXT_MT_editor_menus.append(draw_menu) + env_shelves = os.getenv("CUSTOM_SHELVES") if env_shelves: shelves = env_shelves.split(os.pathsep) @@ -60,24 +65,24 @@ def register(): # prefs.additionnal_shelves.clear() for path in shelves: - s = next((s for s in prefs.additionnal_shelves if s.path == path), None) - if not s: - s = prefs.additionnal_shelves.add() - s.path = path + shelf = next((s for s in prefs.additionnal_shelves if s.path == path), None) + if not shelf: + shelf = prefs.additionnal_shelves.add() + shelf.path = path read_shelves() def unregister(): # unregister panel : - for p in CustomShelfSettings.panel_list : + for panel in CustomShelfSettings.panel_list : try : - bpy.utils.unregister_class(p) - except : + bpy.utils.unregister_class(panel) + except Exception: pass + bpy.types.TEXT_MT_editor_menus.remove(draw_menu) del bpy.types.Scene.CustomShelf del bpy.types.WindowManager.CustomShelf - - for bl_classes in class_to_register : - bpy.utils.unregister_class(bl_classes) + for bl_class in bl_classes : + bpy.utils.unregister_class(bl_class) diff --git a/functions.py b/functions.py index 0b70a73..f5fad7b 100644 --- a/functions.py +++ b/functions.py @@ -74,13 +74,14 @@ def read_shelves() : tag_filter_items = [] # unregister panel : - for p in CustomShelfSettings.panel_list : - if p.__name__ not in get_tabs() : + for panel in CustomShelfSettings.panel_list: + print(panel) + if panel.__name__ not in get_tabs(): try : - bpy.utils.unregister_class(p) - except : + bpy.utils.unregister_class(panel) + except Exception: pass - CustomShelfSettings.panel_list.remove(p) + CustomShelfSettings.panel_list.remove(panel) for cat in get_dirs(get_shelves_folder()) : @@ -105,7 +106,7 @@ def read_shelves() : PanelProps = type("CustomShelfPrefs",(PropertyGroup,),panel_props) bpy.utils.register_class(PanelProps) - setattr(CustomShelfPrefs,cat.name,PointerProperty(type = PanelProps)) + setattr(CustomShelfPrefs, cat.name, PointerProperty(type=PanelProps)) #search and filter props = { @@ -156,7 +157,10 @@ def read_shelves() : scripts = [] for script in scandir(tab.path) : - if not script.name.endswith('.py') : continue + if not script.name.endswith('.py'): + continue + + print(script.path) script_name = splitext(script.name)[0] @@ -164,13 +168,14 @@ def read_shelves() : info["description"] = info.get('description',"") - icon = info.get('icon',"WORDWRAP_OFF") + icon = info.get('icon', "WORDWRAP_OFF") - popup = type(script_name,(CSHELF_OT_shelf_popup,),{"script":script.path,'bl_description':info["description"]}) - popup.initialyse(popup,script_name,info) + popup = type(script_name, (CSHELF_OT_shelf_popup,), + {"script": script.path, + 'bl_description': info["description"] + }) + popup.initialyse(popup, script_name, info) bpy.utils.register_class(popup) - - scripts.append({"operator" : popup.bl_idname,"text" : script_name,"icon" : icon}) panel.scripts = sorted(scripts,key = lambda x :x['text']) diff --git a/operators.py b/operators.py index 6a98c6b..d4d2aae 100644 --- a/operators.py +++ b/operators.py @@ -4,6 +4,7 @@ from bpy.types import Operator from bpy.props import * from .properties import CustomShelfSettings + class CSHELF_OT_refresh(Operator): bl_idname = "customshelf.refresh" bl_label = 'Refresh Shelves' @@ -85,6 +86,10 @@ class CSHELF_OT_add_script(Operator) : icon : StringProperty() show_icons : BoolProperty() + @classmethod + def poll(cls, context): + return context.area.type == 'TEXT_EDITOR' and context.space_data.text + def add_folder(self,context,op) : folder = self.folder.add() folder.name = self.name @@ -153,11 +158,11 @@ class CSHELF_OT_add_script(Operator) : if not i%12 : row = col.row(align= True) - row.operator("customshelf.set_icon",icon=icon,emboss = False,text="").icon = icon + row.operator("customshelf.set_icon", icon=icon, emboss=False, text="").icon=icon i += 1 row = col.row(align= True) - layout.prop(self,"description",text="") + layout.prop(self, "description", text="") layout.separator() #Category Row @@ -258,7 +263,6 @@ class CSHELF_OT_add_script(Operator) : if self.info.get('description') : description = self.info["description"] - self.icon = icon self.name = splitext(self.active_text.name)[0] self.show_icons = False @@ -268,16 +272,16 @@ class CSHELF_OT_add_script(Operator) : self.new_shelf = "" self.icons = [] - operator("get_icons",{'execute':self.get_icons}) - operator("set_icon",{'execute':self.set_icon,'icon':StringProperty()}) - operator("add_folder",{'execute':self.add_folder}) + operator("get_icons", {'execute': self.get_icons}) + operator("set_icon", {'execute': self.set_icon, '__annotations__': {'icon' : StringProperty()}}) + operator("add_folder", {'execute': self.add_folder}) #operator("remove_folder",{'execute':self.remove_folder}) self.tabs = get_tabs() self.categories = get_categories() - CustomShelfSettings.category_enum = EnumProperty(items = [(i,i,"") for i in self.categories]) - CustomShelfSettings.tab_enum = EnumProperty(items = [(i,i,"") for i in self.tabs]) + CustomShelfSettings.category_enum = EnumProperty(items=[(i,i,"") for i in self.categories]) + CustomShelfSettings.tab_enum = EnumProperty(items=[(i,i,"") for i in self.tabs]) if self.active_text.filepath : tab_path = dirname(self.active_text.filepath) @@ -289,4 +293,4 @@ class CSHELF_OT_add_script(Operator) : if tab in self.tabs : bl_props.tab_enum = tab - return context.window_manager.invoke_props_dialog(self,width = 500) + return context.window_manager.invoke_props_dialog(self, width=500) diff --git a/panels.py b/ui.py similarity index 84% rename from panels.py rename to ui.py index 5ac6074..74d0b89 100644 --- a/panels.py +++ b/ui.py @@ -1,21 +1,14 @@ -from .utils import * + +import bpy - -class CSHELF_PT_text_editor(bpy.types.Panel): - bl_space_type = "TEXT_EDITOR" - bl_region_type = "UI" - bl_category = "Dev" - bl_label = "Custom Shelf" +class CSHELF_MT_text_editor(bpy.types.Menu): + bl_label = "Shelves" def draw(self, context): layout = self.layout - shelves = bpy.context.scene.CustomShelf + layout.operator("customshelf.add_script", text='Add Script', icon="FILE_NEW") - row = layout.row(align = True) - - row.operator("customshelf.add_script", text='Add Script',emboss=True,icon= "LONGDISPLAY") - row.separator() diff --git a/utils.py b/utils.py index 8004936..531a374 100644 --- a/utils.py +++ b/utils.py @@ -14,7 +14,7 @@ id_type = {"Action" : "actions", "Armature":"armatures", "Brush":"brushes", "Cac "Material":"materials", "Mesh":"meshes", "MetaBall":"metaballs", "MovieClip":"movieclips", "NodeTree":"node_groups", "Object":"objects", "PaintCurve":"paint_curves", "Palette":"palettes", "ParticleSettings":"particles", "Scene":"scenes", "Screen":"screens", "Sound":"sounds", "Speaker":"speakers", "Text":"texts", "Texture":"textures", - "VectorFont":"fonts", "WindowManager":"window_managers", "World":"worlds"} + "Collection":"collections", "VectorFont":"fonts", "WindowManager":"window_managers", "World":"worlds"} @@ -63,7 +63,14 @@ def dic_to_args(dic): import collections args = collections.OrderedDict() - for k,v in dic.items() : + prop_type = { + str: StringProperty, + bool: BoolProperty, + float: FloatProperty, + int : IntProperty + } + + for k, v in dic.items() : if k in ('icon','description') or not isinstance(k,str): continue @@ -76,13 +83,13 @@ def dic_to_args(dic): elif isinstance(v,bool) : args[k] = BoolProperty(default=v) - elif isinstance(v,float) : + elif isinstance(v, float) : args[k] = FloatProperty(default=v,precision=3) elif isinstance(v,int) : args[k] = IntProperty(default=v) - elif isinstance(v,dict) : + elif isinstance(v, dict) : if v.get("items") and isinstance(v["items"],(tuple,list)) : args[k] = EnumProperty(items = [(i,i,"") for i in v["items"]]) @@ -92,6 +99,9 @@ def dic_to_args(dic): #args[k] = PointerProperty(type = getattr(bpy.types,v["collection"])) else : args[k] = PointerProperty(type = getattr(bpy.types,v["collection"]),poll = v.get('poll')) + else: + args[k] = prop_type[type(v['default'])](**v) + return args