from os import scandir from posixpath import splitext from .utils import * from bpy.props import * from bpy.types import Panel, Operator from .properties import CustomShelfSettings, CustomShelfPrefs from .Types import * from os.path import join, dirname, exists SHELF_DIR = join(dirname(__file__), "shelves") def operator(idname, args): op_execute = args["execute"] def execute(self, context): op_execute(context, self) return {"FINISHED"} package = __package__.replace("_", "").replace("-", "").lower() args["bl_idname"] = "%s.%s" % (package, idname) args["bl_label"] = title(idname) args["execute"] = execute op = type("operator", (Operator,), args) bpy.utils.register_class(op) return op def register_bl_class(bl_class, args): a = type("test", (bl_class,), {}) a.initialyse(a, *args) bpy.utils.register_class(a) return a def filter_dir(dir_list): return [d for d in dir_list if d.is_dir() and not d.name.startswith("_")] def get_shelves_folder(): prefs = bpy.context.preferences.addons[__package__].preferences shelves_path = prefs.global_shelves additionnal_shelves_path = [s.path for s in prefs.additionnal_shelves] return [p for p in additionnal_shelves_path + [shelves_path] if exists(p)] def get_dirs(paths): if isinstance(paths, (tuple, list)): dirs = [] for dir in paths: if not isinstance(dir, str): dir = dir.path dirs += filter_dir(scandir(dir)) return dirs else: return filter_dir(scandir(paths)) def get_categories(): return [d.name for d in get_dirs(get_shelves_folder())] def get_tabs(): return [d.name for d in get_dirs(get_dirs(get_shelves_folder()))] def get_category_path(category): category_dir = [ f for f in get_shelves_folder() if category in [d.name for d in get_dirs(f)] ] if category_dir: return join(category_dir[0], category) def get_category_tabs(category): return [d.name for d in get_dirs(get_category_path(category))] def read_shelves(): tag_filter_items = [] # unregister panel : for panel in CustomShelfSettings.panel_list: print(panel) if panel.__name__ not in get_tabs(): try: bpy.utils.unregister_class(panel) except Exception: pass CustomShelfSettings.panel_list.remove(panel) for cat in get_dirs(get_shelves_folder()): cat_name = cat.name.replace("_", " ").title() header_info = { "bl_region_type": "UI", # petit ajout pour voir si foncitonne... "bl_category": cat_name, "bl_idname": "%s_PT_%s_header" % (__package__.upper(), cat.name), # -> "%s.%s_header" makes _PT_ warning "cat": cat.name, "path": cat.path, } header = type("Header", (CSHELF_PT_shelf_header,), header_info) bpy.utils.register_class(header) # enable bool prefs # panel_props = {t.name : BoolProperty(default = False) for t in get_dirs(cat.path)}# give "should be an annotation" field warning ## need annoattion type : https://blender.stackexchange.com/questions/118118/blender-2-8-field-property-declaration-and-dynamic-class-creation panel_props = { "__annotations__": { t.name: BoolProperty(default=False) for t in get_dirs(cat.path) } } PanelProps = type("CustomShelfPrefs", (PropertyGroup,), panel_props) bpy.utils.register_class(PanelProps) setattr(CustomShelfPrefs, cat.name, PointerProperty(type=PanelProps)) # search and filter props = { "search": StringProperty(options={"TEXTEDIT_UPDATE"}), "filter": BoolProperty(default=True), } # Props = type("props",(PropertyGroup,), props)# annotation error Props = type("props", (PropertyGroup,), {"__annotations__": props}) bpy.utils.register_class(Props) setattr(CustomShelfSettings, cat.name, PointerProperty(type=Props)) # enable bool prefs # Prefs = type("CustomShelfPrefs",(PropertyGroup,),{}) # bpy.utils.register_class(Prefs) # setattr(CustomShelfPrefs,cat.name,PointerProperty(type = Prefs)) for tab in get_dirs(cat.path): # get_settings settings_json = join(tab.path, "settings.json") tab_settings = {} if exists(settings_json): tab_settings = read_json(settings_json) if not tab_settings or not tab_settings.get("tags"): continue for tag in tab_settings["tags"]: if tag not in tag_filter_items: tag_filter_items.append(tag) panel_info = { "bl_region_type": "UI", # Added, maybe need it in 2.8+... "bl_category": cat_name, "bl_idname": "%s_PT_%s_%s" % ( __package__.upper(), cat.name, tab.name, ), # "%s.%s_%s" -> makes _PT_ warning "bl_label": tab.name.replace("_", " ").title(), "cat": cat.name, "settings": tab_settings, } space_info = { k: v for k, v in tab_settings.items() if k in ("bl_space_type", "bl_region_type") } panel_info.update(space_info) panel = type("Panel", (CSHELF_PT_shelf_panel,), panel_info) bpy.utils.register_class(panel) CustomShelfSettings.panel_list.append(panel) scripts = [] for script in scandir(tab.path): if not script.name.endswith(".py"): continue print(script.path) script_name = splitext(script.name)[0] info, lines = read_info(script.path) info["description"] = info.get("description", "") 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) 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"]) # Register tag filter enum # setattr(Pre, v) prefs = bpy.context.preferences.addons[__package__].preferences tag_filter_items.sort() tag_filter_items.insert(0, "__clear__") # prefs["tag_filter_items"] = tag_filter_items # bpy.utils.unregister_class(CustomShelfPrefs) # bpy.utils.register_class(CustomShelfPrefs) # CustomShelfSettings.folders = list(get_shelves_folder().keys()) # folder_enum = EnumProperty(items = lambda s,c : [(f,f,"") for f in CustomShelfSettings.folders]) # setattr(CustomShelfSettings,'folders_enum',folder_enum)