object renumbering from depth

0.9.0

- feat: Renumber objects prefix according to origin point depth, and button to remove
- ui: improve dopesheet panel readability
main
Pullusb 2022-01-22 19:13:11 +01:00
parent 55f9248c6a
commit 3aa8ccccfe
4 changed files with 120 additions and 13 deletions

View File

@ -14,12 +14,17 @@ Activate / deactivate layer opaticty according to prefix
Activate / deactivate all masks using MA layers
-->
0.9.0
- feat: Renumber objects prefix according to origin point depth, and button to remove
- ui: improve dopesheet panel readability
0.8.0
- feat: Select a file output node. Set active file slot path and settings to main Scene output.
- Button in GP render panel with `Advanced` options active.
- Or search operator label `Set Active File Output To Composite`
- if Composite is already linked, pop-up ask if link should be replaced
- Button in GP render panel with `Advanced` options active.
- Or search operator label `Set Active File Output To Composite`
- if Composite is already linked, pop-up ask if link should be replaced
0.7.0

View File

@ -5,6 +5,8 @@ from bpy.props import (FloatProperty,
StringProperty,
IntProperty)
from . import fn
import math
import re
class GPEXP_OT_layers_state(bpy.types.Operator):
bl_idname = "gp.layers_state"
@ -221,9 +223,103 @@ class GPEXP_OT_lower_layers_name(bpy.types.Operator):
return {"FINISHED"}
class GPEXP_OT_auto_number_object(bpy.types.Operator):
bl_idname = "gp.auto_number_object"
bl_label = "Auto Number Object"
bl_description = "Automatic prefix number based on origin distance to camera and in_front values\nCtrl + Clic to delete name to delete numbering"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.object and context.object.type == 'GPENCIL'
all_objects : BoolProperty(name='On All GP Object',
default=False, description='On All object, else use selected Grease Pencil objects') # , options={'SKIP_SAVE'}
rename_data : BoolProperty(name='Rename Gpencil Data',
default=True, description='Rename Also the Grease Pencil data using same name as object') # , options={'SKIP_SAVE'}
delete : BoolProperty(default=False, options={'SKIP_SAVE'})
def invoke(self, context, event):
# if event.alt:
# self.all_objects=True
if event.ctrl or self.delete:
regex_num = re.compile(r'^(\d{3})_')
ct = 0
gps = [o for o in context.selected_objects if o.type == 'GPENCIL']
for o in gps:
if regex_num.match(o.name):
o.name = o.name[4:]
ct += 1
self.report({'INFO'}, f'{ct}/{len(gps)} number prefix removed from object names')
return {"FINISHED"}
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
layout.prop(self, 'all_objects')
if self.all_objects:
gp_ct = len([o for o in context.scene.objects if o.type == 'GPENCIL'])
else:
gp_ct = len([o for o in context.selected_objects if o.type == 'GPENCIL'])
layout.prop(self, 'rename_data')
layout.label(text=f'{gp_ct} objects to renumber')
if not gp_ct:
layout.label(text='No Gpencil object to renumber', icon = 'ERROR')
def execute(self, context):
if self.all_objects:
pool = [o for o in context.scene.objects if o.type == 'GPENCIL']
else:
pool = [o for o in context.selected_objects if o.type == 'GPENCIL']
def reversed_enumerate(collection: list):
for i in range(len(collection)-1, -1, -1):
yield i, collection[i]
fronts = []
## separate In Front objects:
for i, o in reversed_enumerate(pool):
if o.show_in_front:
fronts.append(pool.pop(i))
cam_loc = context.scene.camera.matrix_world.to_translation()
# filter by distance to camera object (considering origins)
pool.sort(key=lambda x: math.dist(x.matrix_world.to_translation(), cam_loc))
fronts.sort(key=lambda x: math.dist(x.matrix_world.to_translation(), cam_loc))
# re-insert fitlered infront object before others
pool = fronts + pool
ct = 10
regex_num = re.compile(r'^(\d{3})_')
for o in pool:
renum = regex_num.search(o.name)
if not renum:
o.name = f'{str(ct).zfill(3)}_{o.name}'
else:
## either replace or leave untouched
# continue
o.name = f'{str(ct).zfill(3)}_{o.name[4:]}'
ct += 10
if self.rename_data and o.name != o.data.name:
o.data.name = o.name
return {"FINISHED"}
classes=(
GPEXP_OT_layers_state,
GPEXP_OT_lower_layers_name
GPEXP_OT_lower_layers_name,
GPEXP_OT_auto_number_object
)
def register():

View File

@ -2,7 +2,7 @@ bl_info = {
"name": "GP Render",
"description": "Organise export of gp layers through compositor output",
"author": "Samuel Bernou",
"version": (0, 8, 0),
"version": (0, 9, 0),
"blender": (2, 93, 0),
"location": "View3D",
"warning": "",

22
ui.py
View File

@ -178,15 +178,16 @@ class GPEXP_PT_gp_dopesheet_ui(Panel):
layout.label(text=f'(Active dopesheet layer not in active obj)')
## On layers
col = layout.column()
if context.object and context.object.type == 'GPENCIL':
txt = f'{len([l for l in context.object.data.layers if l.select])} Layer(s) To Render'
else:
txt = 'Layer To Render'
layout.operator('gp.add_layer_to_render', icon='RENDERLAYERS', text=txt)
col.operator('gp.add_layer_to_render', icon='RENDERLAYERS', text=txt)
# merge (only accessible if multiple layers selected)
row = layout.row()
row = col.row()
ct = len([l for l in context.object.data.layers if l.select])
txt = f'Merge {ct} layers'
# merge layers from dopesheet
@ -197,16 +198,21 @@ class GPEXP_PT_gp_dopesheet_ui(Panel):
## all and objects
layout.separator()
layout.label(text='Whole objects:')
col = layout.column()
col.label(text='Whole Objects:')
if context.scene.name != 'Render':
txt = f'{len([o for o in context.selected_objects if o.type == "GPENCIL" and o.select_get()])} Selected Object(s) To Render'
layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text=txt).mode='SELECTED'
layout.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All Visible GP To Render').mode='ALL'
col.operator('gp.add_object_to_render', icon='RENDERLAYERS', text=txt).mode='SELECTED'
col.operator('gp.add_object_to_render', icon='RENDERLAYERS', text='All Visible GP To Render').mode='ALL'
layout.separator()
layout.operator('gp.layers_state', icon='CHECKMARK', text='Check layers')
layout.operator('gp.lower_layers_name', icon='SYNTAX_OFF', text='Rename Lowercase')
col = layout.column()
col.label(text='Fixes:')
row = col.row(align=True)
row.operator('gp.auto_number_object', icon='OBJECT_DATAMODE', text='Renumber Objects')
row.operator('gp.auto_number_object', icon='X', text='').delete = True
col.operator('gp.layers_state', icon='CHECKMARK', text='Check layers')
col.operator('gp.lower_layers_name', icon='SYNTAX_OFF', text='Rename Lowercase')
# row = layout.row()
layout.prop(bpy.context.preferences.edit, 'use_anim_channel_group_colors')