import bpy import os import re from .utils import get_addon_prefs from .functions import redraw_ui from .__init__ import set_namespace_env class GPTB_OT_reset_project_namespaces(bpy.types.Operator): bl_idname = "gptb.reset_project_namespaces" bl_label = "Reload Project Names" bl_description = "Reset projects namespaced from environnement variable" bl_options = {'REGISTER', 'INTERNAL'} def execute(self, context): prefs = get_addon_prefs() prefix_list = os.getenv('PREFIXES') suffix_list = os.getenv('SUFFIXES') if not prefix_list and not suffix_list: self.report({'WARNING'}, "No name list in env (variables: 'PREFIXES','SUFFIXES')") return {'CANCELLED'} for propname in ('prefixes', 'suffixes'): pg = getattr(prefs, propname) uilist = pg.namespaces uilist.clear() missing = [] if prefix_list: set_namespace_env('PREFIXES', prefs.prefixes) else: missing.append('prefixes') if suffix_list: set_namespace_env('SUFFIXES', prefs.suffixes) else: missing.append('suffixes') if missing: self.report({'WARNING'}, f'No {" and ".join(missing)} presets to load from project env') return {'FINISHED'} class GPTB_OT_add_namespace_entry(bpy.types.Operator): bl_idname = "gptb.add_namespace_entry" bl_label = "Add Namespace Entry" bl_description = "Add item in list" bl_options = {'REGISTER', 'INTERNAL'} idx : bpy.props.IntProperty() new : bpy.props.BoolProperty(default=True, options={'SKIP_SAVE'}) propname : bpy.props.StringProperty(default='prefixes', options={'SKIP_SAVE'}) def invoke(self, context, event): self.pg = getattr(get_addon_prefs(), self.propname) self.proptype = self.propname[:-2] ## Basic: # self.pg.namespaces.add() # return {'FINISHED'}# can just add empty entry and leave... if self.new: self.pg.namespaces.add() self.idx = len(self.pg.namespaces) - 1 return context.window_manager.invoke_props_dialog(self, width=450) def draw(self, context): layout = self.layout # layout.use_property_split = True item = self.pg.namespaces[self.idx] layout.label(text=f'Enter {self.proptype.title()}:', icon='INFO') layout.prop(item, 'tag', text=self.proptype.title()) if item.tag and not re.match(r'^[A-Z]{2}$', item.tag): layout.label(text=f'{self.propname.title()} are preferably two capital letter (ex: CO)', icon='ERROR') layout.separator() layout.label(text='Provide a name (Optional):', icon='INFO') layout.prop(item, 'name') def execute(self, context): item = self.pg.namespaces[self.idx] ## Here can perform post add checks # (check for duplicate ?) # all_prefix = [n.tag for i, n in enumerate(self.pg.namespaces) if i != self.pg.idx] if self.new: # in case of new addition, remove just added if nothing specified if not item.tag and not item.name: self.pg.namespaces.remove(self.idx) redraw_ui() return {'FINISHED'} class GPTB_OT_remove_namespace_entry(bpy.types.Operator): bl_idname = "gptb.remove_namespace_entry" bl_label = "Remove Namespace Entry" bl_description = "Remove item in list" bl_options = {'REGISTER', 'INTERNAL'} propname : bpy.props.StringProperty(default='prefixes', options={'SKIP_SAVE'}) def execute(self, context): self.pg = getattr(get_addon_prefs(), self.propname) entry_count = len(self.pg.namespaces) if not entry_count: return {'CANCELLED'} # check if index is out of range if not (0 <= self.pg.idx < entry_count): self.report({"ERROR"}, 'Must select an entry to remove it') return {'CANCELLED'} item = self.pg.namespaces[self.pg.idx] if item.is_project: self.report({"ERROR"}, 'Cannot remove a prefix that is defined by project, hide it instead') return {'CANCELLED'} self.pg.namespaces.remove(self.pg.idx) self.pg.idx -= 1 redraw_ui() return {'FINISHED'} class GPTB_OT_move_item(bpy.types.Operator): bl_idname = "gptb.move_item" bl_label = "Move Item" bl_description = "Move item in list up or down" bl_options = {'REGISTER', 'INTERNAL'} # direction : bpy.props.IntProperty(default=1) direction : bpy.props.EnumProperty( items=( ('UP', 'Move Up', 'Move up'), ('DOWN', 'Move down', 'Move down'), ), default='UP', ) propname : bpy.props.StringProperty() def execute(self, context): pg = getattr(get_addon_prefs(), self.propname) uilist = pg.namespaces index = pg.idx neighbor = index + (-1 if self.direction == 'UP' else 1) uilist.move(neighbor, index) list_length = len(uilist) - 1 # (index starts at 0) new_index = index + (-1 if self.direction == 'UP' else 1) list_index = max(0, min(new_index, list_length)) setattr(pg, 'idx', list_index) redraw_ui() return {'FINISHED'} def draw_namespace_item(self, context, layout, data, item, icon, active_data, active_propname): # self.use_filter_show = True # force open/close the search feature # prefs = get_addon_prefs() # split = layout.split(align=False, factor=0.3) row = layout.row() hide_ico = 'HIDE_ON' if item.hide else 'HIDE_OFF' source_ico = 'NETWORK_DRIVE' if item.is_project else 'USER' # BLANK1 row.label(text='', icon=source_ico) row.prop(item, 'hide', text='', icon=hide_ico, invert_checkbox=True) subrow = row.row(align=True) subrow.prop(item, 'tag', text='') subrow.prop(item, 'name', text='') subrow.enabled = not item.is_project # row = layout.split(align=False) # row.label(text=item.prefix) # row.label(text=item.name) # if self.show_desc: # row.label(text=item.description) # row.operator('sbam.open_online_repo', text='', icon='URL') class GPTB_UL_namespace_list(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): draw_namespace_item(self, context, layout, data, item, icon, active_data, active_propname) ## Need to duplicate UL as a separate class for suffixes\ ## otherwise displayed row in UI are synchronised class GPTB_UL_namespace_list_suffix(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): draw_namespace_item(self, context, layout, data, item, icon, active_data, active_propname) classes = ( ## layer name management GPTB_OT_reset_project_namespaces, GPTB_OT_add_namespace_entry, GPTB_OT_remove_namespace_entry, GPTB_OT_move_item, GPTB_UL_namespace_list, GPTB_UL_namespace_list_suffix, ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls)