object renumbering from depth
0.9.0 - feat: Renumber objects prefix according to origin point depth, and button to remove - ui: improve dopesheet panel readabilitymain
parent
55f9248c6a
commit
3aa8ccccfe
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
22
ui.py
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue