clean + add collection

master
christophe.seux 2024-10-03 12:07:33 +02:00
parent ed2063f705
commit f1aaa1dfca
6 changed files with 96 additions and 87 deletions

View File

@ -6,12 +6,12 @@ from .properties import CustomShelfProps
class Types(): class Types():
def initialyse(self,label) : def initialyse(self, label) :
package = __package__.replace('_','').replace('-','').lower() package = __package__.replace('_','').replace('-','').lower()
idname = label.replace(' ','_').replace('-','_').lower() idname = label.replace(' ','_').replace('-','_').lower()
self.bl_label = title(label) 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.bl_props = bpy.context.scene.CustomShelf
#self.prefs = "" #self.prefs = ""
@ -19,24 +19,23 @@ class Types():
class CSHELF_OT_shelf_popup(Types,Operator) : class CSHELF_OT_shelf_popup(Types, Operator):
#props = None #props = None
bl_options = {'REGISTER', 'UNDO'}
@property @property
def props(self) : def props(self) :
#print(getattr(bpy.context.window_manager.CustomShelf,self.prop)) #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): def get_props(self):
properties = self.props.bl_rna.properties properties = self.props.bl_rna.properties
#props = #props =
return {k:v for k,v in self.args.items() if k in properties} return {k:v for k,v in self.args.items() if k in properties}
def set_props(self,prop,value): def set_props(self,prop,value):
setattr(bpy.context.window_manager.CustomShelf,prop,value) setattr(bpy.context.window_manager.CustomShelf,prop,value)
def initialyse(self,label,info) : def initialyse(self,label,info) :
super().initialyse(CSHELF_OT_shelf_popup,label) 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)}) Props = type("props",(PropertyGroup,),{'__annotations__' : dict(self.args)})
bpy.utils.register_class(Props) 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.props = getattr(bpy.context.window_manager,self.bl_idname)
self.info = info self.info = info
self.prop = arg_name(label) self.prop = arg_name(label)
@ -119,9 +118,7 @@ class CSHELF_OT_shelf_popup(Types,Operator) :
print(*args) print(*args)
def execute(self,context): def execute(self,context):
import tempfile info, lines = read_info(self.script)
info,lines = read_info(self.script)
values = dict(info) values = dict(info)
for arg in self.args : for arg in self.args :
@ -136,16 +133,11 @@ class CSHELF_OT_shelf_popup(Types,Operator) :
else : else :
values[arg] = value values[arg] = value
info_str = "info = %s\n\n"%values info_str = "info = %s\n\n"%values
lines_str = '\n'.join(lines)
script = f"{info_str}\n\n{lines_str}"
tmp_folder = tempfile.gettempdir() exec(script, {'info': values, 'print': self.bl_report})
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})
return {'FINISHED'} return {'FINISHED'}

View File

@ -3,7 +3,7 @@ bl_info = {
"author": "Christophe Seux", "author": "Christophe Seux",
"description": "Adds buttons to launch custom python scripts in the User panel.", "description": "Adds buttons to launch custom python scripts in the User panel.",
"version": (0, 3, 2), "version": (0, 3, 2),
"blender": (2, 82, 0), "blender": (4, 0, 2),
"location": "View3D > User Panel", "location": "View3D > User Panel",
"doc_url": "https://gitlab.com/autour-de-minuit/blender/custom_shelf/-/blob/main/README.md", "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", "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(functions)
importlib.reload(properties) importlib.reload(properties)
from .utils import report from . utils import report
from .functions import read_shelves from . functions import read_shelves
from .import operators from . import operators
#from .import shelves from . import properties
from .import properties from . import ui
from .import panels
from .properties import CustomShelfSettings,CustomShelfProps from .properties import CustomShelfSettings,CustomShelfProps
import bpy import bpy
import os import os
class_to_register = [ bl_classes = [
properties.AdditionnalShelves, properties.AdditionnalShelves,
properties.CustomShelfProps, properties.CustomShelfProps,
properties.CustomShelfSettings, properties.CustomShelfSettings,
properties.CustomShelfPrefs, properties.CustomShelfPrefs,
operators.CSHELF_OT_refresh, operators.CSHELF_OT_refresh,
operators.CSHELF_OT_add_shelf_folder, operators.CSHELF_OT_add_shelf_folder,
operators.CSHELF_OT_remove_shelf_folder, operators.CSHELF_OT_remove_shelf_folder,
operators.CSHELF_OT_open_shelf_folder, operators.CSHELF_OT_open_shelf_folder,
operators.CSHELF_OT_add_script, operators.CSHELF_OT_add_script,
operators.CSHELF_OT_set_tag_filter, operators.CSHELF_OT_set_tag_filter,
panels.CSHELF_PT_text_editor ui.CSHELF_MT_text_editor
] ]
def draw_menu(self, context):
self.layout.menu('CSHELF_MT_text_editor')
def register(): def register():
for bl_classes in class_to_register : for bl_class in bl_classes :
bpy.utils.register_class(bl_classes) bpy.utils.register_class(bl_class)
bpy.types.Scene.CustomShelf = bpy.props.PointerProperty(type=CustomShelfSettings) bpy.types.Scene.CustomShelf = bpy.props.PointerProperty(type=CustomShelfSettings)
bpy.types.WindowManager.CustomShelf = bpy.props.PointerProperty(type=CustomShelfProps) bpy.types.WindowManager.CustomShelf = bpy.props.PointerProperty(type=CustomShelfProps)
bpy.types.TEXT_MT_editor_menus.append(draw_menu)
env_shelves = os.getenv("CUSTOM_SHELVES") env_shelves = os.getenv("CUSTOM_SHELVES")
if env_shelves: if env_shelves:
shelves = env_shelves.split(os.pathsep) shelves = env_shelves.split(os.pathsep)
@ -60,24 +65,24 @@ def register():
# prefs.additionnal_shelves.clear() # prefs.additionnal_shelves.clear()
for path in shelves: for path in shelves:
s = next((s for s in prefs.additionnal_shelves if s.path == path), None) shelf = next((s for s in prefs.additionnal_shelves if s.path == path), None)
if not s: if not shelf:
s = prefs.additionnal_shelves.add() shelf = prefs.additionnal_shelves.add()
s.path = path shelf.path = path
read_shelves() read_shelves()
def unregister(): def unregister():
# unregister panel : # unregister panel :
for p in CustomShelfSettings.panel_list : for panel in CustomShelfSettings.panel_list :
try : try :
bpy.utils.unregister_class(p) bpy.utils.unregister_class(panel)
except : except Exception:
pass pass
bpy.types.TEXT_MT_editor_menus.remove(draw_menu)
del bpy.types.Scene.CustomShelf del bpy.types.Scene.CustomShelf
del bpy.types.WindowManager.CustomShelf del bpy.types.WindowManager.CustomShelf
for bl_class in bl_classes :
for bl_classes in class_to_register : bpy.utils.unregister_class(bl_class)
bpy.utils.unregister_class(bl_classes)

View File

@ -74,13 +74,14 @@ def read_shelves() :
tag_filter_items = [] tag_filter_items = []
# unregister panel : # unregister panel :
for p in CustomShelfSettings.panel_list : for panel in CustomShelfSettings.panel_list:
if p.__name__ not in get_tabs() : print(panel)
if panel.__name__ not in get_tabs():
try : try :
bpy.utils.unregister_class(p) bpy.utils.unregister_class(panel)
except : except Exception:
pass pass
CustomShelfSettings.panel_list.remove(p) CustomShelfSettings.panel_list.remove(panel)
for cat in get_dirs(get_shelves_folder()) : for cat in get_dirs(get_shelves_folder()) :
@ -105,7 +106,7 @@ def read_shelves() :
PanelProps = type("CustomShelfPrefs",(PropertyGroup,),panel_props) PanelProps = type("CustomShelfPrefs",(PropertyGroup,),panel_props)
bpy.utils.register_class(PanelProps) bpy.utils.register_class(PanelProps)
setattr(CustomShelfPrefs,cat.name,PointerProperty(type = PanelProps)) setattr(CustomShelfPrefs, cat.name, PointerProperty(type=PanelProps))
#search and filter #search and filter
props = { props = {
@ -156,7 +157,10 @@ def read_shelves() :
scripts = [] scripts = []
for script in scandir(tab.path) : 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] script_name = splitext(script.name)[0]
@ -164,13 +168,14 @@ def read_shelves() :
info["description"] = info.get('description',"") 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 = type(script_name, (CSHELF_OT_shelf_popup,),
popup.initialyse(popup,script_name,info) {"script": script.path,
'bl_description': info["description"]
})
popup.initialyse(popup, script_name, info)
bpy.utils.register_class(popup) bpy.utils.register_class(popup)
scripts.append({"operator" : popup.bl_idname,"text" : script_name,"icon" : icon}) scripts.append({"operator" : popup.bl_idname,"text" : script_name,"icon" : icon})
panel.scripts = sorted(scripts,key = lambda x :x['text']) panel.scripts = sorted(scripts,key = lambda x :x['text'])

View File

@ -4,6 +4,7 @@ from bpy.types import Operator
from bpy.props import * from bpy.props import *
from .properties import CustomShelfSettings from .properties import CustomShelfSettings
class CSHELF_OT_refresh(Operator): class CSHELF_OT_refresh(Operator):
bl_idname = "customshelf.refresh" bl_idname = "customshelf.refresh"
bl_label = 'Refresh Shelves' bl_label = 'Refresh Shelves'
@ -85,6 +86,10 @@ class CSHELF_OT_add_script(Operator) :
icon : StringProperty() icon : StringProperty()
show_icons : BoolProperty() 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) : def add_folder(self,context,op) :
folder = self.folder.add() folder = self.folder.add()
folder.name = self.name folder.name = self.name
@ -153,11 +158,11 @@ class CSHELF_OT_add_script(Operator) :
if not i%12 : if not i%12 :
row = col.row(align= True) 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 i += 1
row = col.row(align= True) row = col.row(align= True)
layout.prop(self,"description",text="") layout.prop(self, "description", text="")
layout.separator() layout.separator()
#Category Row #Category Row
@ -258,7 +263,6 @@ class CSHELF_OT_add_script(Operator) :
if self.info.get('description') : if self.info.get('description') :
description = self.info["description"] description = self.info["description"]
self.icon = icon self.icon = icon
self.name = splitext(self.active_text.name)[0] self.name = splitext(self.active_text.name)[0]
self.show_icons = False self.show_icons = False
@ -268,16 +272,16 @@ class CSHELF_OT_add_script(Operator) :
self.new_shelf = "" self.new_shelf = ""
self.icons = [] self.icons = []
operator("get_icons",{'execute':self.get_icons}) operator("get_icons", {'execute': self.get_icons})
operator("set_icon",{'execute':self.set_icon,'icon':StringProperty()}) operator("set_icon", {'execute': self.set_icon, '__annotations__': {'icon' : StringProperty()}})
operator("add_folder",{'execute':self.add_folder}) operator("add_folder", {'execute': self.add_folder})
#operator("remove_folder",{'execute':self.remove_folder}) #operator("remove_folder",{'execute':self.remove_folder})
self.tabs = get_tabs() self.tabs = get_tabs()
self.categories = get_categories() self.categories = get_categories()
CustomShelfSettings.category_enum = EnumProperty(items = [(i,i,"") for i in self.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.tab_enum = EnumProperty(items=[(i,i,"") for i in self.tabs])
if self.active_text.filepath : if self.active_text.filepath :
tab_path = dirname(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 : if tab in self.tabs :
bl_props.tab_enum = tab 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)

View File

@ -1,21 +1,14 @@
from .utils import *
import bpy
class CSHELF_MT_text_editor(bpy.types.Menu):
class CSHELF_PT_text_editor(bpy.types.Panel): bl_label = "Shelves"
bl_space_type = "TEXT_EDITOR"
bl_region_type = "UI"
bl_category = "Dev"
bl_label = "Custom Shelf"
def draw(self, context): def draw(self, context):
layout = self.layout 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()

View File

@ -14,7 +14,7 @@ id_type = {"Action" : "actions", "Armature":"armatures", "Brush":"brushes", "Cac
"Material":"materials", "Mesh":"meshes", "MetaBall":"metaballs", "MovieClip":"movieclips", "NodeTree":"node_groups", "Material":"materials", "Mesh":"meshes", "MetaBall":"metaballs", "MovieClip":"movieclips", "NodeTree":"node_groups",
"Object":"objects", "PaintCurve":"paint_curves", "Palette":"palettes", "ParticleSettings":"particles", "Object":"objects", "PaintCurve":"paint_curves", "Palette":"palettes", "ParticleSettings":"particles",
"Scene":"scenes", "Screen":"screens", "Sound":"sounds", "Speaker":"speakers", "Text":"texts", "Texture":"textures", "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 import collections
args = collections.OrderedDict() 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): if k in ('icon','description') or not isinstance(k,str):
continue continue
@ -76,13 +83,13 @@ def dic_to_args(dic):
elif isinstance(v,bool) : elif isinstance(v,bool) :
args[k] = BoolProperty(default=v) args[k] = BoolProperty(default=v)
elif isinstance(v,float) : elif isinstance(v, float) :
args[k] = FloatProperty(default=v,precision=3) args[k] = FloatProperty(default=v,precision=3)
elif isinstance(v,int) : elif isinstance(v,int) :
args[k] = IntProperty(default=v) args[k] = IntProperty(default=v)
elif isinstance(v,dict) : elif isinstance(v, dict) :
if v.get("items") and isinstance(v["items"],(tuple,list)) : if v.get("items") and isinstance(v["items"],(tuple,list)) :
args[k] = EnumProperty(items = [(i,i,"") for i in v["items"]]) 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"])) #args[k] = PointerProperty(type = getattr(bpy.types,v["collection"]))
else : else :
args[k] = PointerProperty(type = getattr(bpy.types,v["collection"]),poll = v.get('poll')) args[k] = PointerProperty(type = getattr(bpy.types,v["collection"]),poll = v.get('poll'))
else:
args[k] = prop_type[type(v['default'])](**v)
return args return args