New project and user prefix management
2.0.6 - changed: Use prefixes toggle is enabled by default - changed: prefixes are now set in preferences as a reorderable UI list with full name for description - This should not affect `PREFIXES` env variable (`'CO, LN'`) - Now can be also passed as prefix:name pair ex: `'CO : Color, LN : Line`gpv2
parent
8e3b3871e6
commit
02d13c6f29
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
2.0.6
|
||||
|
||||
- changed: Use prefixes toggle is enabled by default
|
||||
- changed: prefixes are now set in preferences as a reorderable UI list with full name for description
|
||||
- This should not affect `PREFIXES` env variable (`'CO, LN'`)
|
||||
- Now can be also passed as prefix:name pair ex: `'CO : Color, LN : Line`
|
||||
|
||||
2.0.5
|
||||
|
||||
- changed: redo panel for GP layer picker has better name and display active layer name
|
||||
|
|
|
@ -138,9 +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'})
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, properties):
|
||||
if properties.prefix_tooltip:
|
||||
return f"Use prefix: {properties.prefix} ({properties.prefix_tooltip})"
|
||||
else:
|
||||
return f"Use prefix: {properties.prefix}"
|
||||
|
||||
def execute(self, context):
|
||||
ob = context.object
|
||||
gpl = ob.data.layers
|
||||
|
@ -544,7 +552,7 @@ def layer_name_builder_ui(self, context):
|
|||
prefs = get_addon_prefs()
|
||||
if not prefs.show_prefix_buttons:
|
||||
return
|
||||
if not prefs.prefixes and not prefs.suffixes:
|
||||
if not len(prefs.prefixes.namespaces) and not prefs.suffixes:
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
|
@ -552,38 +560,57 @@ def layer_name_builder_ui(self, context):
|
|||
# layout.separator()
|
||||
col = layout.column()
|
||||
|
||||
all_prefixes = prefs.prefixes.split(',')
|
||||
all_suffixes = prefs.suffixes.split(',')
|
||||
|
||||
line_limit = 8
|
||||
|
||||
if len(prefs.prefixes.namespaces):
|
||||
ct = 0
|
||||
# can't use enumerate cause there can be hided prefix
|
||||
for namespace in prefs.prefixes.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.prefix)
|
||||
op.prefix = namespace.prefix
|
||||
op.prefix_tooltip = namespace.name
|
||||
|
||||
if ct > 0:
|
||||
row.operator("gp.layer_name_build", text='', icon='X').prefix = 'prefixkillcode'
|
||||
|
||||
## old single string prefix method
|
||||
"""
|
||||
if prefs.prefixes:
|
||||
## first prefix
|
||||
p = prefs.prefixes.split(',')
|
||||
for i, prefix in enumerate(all_prefixes):
|
||||
if i % line_limit == 0:
|
||||
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='')
|
||||
row.operator("gp.layer_new_group", text='', icon='COLLECTION_NEW')
|
||||
row.operator("gp.layer_group_toggle", text='', icon='OUTLINER_OB_GROUP_INSTANCE')
|
||||
|
||||
## 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(',')
|
||||
for i, suffix in enumerate(all_suffixes):
|
||||
if i % line_limit == 0:
|
||||
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'
|
||||
|
||||
|
||||
|
||||
|
||||
## --- UI dopesheet ---
|
||||
|
||||
def gpencil_dopesheet_header(self, context):
|
||||
|
|
137
__init__.py
137
__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, 5),
|
||||
"version": (2, 0, 6),
|
||||
"blender": (2, 91, 0),
|
||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||
"warning": "",
|
||||
|
@ -110,34 +110,36 @@ def remap_on_save_update(self, context):
|
|||
# kmi.active = self.use_precise_eraser
|
||||
|
||||
|
||||
|
||||
class GPTB_OT_add_namespace_prefix(bpy.types.Operator):
|
||||
bl_idname = "gptb.add_namespace_prefix"
|
||||
bl_label = "Add"
|
||||
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 = get_addon_prefs().user_prefixes
|
||||
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=650)
|
||||
return context.window_manager.invoke_props_dialog(self, width=450)
|
||||
|
||||
def draw(self, context):
|
||||
import re
|
||||
layout = self.layout
|
||||
# layout.use_property_split = True
|
||||
item = self.pg.namespaces[self.idx]
|
||||
layout.label(text='Enter prefix:', icon='INFO')
|
||||
layout.prop(item, 'prefix')
|
||||
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='Prefix are preferably two capital letter (ex: CO)', icon='ERROR')
|
||||
layout.label(text=f'{self.propname} are preferably two capital letter (ex: CO)', icon='ERROR')
|
||||
|
||||
layout.separator()
|
||||
layout.label(text='Provide a name (Optional):', icon='INFO')
|
||||
|
@ -152,10 +154,34 @@ class GPTB_OT_add_namespace_prefix(bpy.types.Operator):
|
|||
if self.new:
|
||||
# in case of new addition, remove just added if nothing specified
|
||||
if not item.prefix and not item.name:
|
||||
self.pg.dirs.remove(self.idx)
|
||||
self.pg.namespaces.remove(self.idx)
|
||||
|
||||
context.area.tag_redraw()
|
||||
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)
|
||||
if not len(self.pg.namespaces):
|
||||
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)
|
||||
context.area.tag_redraw()
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
||||
class GPTB_OT_move_item(bpy.types.Operator):
|
||||
bl_idname = "gptb.move_item"
|
||||
bl_label = "Move Item"
|
||||
|
@ -174,7 +200,7 @@ class GPTB_OT_move_item(bpy.types.Operator):
|
|||
# prop_name : bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
pg = get_addon_prefs().user_prefixes
|
||||
pg = get_addon_prefs().prefixes
|
||||
# uilist = getattr(pg, self.prop_name)
|
||||
uilist = pg.namespaces
|
||||
index = pg.idx
|
||||
|
@ -188,6 +214,7 @@ class GPTB_OT_move_item(bpy.types.Operator):
|
|||
# index = list_index
|
||||
# setattr(pg, self.prop_name + '_idx', list_index)
|
||||
setattr(pg, 'idx', list_index)
|
||||
context.area.tag_redraw()
|
||||
return {'FINISHED'}
|
||||
|
||||
class GPTB_UL_namespace_list(bpy.types.UIList):
|
||||
|
@ -200,10 +227,15 @@ class GPTB_UL_namespace_list(bpy.types.UIList):
|
|||
# prefs = get_addon_prefs()
|
||||
# split = layout.split(align=False, factor=0.3)
|
||||
row = layout.row()
|
||||
ico = 'HIDE_ON' if item.hide else 'HIDE_OFF'
|
||||
row.prop(item, 'hide', text='', icon=ico, invert_checkbox=True)
|
||||
row.prop(item, 'prefix', text='')
|
||||
row.prop(item, 'name', text='')
|
||||
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, 'prefix', text='')
|
||||
subrow.prop(item, 'name', text='')
|
||||
subrow.enabled = not item.is_project
|
||||
|
||||
# row = layout.split(align=False)
|
||||
# row.label(text=item.prefix)
|
||||
|
@ -320,12 +352,13 @@ 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')
|
||||
|
||||
prefixes : StringProperty(
|
||||
name="Layers Prefixes",
|
||||
description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)",
|
||||
default="", maxlen=0)
|
||||
## Old one string comma separated prefix list
|
||||
# prefixes : StringProperty(
|
||||
# name="Layers Prefixes",
|
||||
# description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)",
|
||||
# default="", maxlen=0)
|
||||
|
||||
# user_prefixes : PointerProperty(type=GP_PG_namespaces)
|
||||
prefixes : PointerProperty(type=GP_PG_namespaces)
|
||||
### proj_prefixes : PointerProperty(type=GP_PG_namespaces) # Store in the same list ?
|
||||
|
||||
suffixes : StringProperty(
|
||||
|
@ -342,7 +375,7 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
show_prefix_buttons : BoolProperty(
|
||||
name="Show Prefix Buttons",
|
||||
description="Show prefix and suffix buttons above layer stack",
|
||||
default=False,
|
||||
default=True,
|
||||
)
|
||||
|
||||
## Playblast prefs
|
||||
|
@ -514,20 +547,19 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
|
||||
if self.show_prefix_buttons:
|
||||
# subbox.prop(self, 'use_env_namespace')
|
||||
"""
|
||||
row = subbox.row()
|
||||
row.prop(self, 'prefixes')
|
||||
row.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'PREFIXES'
|
||||
row = subbox.row()
|
||||
row.prop(self, 'suffixes')
|
||||
row.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'SUFFIXES'
|
||||
|
||||
## Collection UI list version # WIP # TODO
|
||||
"""
|
||||
pg = self.user_prefixes
|
||||
## 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=6)
|
||||
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_prefix", icon="PLUS", text="")
|
||||
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'
|
||||
|
@ -535,7 +567,14 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
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'
|
||||
|
||||
### TODO add render settings
|
||||
|
||||
|
@ -765,7 +804,28 @@ def set_env_properties():
|
|||
|
||||
# if prefs.use_env_namespace:
|
||||
prefix_list = os.getenv('PREFIXES')
|
||||
prefs.prefixes = prefix_list if prefix_list else prefs.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
|
||||
|
@ -808,11 +868,14 @@ class GPTB_set_env_settings(bpy.types.Operator):
|
|||
|
||||
|
||||
classes = (
|
||||
# GP_PG_namespace_props,
|
||||
# GP_PG_namespaces,
|
||||
# GPTB_OT_add_namespace_prefix,
|
||||
# GPTB_OT_move_item,
|
||||
# GPTB_UL_namespace_list,
|
||||
## layer name management
|
||||
GP_PG_namespace_props,
|
||||
GP_PG_namespaces,
|
||||
GPTB_OT_add_namespace_entry,
|
||||
GPTB_OT_remove_namespace_entry,
|
||||
GPTB_OT_move_item,
|
||||
GPTB_UL_namespace_list,
|
||||
|
||||
GP_PG_FixSettings,
|
||||
GP_PG_ToolsSettings,
|
||||
GPTB_set_env_settings,
|
||||
|
@ -867,7 +930,7 @@ def register():
|
|||
if not 'remap_relative' in [hand.__name__ for hand in bpy.app.handlers.save_pre]:
|
||||
bpy.app.handlers.save_pre.append(remap_relative)
|
||||
|
||||
## change a variable in prefs if a '.git is detected'
|
||||
## Change a variable in prefs if a '.git is detected'
|
||||
prefs.is_git_repo = (Path(__file__).parent / '.git').exists()
|
||||
prefs.has_git = bool(which('git'))
|
||||
|
||||
|
|
|
@ -234,7 +234,11 @@ class GP_PG_namespace_props(PropertyGroup):
|
|||
name="Name", description="Name that represent this prefix (used as hint and tooltip)",
|
||||
default="")
|
||||
hide : BoolProperty(
|
||||
name="Hide", description="Hide this prefix from layer prefex management",
|
||||
name="Hide", description="Hide this prefix from layer prefix management",
|
||||
default=False)
|
||||
|
||||
is_project : BoolProperty(
|
||||
name="Project", description="Show this propery was set by project environnement (not deletable if that's the case)",
|
||||
default=False)
|
||||
|
||||
class GP_PG_namespaces(PropertyGroup):
|
||||
|
|
Loading…
Reference in New Issue