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
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
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
|
||||
|
||||
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
|
||||
|
||||
|
|
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)",
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue