namespace improvement
1.5.8 - feat: Namespace improvement: - new suffixes list that generate suffix buttons - dynamic layer name field that show active (msgbus) - possible to disable the panel with an optiongpv2
parent
9612c84396
commit
212436c451
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
1.5.8
|
||||||
|
|
||||||
|
- feat: Namespace improvement:
|
||||||
|
- new suffixes list that generate suffix buttons
|
||||||
|
- dynamic layer name field that show active (msgbus)
|
||||||
|
- possible to disable the panel with an option
|
||||||
|
|
||||||
1.5.7
|
1.5.7
|
||||||
|
|
||||||
- feat: check list, specify in addon pref if you prefer a dry run (check without set)
|
- feat: check list, specify in addon pref if you prefer a dry run (check without set)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
from os import error
|
||||||
import bpy
|
import bpy
|
||||||
import re
|
import re
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import StringProperty, BoolProperty, EnumProperty
|
from bpy.props import StringProperty, BoolProperty, EnumProperty
|
||||||
|
from bpy.app.handlers import persistent
|
||||||
from .utils import get_addon_prefs
|
from .utils import get_addon_prefs
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,11 +12,13 @@ from .utils import get_addon_prefs
|
||||||
# pattern = r'([A-Z]{2})?_?([A-Z]{2})?_?(.*)' # bad ! match whithout separator
|
# pattern = r'([A-Z]{2})?_?([A-Z]{2})?_?(.*)' # bad ! match whithout separator
|
||||||
# pattern = r'(?:(^[A-Z]{2})_)?(?:([A-Z]{2})_)?(.*)' # matching only two letter
|
# pattern = r'(?:(^[A-Z]{2})_)?(?:([A-Z]{2})_)?(.*)' # matching only two letter
|
||||||
# pattern = r'^([A-Z]{2}_)?([A-Z]{2}_)?(.*)' # matching letters with separator
|
# pattern = r'^([A-Z]{2}_)?([A-Z]{2}_)?(.*)' # matching letters with separator
|
||||||
pattern = r'^([A-Z]{1,6}_)?([A-Z]{1,6}_)?(.*)' # matching capital letters from one to six
|
|
||||||
|
|
||||||
def layer_name_build(layer, prefix='', prefix2='', desc=''):
|
# pattern = r'^([A-Z]{1,6}_)?([A-Z]{1,6}_)?(.*)' # matching capital letters from one to six
|
||||||
|
pattern = r'^([A-Z]{1,6}_)?([A-Z]{1,6}_)?(.*?)(_[A-Z]{2})?$' # 2 letter suffix
|
||||||
|
|
||||||
|
def layer_name_build(layer, prefix='', prefix2='', desc='', suffix=''):
|
||||||
'''GET a layer and infos to build name
|
'''GET a layer and infos to build name
|
||||||
can take one or two prefix and description/name of the layer)
|
Can take one or two prefix and description/name of the layer)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global pattern
|
global pattern
|
||||||
|
@ -26,27 +29,31 @@ def layer_name_build(layer, prefix='', prefix2='', desc=''):
|
||||||
|
|
||||||
pattern = pattern.replace('_', sep) # set separator
|
pattern = pattern.replace('_', sep) # set separator
|
||||||
|
|
||||||
res = re.search(pattern, name)
|
res = re.search(pattern, name.strip())
|
||||||
p1, p2, p3 = res.group(1), res.group(2), res.group(3)
|
p1 = '' if res.group(1) is None else res.group(1)
|
||||||
|
p2 = '' if res.group(2) is None else res.group(2)
|
||||||
## empty instead of None
|
p3 = '' if res.group(3) is None else res.group(3)
|
||||||
p1 = '' if p1 is None else p1
|
p4 = '' if res.group(4) is None else res.group(4)
|
||||||
p2 = '' if p2 is None else p2
|
|
||||||
p3 = '' if p3 is None else p3
|
|
||||||
|
|
||||||
if prefix:
|
if prefix:
|
||||||
if prefix == 'prefixkillcode':
|
if prefix == 'prefixkillcode':
|
||||||
p1 = ''
|
p1 = ''
|
||||||
else:
|
else:
|
||||||
p1 = prefix.upper() + sep
|
p1 = prefix.upper().strip() + sep
|
||||||
|
|
||||||
if prefix2:
|
if prefix2:
|
||||||
p2 = prefix2.upper() + sep
|
p2 = prefix2.upper().strip() + sep
|
||||||
|
|
||||||
if desc:
|
if desc:
|
||||||
p3 = desc
|
p3 = desc
|
||||||
|
|
||||||
|
if suffix:
|
||||||
|
if suffix == 'suffixkillcode':
|
||||||
|
p4 = ''
|
||||||
|
else:
|
||||||
|
p4 = sep + suffix.upper().strip()
|
||||||
|
|
||||||
new = f'{p1}{p2}{p3}'
|
new = f'{p1}{p2}{p3}{p4}'
|
||||||
|
|
||||||
layer.info = new
|
layer.info = new
|
||||||
|
|
||||||
## multi-prefix solution (Caps letters)
|
## multi-prefix solution (Caps letters)
|
||||||
|
@ -63,6 +70,7 @@ class GPTB_OT_layer_name_build(Operator):
|
||||||
prefix : StringProperty(default='', options={'SKIP_SAVE'})
|
prefix : StringProperty(default='', options={'SKIP_SAVE'})
|
||||||
prefix2 : StringProperty(default='', options={'SKIP_SAVE'})
|
prefix2 : StringProperty(default='', options={'SKIP_SAVE'})
|
||||||
desc : StringProperty(default='', options={'SKIP_SAVE'})
|
desc : StringProperty(default='', options={'SKIP_SAVE'})
|
||||||
|
suffix : StringProperty(default='', options={'SKIP_SAVE'})
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
ob = context.object
|
ob = context.object
|
||||||
|
@ -71,10 +79,10 @@ class GPTB_OT_layer_name_build(Operator):
|
||||||
if not act:
|
if not act:
|
||||||
self.report({'ERROR'}, 'no layer active')
|
self.report({'ERROR'}, 'no layer active')
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
for l in gpl:
|
for l in gpl:
|
||||||
if not l.select:
|
if l.select or l == act:
|
||||||
continue
|
layer_name_build(l, prefix=self.prefix, prefix2=self.prefix2, desc=self.desc, suffix=self.suffix)
|
||||||
layer_name_build(l, prefix=self.prefix, prefix2=self.prefix2, desc=self.desc)
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -284,33 +292,42 @@ def layer_name_builder(self, context):
|
||||||
'''appended to DATA_PT_gpencil_layers'''
|
'''appended to DATA_PT_gpencil_layers'''
|
||||||
|
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
if not prefs.prefixes:
|
if not prefs.show_prefix_buttons:
|
||||||
return
|
return
|
||||||
|
if not prefs.prefixes and not prefs.suffixes:
|
||||||
|
return
|
||||||
|
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
# {'EDIT_GPENCIL', 'PAINT_GPENCIL','SCULPT_GPENCIL','WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
|
# {'EDIT_GPENCIL', 'PAINT_GPENCIL','SCULPT_GPENCIL','WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
|
||||||
# layout.separator()
|
# layout.separator()
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
|
|
||||||
all_prefixes = prefs.prefixes.split(',')
|
all_prefixes = prefs.prefixes.split(',')
|
||||||
|
all_suffixes = prefs.suffixes.split(',')
|
||||||
line_limit = 8
|
line_limit = 8
|
||||||
|
|
||||||
## first prefix
|
if prefs.prefixes:
|
||||||
for i, prefix in enumerate(all_prefixes):
|
## first prefix
|
||||||
if i % line_limit == 0:
|
for i, prefix in enumerate(all_prefixes):
|
||||||
row = col.row(align=True)
|
if i % line_limit == 0:
|
||||||
row.operator("gp.layer_name_build", text=prefix.upper() ).prefix = prefix
|
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'
|
row.operator("gp.layer_name_build", text='', icon='X').prefix = 'prefixkillcode'
|
||||||
|
|
||||||
## secondary prefix
|
## secondary prefix ?
|
||||||
# row = layout.row(align=True)
|
|
||||||
# for task in prefs.prefixes: # 'PO', 'AN'
|
|
||||||
# row.operator("me.set_layer_name", text=task).prefix2 = task
|
|
||||||
|
|
||||||
|
## name (description)
|
||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.prop(context.scene.gptoolprops, 'layer_name', text='')
|
row.prop(context.scene.gptoolprops, 'layer_name', text='')
|
||||||
row.operator("gp.layer_name_build", text='', icon='EVENT_RETURN').desc = context.scene.gptoolprops.layer_name
|
## 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:
|
||||||
|
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 ---
|
## --- UI dopesheet ---
|
||||||
|
@ -334,6 +351,39 @@ def gpencil_layer_dropdown_menu(self, context):
|
||||||
'''to append in GPENCIL_MT_layer_context_menu'''
|
'''to append in GPENCIL_MT_layer_context_menu'''
|
||||||
self.layout.operator('gp.rename_gp_layers', icon='BORDERMOVE')
|
self.layout.operator('gp.rename_gp_layers', icon='BORDERMOVE')
|
||||||
|
|
||||||
|
## handler and msgbus
|
||||||
|
|
||||||
|
def obj_layer_name_callback():
|
||||||
|
'''assign layer name properties so user an tweak it'''
|
||||||
|
ob = bpy.context.object
|
||||||
|
if not ob or ob.type != 'GPENCIL':
|
||||||
|
return
|
||||||
|
if not ob.data.layers.active:
|
||||||
|
return
|
||||||
|
pattern = r'^([A-Z]{1,6}_)?([A-Z]{1,6}_)?(.*?)(_[A-Z]{2})?$'
|
||||||
|
res = re.search(pattern, ob.data.layers.active.info)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
if not res.group(3):
|
||||||
|
return
|
||||||
|
bpy.context.scene.gptoolprops['layer_name'] = res.group(3)
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def subscribe_handler(dummy):
|
||||||
|
subscribe_to = (bpy.types.GreasePencilLayers, "active_index")
|
||||||
|
bpy.msgbus.subscribe_rna(
|
||||||
|
key=subscribe_to,
|
||||||
|
# owner of msgbus subcribe (for clearing later)
|
||||||
|
# owner=handle,
|
||||||
|
owner=bpy.types.GreasePencil, # <-- can atach to an ID during all it's lifetime...
|
||||||
|
# Args passed to callback function (tuple)
|
||||||
|
args=(),
|
||||||
|
# Callback function for property update
|
||||||
|
notify=obj_layer_name_callback,
|
||||||
|
options={'PERSISTENT'},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
classes=(
|
classes=(
|
||||||
GPTB_OT_rename_gp_layer,
|
GPTB_OT_rename_gp_layer,
|
||||||
GPTB_OT_layer_name_build,
|
GPTB_OT_layer_name_build,
|
||||||
|
@ -348,11 +398,16 @@ def register():
|
||||||
bpy.types.DATA_PT_gpencil_layers.prepend(layer_name_builder)
|
bpy.types.DATA_PT_gpencil_layers.prepend(layer_name_builder)
|
||||||
bpy.types.DOPESHEET_HT_header.append(gpencil_dopesheet_header)
|
bpy.types.DOPESHEET_HT_header.append(gpencil_dopesheet_header)
|
||||||
bpy.types.GPENCIL_MT_layer_context_menu.append(gpencil_layer_dropdown_menu)
|
bpy.types.GPENCIL_MT_layer_context_menu.append(gpencil_layer_dropdown_menu)
|
||||||
|
bpy.app.handlers.load_post.append(subscribe_handler) # need to restart after first activation
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
|
bpy.app.handlers.load_post.remove(subscribe_handler)
|
||||||
bpy.types.GPENCIL_MT_layer_context_menu.remove(gpencil_layer_dropdown_menu)
|
bpy.types.GPENCIL_MT_layer_context_menu.remove(gpencil_layer_dropdown_menu)
|
||||||
bpy.types.DOPESHEET_HT_header.remove(gpencil_dopesheet_header)
|
bpy.types.DOPESHEET_HT_header.remove(gpencil_dopesheet_header)
|
||||||
bpy.types.DATA_PT_gpencil_layers.remove(layer_name_builder)
|
bpy.types.DATA_PT_gpencil_layers.remove(layer_name_builder)
|
||||||
|
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
|
# delete layer index trigger
|
||||||
|
bpy.msgbus.clear_by_owner(bpy.types.GreasePencil)
|
17
README.md
17
README.md
|
@ -33,15 +33,16 @@ Note about palette : For now the importer is not working with linked palette as
|
||||||
|
|
||||||
> Mainly for devellopers to set project environnement
|
> Mainly for devellopers to set project environnement
|
||||||
|
|
||||||
Since 1.5.2, following _environnement variable_ can set the project properties in toolbox preferences at register launch.
|
Since 1.5.2, following _environnement variable_ can set the project properties in toolbox preferences at register launch:
|
||||||
|
|
||||||
`RENDER_WIDTH` : resolution x
|
`RENDER_WIDTH` : resolution x
|
||||||
`RENDER_HEIGHT` : resolution y
|
`RENDER_HEIGHT` : resolution y
|
||||||
`FPS` : project frame rate
|
`FPS` : project frame rate
|
||||||
`PALETTES` : path to the blends (or json) containing materials palettes
|
`PALETTES` : path to the blends (or json) containing materials palettes
|
||||||
`BRUSHES` : path to the blend containing brushes to load
|
`BRUSHES` : path to the blend containing brushes to load
|
||||||
`PREFIXES` : list of prefix (comma separated uppercase letters between 1 and 6 character, ex: 'AN,SP,L')
|
`PREFIXES` : list of prefix (comma separated uppercase letters between 1 and 6 character, ex: 'AN,SP,L')
|
||||||
`SEPARATOR` : Separator character to determine prefixes, default is '_' (should not be a special regex character)
|
`SUFFIXES` : list of suffixes (comma separated uppercase letters between 1 and 6 character, ex: 'OL,UL')
|
||||||
|
`SEPARATOR` : Separator character to determine prefixes, default is '_' (should not be a special regex character)
|
||||||
|
|
||||||
### Passive action
|
### Passive action
|
||||||
|
|
||||||
|
|
19
__init__.py
19
__init__.py
|
@ -234,6 +234,17 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
||||||
description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)",
|
description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)",
|
||||||
default="", maxlen=0)
|
default="", maxlen=0)
|
||||||
|
|
||||||
|
suffixes : StringProperty(
|
||||||
|
name="Layers Suffixes",
|
||||||
|
description="List of suffixes (two capital letters) available for layers(ex: OL,UL)",
|
||||||
|
default="", maxlen=0)
|
||||||
|
|
||||||
|
show_prefix_buttons : BoolProperty(
|
||||||
|
name="Show Prefix Buttons",
|
||||||
|
description="Show prefix and suffix buttons above layer stack",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
## Playblast prefs
|
## Playblast prefs
|
||||||
playblast_auto_play : BoolProperty(
|
playblast_auto_play : BoolProperty(
|
||||||
name="Playblast auto play",
|
name="Playblast auto play",
|
||||||
|
@ -364,7 +375,10 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
||||||
subbox = box.box()
|
subbox = box.box()
|
||||||
subbox.label(text='Namespace:')
|
subbox.label(text='Namespace:')
|
||||||
subbox.prop(self, 'separator')
|
subbox.prop(self, 'separator')
|
||||||
subbox.prop(self, 'prefixes')
|
subbox.prop(self, 'show_prefix_buttons', text='Use Prefixes Toggles')
|
||||||
|
if self.show_prefix_buttons:
|
||||||
|
subbox.prop(self, 'prefixes')
|
||||||
|
subbox.prop(self, 'suffixes')
|
||||||
|
|
||||||
### TODO add render settings
|
### TODO add render settings
|
||||||
|
|
||||||
|
@ -504,6 +518,9 @@ def set_env_properties():
|
||||||
|
|
||||||
prefix_list = os.getenv('PREFIXES')
|
prefix_list = os.getenv('PREFIXES')
|
||||||
prefs.prefixes = prefix_list if prefix_list else prefs.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
|
||||||
|
|
||||||
separator = os.getenv('SEPARATOR')
|
separator = os.getenv('SEPARATOR')
|
||||||
prefs.separator = separator if separator else prefs.separator
|
prefs.separator = separator if separator else prefs.separator
|
||||||
|
|
|
@ -8,7 +8,7 @@ from bpy.props import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from .OP_cursor_snap_canvas import cursor_follow_update
|
from .OP_cursor_snap_canvas import cursor_follow_update
|
||||||
|
from .OP_layer_manager import layer_name_build
|
||||||
|
|
||||||
def change_edit_lines_opacity(self, context):
|
def change_edit_lines_opacity(self, context):
|
||||||
for gp in bpy.data.grease_pencils:
|
for gp in bpy.data.grease_pencils:
|
||||||
|
@ -16,6 +16,18 @@ def change_edit_lines_opacity(self, context):
|
||||||
gp.edit_line_color[3]=self.edit_lines_opacity
|
gp.edit_line_color[3]=self.edit_lines_opacity
|
||||||
|
|
||||||
|
|
||||||
|
def update_layer_name(self, context):
|
||||||
|
if not self.layer_name:
|
||||||
|
# never replace by nothing (since there should be prefix/suffix)
|
||||||
|
return
|
||||||
|
if not context.object or context.object.type != 'GPENCIL':
|
||||||
|
return
|
||||||
|
if not context.object.data.layers.active:
|
||||||
|
return
|
||||||
|
layer_name_build(context.object.data.layers.active, desc=self.layer_name)
|
||||||
|
# context.object.data.layers.active.info = self.layer_name
|
||||||
|
|
||||||
|
|
||||||
class GP_PG_FixSettings(bpy.types.PropertyGroup):
|
class GP_PG_FixSettings(bpy.types.PropertyGroup):
|
||||||
|
|
||||||
check_only : BoolProperty(
|
check_only : BoolProperty(
|
||||||
|
@ -168,7 +180,8 @@ class GP_PG_ToolsSettings(bpy.types.PropertyGroup):
|
||||||
layer_name : StringProperty(
|
layer_name : StringProperty(
|
||||||
name="Layer Name",
|
name="Layer Name",
|
||||||
description="The layer name, should describe the content of the layer",
|
description="The layer name, should describe the content of the layer",
|
||||||
default="")# update=None, get=None, set=None
|
default="",
|
||||||
|
update=update_layer_name)# update=None, get=None, set=None
|
||||||
"""
|
"""
|
||||||
reconnect_parent = bpy.props.PointerProperty(type =bpy.types.Object,poll=poll_armature)
|
reconnect_parent = bpy.props.PointerProperty(type =bpy.types.Object,poll=poll_armature)
|
||||||
render_settings = bpy.props.BoolProperty(default = False)
|
render_settings = bpy.props.BoolProperty(default = False)
|
||||||
|
|
Loading…
Reference in New Issue