diff --git a/CHANGELOG.md b/CHANGELOG.md index e67461b..7db6ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +2.0.8 + +- changed: suffix as UIlist in prefs, +- fix: prefix and suffix register and load + 2.0.7 - fix: broken auto-fade with gp layer navigation when used with a customized shortcut. @@ -16,7 +21,7 @@ - changed: redo panel for GP layer picker has better name and display active layer name - changed: some operator id_name to expose "add shortcut" in context menu for some button -- fixed: error with draw_cam handler when no camera is active +- fix: error with draw_cam handler when no camera is active 2.0.3 diff --git a/OP_layer_manager.py b/OP_layer_manager.py index 67ebb3b..a048838 100644 --- a/OP_layer_manager.py +++ b/OP_layer_manager.py @@ -138,16 +138,17 @@ class GPTB_OT_layer_name_build(Operator): prefix : StringProperty(default='', options={'SKIP_SAVE'}) # prefix2 : StringProperty(default='', options={'SKIP_SAVE'}) - prefix_tooltip : StringProperty(default='', options={'SKIP_SAVE'}) desc : StringProperty(default='', options={'SKIP_SAVE'}) suffix : StringProperty(default='', options={'SKIP_SAVE'}) + tooltip : StringProperty(default='', options={'SKIP_SAVE'}) @classmethod def description(cls, context, properties): - if properties.prefix_tooltip: - return f"Use prefix: {properties.prefix} ({properties.prefix_tooltip})" + tag = properties.prefix if properties.prefix else properties.suffix + if properties.tooltip: + return f"Use prefix: {tag} ({properties.tooltip})" else: - return f"Use prefix: {properties.prefix}" + return f"Use prefix: {tag}" def execute(self, context): ob = context.object @@ -552,7 +553,7 @@ def layer_name_builder_ui(self, context): prefs = get_addon_prefs() if not prefs.show_prefix_buttons: return - if not len(prefs.prefixes.namespaces) and not prefs.suffixes: + if not len(prefs.prefixes.namespaces) and not len(prefs.suffixes.namespaces): return layout = self.layout @@ -572,9 +573,9 @@ def layer_name_builder_ui(self, context): if ct % line_limit == 0: row = col.row(align=True) ct += 1 - op = row.operator("gp.layer_name_build", text=namespace.prefix) - op.prefix = namespace.prefix - op.prefix_tooltip = namespace.name + op = row.operator("gp.layer_name_build", text=namespace.tag) + op.prefix = namespace.tag + op.tooltip = namespace.name if ct > 0: row.operator("gp.layer_name_build", text='', icon='X').prefix = 'prefixkillcode' @@ -588,20 +589,8 @@ def layer_name_builder_ui(self, context): row = col.row(align=True) row.operator("gp.layer_name_build", text=prefix.upper() ).prefix = prefix row.operator("gp.layer_name_build", text='', icon='X').prefix = 'prefixkillcode' - """ - ## secondary prefix ? - ## name (description) - row = col.row(align=True) - row.prop(context.scene.gptoolprops, 'layer_name', text='') - - ## mimic groups using dash (disabled for now) - # row.operator("gp.layer_new_group", text='', icon='COLLECTION_NEW') - # row.operator("gp.layer_group_toggle", text='', icon='OUTLINER_OB_GROUP_INSTANCE') - - ## no need for desc ops, already trigerred from update - # row.operator("gp.layer_name_build", text='', icon='EVENT_RETURN').desc = context.scene.gptoolprops.layer_name if prefs.suffixes: all_suffixes = prefs.suffixes.split(',') @@ -610,6 +599,33 @@ def layer_name_builder_ui(self, context): row = col.row(align=True) row.operator("gp.layer_name_build", text=suffix.upper() ).suffix = suffix row.operator("gp.layer_name_build", text='', icon='X').suffix = 'suffixkillcode' + """ + + ## name (description of layer content) + row = col.row(align=True) + row.prop(context.scene.gptoolprops, 'layer_name', text='') + + ## mimic groups using dash (disabled for now) + # row.operator("gp.layer_new_group", text='', icon='COLLECTION_NEW') + # row.operator("gp.layer_group_toggle", text='', icon='OUTLINER_OB_GROUP_INSTANCE') + ## no need for desc ops, already trigerred from update + # row.operator("gp.layer_name_build", text='', icon='EVENT_RETURN').desc = context.scene.gptoolprops.layer_name + + if len(prefs.suffixes.namespaces): + ct = 0 + # can't use enumerate cause there can be hided prefix + for namespace in prefs.suffixes.namespaces: + if namespace.hide: + continue + if ct % line_limit == 0: + row = col.row(align=True) + ct += 1 + op = row.operator("gp.layer_name_build", text=namespace.tag) + op.suffix = namespace.tag + op.tooltip = namespace.name + + if ct > 0: + row.operator("gp.layer_name_build", text='', icon='X').suffix = 'suffixkillcode' ## --- UI dopesheet --- diff --git a/__init__.py b/__init__.py index 4e548c6..9f52a2e 100755 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "GP toolbox", "description": "Tool set for Grease Pencil in animation production", "author": "Samuel Bernou, Christophe Seux", -"version": (2, 0, 7), +"version": (2, 0, 8), "blender": (3, 0, 0), "location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties", "warning": "", @@ -136,10 +136,10 @@ class GPTB_OT_add_namespace_entry(bpy.types.Operator): layout = self.layout # layout.use_property_split = True item = self.pg.namespaces[self.idx] - layout.label(text=f'Enter {self.proptype}:', icon='INFO') - layout.prop(item, 'prefix') # maybe use a name that fit prefix and suffix - if item.prefix and not re.match(r'^[A-Z]{2}$', item.prefix): - layout.label(text=f'{self.propname} are preferably two capital letter (ex: CO)', icon='ERROR') + 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') @@ -149,11 +149,11 @@ class GPTB_OT_add_namespace_entry(bpy.types.Operator): item = self.pg.namespaces[self.idx] ## Here can perform post add checks # (check for duplicate ?) - # all_prefix = [n.prefix for i, n in enumerate(self.pg.namespaces) if i != self.pg.idx] + # 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.prefix and not item.name: + if not item.tag and not item.name: self.pg.namespaces.remove(self.idx) context.area.tag_redraw() @@ -169,19 +169,24 @@ class GPTB_OT_remove_namespace_entry(bpy.types.Operator): def execute(self, context): self.pg = getattr(get_addon_prefs(), self.propname) - if not len(self.pg.namespaces): + 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 context.area.tag_redraw() return {'FINISHED'} - - class GPTB_OT_move_item(bpy.types.Operator): bl_idname = "gptb.move_item" bl_label = "Move Item" @@ -197,11 +202,10 @@ class GPTB_OT_move_item(bpy.types.Operator): default='UP', ) - # prop_name : bpy.props.StringProperty() + propname : bpy.props.StringProperty() def execute(self, context): - pg = get_addon_prefs().prefixes - # uilist = getattr(pg, self.prop_name) + pg = getattr(get_addon_prefs(), self.propname) uilist = pg.namespaces index = pg.idx @@ -211,8 +215,6 @@ class GPTB_OT_move_item(bpy.types.Operator): new_index = index + (-1 if self.direction == 'UP' else 1) list_index = max(0, min(new_index, list_length)) - # index = list_index - # setattr(pg, self.prop_name + '_idx', list_index) setattr(pg, 'idx', list_index) context.area.tag_redraw() return {'FINISHED'} @@ -233,7 +235,7 @@ class GPTB_UL_namespace_list(bpy.types.UIList): 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, 'prefix', text='') + subrow.prop(item, 'tag', text='') subrow.prop(item, 'name', text='') subrow.enabled = not item.is_project @@ -352,19 +354,20 @@ class GPTB_prefs(bpy.types.AddonPreferences): description="Character delimiter to use for detecting namespace (prefix), default is '_', space if nothing specified", default="_", maxlen=0, subtype='NONE') - ## Old one string comma separated prefix list + ## Old one string comma separated prefix/suffix list # prefixes : StringProperty( # name="Layers Prefixes", # description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)", # default="", maxlen=0) - prefixes : PointerProperty(type=GP_PG_namespaces) - ### proj_prefixes : PointerProperty(type=GP_PG_namespaces) # Store in the same list ? + # suffixes : StringProperty( + # name="Layers Suffixes", + # description="List of suffixes (two capital letters) available for layers(ex: OL,UL)", + # default="", maxlen=0) + + prefixes : PointerProperty(type=GP_PG_namespaces) + suffixes : PointerProperty(type=GP_PG_namespaces) - suffixes : StringProperty( - name="Layers Suffixes", - description="List of suffixes (two capital letters) available for layers(ex: OL,UL)", - default="", maxlen=0) # use_env_namespace : BoolProperty( # name="Use Project namespace", @@ -499,6 +502,27 @@ class GPTB_prefs(bpy.types.AddonPreferences): # description = "Auto assign shortcut for temp_cutter", # default = True) + def draw_namespaces_list(self, layout, pg_name, rows=4): + '''Get layout, property group to draw and default row number''' + + pg = getattr(self, pg_name) + row = layout.row(align=True) + row.template_list("GPTB_UL_namespace_list", "", pg, "namespaces", pg, "idx", rows=rows) + subcol = row.column(align=True) # Lateral right + subcol.operator("gptb.add_namespace_entry", icon="ADD", text="").propname=pg_name + subcol.operator("gptb.remove_namespace_entry", icon="REMOVE", text="").propname=pg_name + subcol.separator() + op_move = subcol.operator("gptb.move_item", icon="TRIA_UP", text="") + op_move.propname = pg_name + op_move.direction = 'UP' + op_move = subcol.operator("gptb.move_item", icon="TRIA_DOWN", text="") + op_move.propname = pg_name + op_move.direction = 'DOWN' + + ## Reset entry (Not needed anymore) + # subcol.separator() + # subcol.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'PREFIXES' + def draw(self, context): layout = self.layout## random color # layout.use_property_split = True @@ -551,30 +575,15 @@ class GPTB_prefs(bpy.types.AddonPreferences): row = subbox.row() row.prop(self, 'prefixes') row.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'PREFIXES' - row = subbox.row() - """ - ## Collection UI list version # WIP - pg = self.prefixes - row = subbox.row(align=True) - row.template_list("GPTB_UL_namespace_list", "", pg, "namespaces", pg, "idx", rows=4) - subcol = row.column(align=True) # Lateral right - subcol.operator("gptb.add_namespace_entry", icon="ADD", text="") - subcol.operator("gptb.remove_namespace_entry", icon="REMOVE", text="") - subcol.separator() - op_move = subcol.operator("gptb.move_item", icon="TRIA_UP", text="") - # op_move.prop_name = 'namespaces' - op_move.direction = 'UP' - op_move = subcol.operator("gptb.move_item", icon="TRIA_DOWN", text="") - # op_move.prop_name = 'namespaces' - op_move.direction = 'DOWN' - - ## Reset entry (Not needed anymore) - # subcol.separator() - # subcol.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'PREFIXES' - row = subbox.row(align=True) row.prop(self, 'suffixes') row.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'SUFFIXES' + """ + ## Collection UI list version + self.draw_namespaces_list(subbox, 'prefixes', rows=4) + subbox.separator() + self.draw_namespaces_list(subbox, 'suffixes', rows=4) + ### TODO add render settings @@ -781,8 +790,30 @@ class GPTB_prefs(bpy.types.AddonPreferences): ### --- ENV_PROP --- +def set_namespace_env(name_env, prop_group): + tag_list = os.getenv(name_env) + if tag_list: + tag_list = tag_list.strip(',').split(',') + current_pfix = [n.tag for n in prop_group.namespaces if n.tag] + for p in tag_list: + pf = p.split(':')[0].strip() + name = '' if not ':' in p else p.split(':')[1].strip() + if pf not in current_pfix: + item = prop_group.namespaces.add() + item.tag = pf + item.name = name + item.is_project = True + else: + tag_list = [] + + # "release" suffix that are not in project anymore + for n in prop_group.namespaces: + if n.tag not in tag_list: + n.is_project = False def set_env_properties(): + + prefs = get_addon_prefs() fps = os.getenv('FPS') @@ -803,32 +834,15 @@ def set_env_properties(): prefs.brush_path = brushes if brushes else prefs.brush_path # if prefs.use_env_namespace: - prefix_list = os.getenv('PREFIXES') - ## old direct string assignment (now a property group) - # prefs.prefixes = prefix_list if prefix_list else prefs.prefixes - - if prefix_list: - prefix_list = prefix_list.strip(',').split(',') - current_pfix = [n.prefix for n in prefs.prefixes.namespaces if n.prefix] - for p in prefix_list: - pf = p.split(':')[0].strip() - name = '' if not ':' in p else p.split(':')[1].strip() - if pf not in current_pfix: - item = prefs.prefixes.namespaces.add() - item.prefix = pf - item.name = name - item.is_project = True - else: - prefix_list = [] - - # "release" suffix that are not in project anymore - for n in prefs.prefixes.namespaces: - # if n.is_project and not n.prefix in prefix_list: - if n.prefix not in prefix_list: - n.is_project = False - suffix_list = os.getenv('SUFFIXES') - prefs.suffixes = suffix_list if suffix_list else prefs.suffixes + ## Old method with direct string assignment (now a property group) + # prefix_list = os.getenv('PREFIXES') + # prefs.prefixes = prefix_list if prefix_list else prefs.prefixes + # suffix_list = os.getenv('SUFFIXES') + # prefs.suffixes = suffix_list if suffix_list else prefs.suffixes + + set_namespace_env('PREFIXES', prefs.prefixes) + set_namespace_env('SUFFIXES', prefs.suffixes) separator = os.getenv('SEPARATOR') prefs.separator = separator if separator else prefs.separator @@ -850,14 +864,15 @@ class GPTB_set_env_settings(bpy.types.Operator): if not prefix_list: self.report({'ERROR'}, 'No prefix preset to load from project environnement') return {'CANCELLED'} - prefs.prefixes = prefix_list if prefix_list else prefs.prefixes - + set_namespace_env('PREFIXES', prefs.prefixes) + elif self.mode == 'SUFFIXES': suffix_list = os.getenv('SUFFIXES') if not suffix_list: self.report({'ERROR'}, 'No suffix preset to load from project environnement') return {'CANCELLED'} - prefs.suffixes = suffix_list if suffix_list else prefs.suffixes + set_namespace_env('SUFFIXES', prefs.suffixes) + return {'FINISHED'} diff --git a/properties.py b/properties.py index 77328b1..4b17400 100755 --- a/properties.py +++ b/properties.py @@ -227,8 +227,8 @@ class GP_PG_ToolsSettings(PropertyGroup): class GP_PG_namespace_props(PropertyGroup): - prefix : StringProperty( - name="Prefix", description="Layer namespace prefix", + tag : StringProperty( + name="Tag", description="Layer namespace tag (prefix/suffix)", default="") name : StringProperty( name="Name", description="Name that represent this prefix (used as hint and tooltip)",