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 option
gpv2
Pullusb 2021-07-20 18:53:39 +02:00
parent 9612c84396
commit 212436c451
5 changed files with 137 additions and 44 deletions

View File

@ -1,5 +1,12 @@
# 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
- feat: check list, specify in addon pref if you prefer a dry run (check without set)

View File

@ -1,8 +1,9 @@
from os import error
import bpy
import re
from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.app.handlers import persistent
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})_)?(.*)' # matching only two letter
# 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
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
@ -26,27 +29,31 @@ def layer_name_build(layer, prefix='', prefix2='', desc=''):
pattern = pattern.replace('_', sep) # set separator
res = re.search(pattern, name)
p1, p2, p3 = res.group(1), res.group(2), res.group(3)
## empty instead of None
p1 = '' if p1 is None else p1
p2 = '' if p2 is None else p2
p3 = '' if p3 is None else p3
res = re.search(pattern, name.strip())
p1 = '' if res.group(1) is None else res.group(1)
p2 = '' if res.group(2) is None else res.group(2)
p3 = '' if res.group(3) is None else res.group(3)
p4 = '' if res.group(4) is None else res.group(4)
if prefix:
if prefix == 'prefixkillcode':
p1 = ''
else:
p1 = prefix.upper() + sep
p1 = prefix.upper().strip() + sep
if prefix2:
p2 = prefix2.upper() + sep
p2 = prefix2.upper().strip() + sep
if 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
## multi-prefix solution (Caps letters)
@ -63,6 +70,7 @@ class GPTB_OT_layer_name_build(Operator):
prefix : StringProperty(default='', options={'SKIP_SAVE'})
prefix2 : StringProperty(default='', options={'SKIP_SAVE'})
desc : StringProperty(default='', options={'SKIP_SAVE'})
suffix : StringProperty(default='', options={'SKIP_SAVE'})
def execute(self, context):
ob = context.object
@ -71,10 +79,10 @@ class GPTB_OT_layer_name_build(Operator):
if not act:
self.report({'ERROR'}, 'no layer active')
return {"CANCELLED"}
for l in gpl:
if not l.select:
continue
layer_name_build(l, prefix=self.prefix, prefix2=self.prefix2, desc=self.desc)
if l.select or l == act:
layer_name_build(l, prefix=self.prefix, prefix2=self.prefix2, desc=self.desc, suffix=self.suffix)
return {"FINISHED"}
@ -284,33 +292,42 @@ def layer_name_builder(self, context):
'''appended to DATA_PT_gpencil_layers'''
prefs = get_addon_prefs()
if not prefs.prefixes:
if not prefs.show_prefix_buttons:
return
if not prefs.prefixes and not prefs.suffixes:
return
layout = self.layout
# {'EDIT_GPENCIL', 'PAINT_GPENCIL','SCULPT_GPENCIL','WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
# layout.separator()
col = layout.column()
all_prefixes = prefs.prefixes.split(',')
all_suffixes = prefs.suffixes.split(',')
line_limit = 8
## first prefix
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'
if prefs.prefixes:
## first prefix
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
# row = layout.row(align=True)
# for task in prefs.prefixes: # 'PO', 'AN'
# row.operator("me.set_layer_name", text=task).prefix2 = task
## secondary prefix ?
## name (description)
row = col.row(align=True)
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 ---
@ -334,6 +351,39 @@ def gpencil_layer_dropdown_menu(self, context):
'''to append in GPENCIL_MT_layer_context_menu'''
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=(
GPTB_OT_rename_gp_layer,
GPTB_OT_layer_name_build,
@ -348,11 +398,16 @@ def register():
bpy.types.DATA_PT_gpencil_layers.prepend(layer_name_builder)
bpy.types.DOPESHEET_HT_header.append(gpencil_dopesheet_header)
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():
bpy.app.handlers.load_post.remove(subscribe_handler)
bpy.types.GPENCIL_MT_layer_context_menu.remove(gpencil_layer_dropdown_menu)
bpy.types.DOPESHEET_HT_header.remove(gpencil_dopesheet_header)
bpy.types.DATA_PT_gpencil_layers.remove(layer_name_builder)
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)

View File

@ -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
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_HEIGHT` : resolution y
`FPS` : project frame rate
`PALETTES` : path to the blends (or json) containing materials palettes
`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')
`SEPARATOR` : Separator character to determine prefixes, default is '_' (should not be a special regex character)
`RENDER_WIDTH` : resolution x
`RENDER_HEIGHT` : resolution y
`FPS` : project frame rate
`PALETTES` : path to the blends (or json) containing materials palettes
`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')
`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

View File

@ -234,6 +234,17 @@ class GPTB_prefs(bpy.types.AddonPreferences):
description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)",
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_auto_play : BoolProperty(
name="Playblast auto play",
@ -364,7 +375,10 @@ class GPTB_prefs(bpy.types.AddonPreferences):
subbox = box.box()
subbox.label(text='Namespace:')
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
@ -504,6 +518,9 @@ def set_env_properties():
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
separator = os.getenv('SEPARATOR')
prefs.separator = separator if separator else prefs.separator

View File

@ -8,7 +8,7 @@ from bpy.props import (
)
from .OP_cursor_snap_canvas import cursor_follow_update
from .OP_layer_manager import layer_name_build
def change_edit_lines_opacity(self, context):
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
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):
check_only : BoolProperty(
@ -168,7 +180,8 @@ class GP_PG_ToolsSettings(bpy.types.PropertyGroup):
layer_name : StringProperty(
name="Layer Name",
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)
render_settings = bpy.props.BoolProperty(default = False)