gpv3 port: create empty frames - add support for group as source
add utility function to check hide-lock state of nested itemsmaster
parent
b525cda28e
commit
49c70860a6
|
@ -11,17 +11,34 @@ def get_layer_list(self, context):
|
|||
'''return (identifier, name, description) of enum content'''
|
||||
return [(l.name, l.name, '') for l in context.object.data.layers if l != context.object.data.layers.active]
|
||||
|
||||
def get_group_list(self, context):
|
||||
return [(g.name, g.name, '') for g in context.object.data.layer_groups]
|
||||
|
||||
def get_top_layer_from_group(gp, group):
|
||||
upper_layer = None
|
||||
for layer in gp.layers:
|
||||
if layer.parent_group == group:
|
||||
upper_layer = layer
|
||||
return upper_layer
|
||||
|
||||
class GP_OT_create_empty_frames(bpy.types.Operator):
|
||||
bl_idname = "gp.create_empty_frames"
|
||||
bl_label = "Create Empty Frames"
|
||||
bl_description = "Create new empty frames on active layer where there is a frame in layer above\n(usefull in color layers to match line frames)"
|
||||
bl_description = "Create new empty frames on active layer where there is a frame in targeted layers\
|
||||
\n(usefull in color layers to match line frames)"
|
||||
bl_options = {'REGISTER','UNDO'}
|
||||
|
||||
layers_enum : EnumProperty(
|
||||
name="Duplicate to layers",
|
||||
description="Duplicate selected keys in active layer and send them to choosen layer",
|
||||
name="Empty Keys from Layer",
|
||||
description="Reference keys from layer",
|
||||
items=get_layer_list
|
||||
)
|
||||
|
||||
groups_enum : EnumProperty(
|
||||
name="Empty Keys from Group",
|
||||
description="Duplicate keys from group",
|
||||
items=get_group_list
|
||||
)
|
||||
|
||||
targeted_layers : EnumProperty(
|
||||
name="Sources", # Empty keys from targets
|
||||
|
@ -34,7 +51,8 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
('ABOVE', 'Layer Directly Above', 'Empty frames from layer directly above'),
|
||||
('BELOW', 'Layer Directly Below', 'Empty frames from layer directly below'),
|
||||
('ALL_VISIBLE', 'Visible', 'Empty frames from all visible layers'),
|
||||
('CHOSEN', 'Chosen layer', ''),
|
||||
('CHOSEN', 'Chosen layer', 'Empty frames from a specific layer'),
|
||||
('CHOSEN_GROUP', 'Chosen group', 'Empty frames from a specific layer group'),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -63,6 +81,13 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
# Possible preset with shortcut
|
||||
# if event.alt:
|
||||
# self.targeted_layers = 'ALL_VISIBLE'
|
||||
gp = context.grease_pencil
|
||||
layer_from_group = None
|
||||
if gp.layer_groups.active:
|
||||
layer_from_group = get_top_layer_from_group(gp, gp.layer_groups.active)
|
||||
if not gp.layers.active and not layer_from_group:
|
||||
self.report({'ERROR'}, 'No active layer or active group containing layer on GP object')
|
||||
return {'CANCELLED'}
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
|
@ -74,7 +99,13 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
if self.layers_enum:
|
||||
layout.prop(self, 'layers_enum')
|
||||
else:
|
||||
layout.label(text='No other layers to match keyframe')
|
||||
layout.label(text='No other layers to match keyframe!', icon='ERROR')
|
||||
|
||||
if self.targeted_layers == 'CHOSEN_GROUP':
|
||||
if self.groups_enum:
|
||||
layout.prop(self, 'groups_enum')
|
||||
else:
|
||||
layout.label(text='No other groups to match keyframe!', icon='ERROR')
|
||||
|
||||
elif self.targeted_layers == 'NUMBER':
|
||||
row = layout.row()
|
||||
|
@ -91,20 +122,28 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
|
||||
def execute(self, context):
|
||||
obj = context.object
|
||||
gpl = obj.data.layers
|
||||
|
||||
gp = obj.data
|
||||
gpl = gp.layers
|
||||
|
||||
if gp.layer_groups.active:
|
||||
reference_layer = get_top_layer_from_group(gp, gp.layer_groups.active)
|
||||
else:
|
||||
reference_layer = gpl.active
|
||||
|
||||
active_index = next((i for i, l in enumerate(gpl) if l == reference_layer), None)
|
||||
|
||||
print(self.targeted_layers)
|
||||
if self.targeted_layers == 'ALL_ABOVE':
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i > gpl.active_index]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i > active_index]
|
||||
|
||||
elif self.targeted_layers == 'ALL_BELOW':
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i < gpl.active_index]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i < active_index]
|
||||
|
||||
elif self.targeted_layers == 'ABOVE':
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i == gpl.active_index + 1]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i == active_index + 1]
|
||||
|
||||
elif self.targeted_layers == 'BELOW':
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i == gpl.active_index - 1]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if i == active_index - 1]
|
||||
|
||||
elif self.targeted_layers == 'ALL_VISIBLE':
|
||||
tgt_layers = [l for l in gpl if not l.hide and l != gpl.active]
|
||||
|
@ -115,17 +154,24 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
return {'CANCELLED'}
|
||||
tgt_layers = [l for l in gpl if l.name == self.layers_enum]
|
||||
|
||||
elif self.targeted_layers == 'CHOSEN_GROUP':
|
||||
if not self.groups_enum:
|
||||
self.report({'ERROR'}, f"No chosen groups, aborted")
|
||||
return {'CANCELLED'}
|
||||
group = gp.layer_groups.get(self.groups_enum)
|
||||
tgt_layers = [l for l in gpl if l.parent_group == group]
|
||||
|
||||
elif self.targeted_layers == 'NUMBER':
|
||||
if self.number == 0:
|
||||
self.report({'ERROR'}, f"Can't have 0 as value")
|
||||
return {'CANCELLED'}
|
||||
|
||||
l_range = gpl.active_index + self.number
|
||||
l_range = active_index + self.number
|
||||
print('l_range: ', l_range)
|
||||
if self.number > 0: # positive
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if gpl.active_index < i <= l_range]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if active_index < i <= l_range]
|
||||
else:
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if gpl.active_index > i >= l_range]
|
||||
tgt_layers = [l for i, l in enumerate(gpl) if active_index > i >= l_range]
|
||||
|
||||
if not tgt_layers:
|
||||
self.report({'ERROR'}, f"No layers found with chosen Targets")
|
||||
|
@ -163,7 +209,7 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
|||
if num in current_frames:
|
||||
continue
|
||||
#Create empty frame
|
||||
gpl.active.frames.new(num, active=False)
|
||||
gpl.active.frames.new(num)
|
||||
fct += 1
|
||||
|
||||
gpl.update()
|
||||
|
|
38
utils.py
38
utils.py
|
@ -155,6 +155,44 @@ def gp_stroke_to_bmesh(strokes):
|
|||
### GP Drawing
|
||||
# -----------------
|
||||
|
||||
def layer_active_index(gpl):
|
||||
'''Get layer list and return index of active layer
|
||||
Can return None if no active layer found (active item can be a group)
|
||||
'''
|
||||
return next((i for i, l in enumerate(gpl) if l == gpl.active), None)
|
||||
|
||||
## Check for nested lock
|
||||
def is_locked(stack_item):
|
||||
'''Check if passed stack item (layer or group) is locked
|
||||
either itself or by parent groups'''
|
||||
if stack_item.lock:
|
||||
return True
|
||||
if stack_item.parent_group:
|
||||
return is_locked(stack_item.parent_group)
|
||||
return False
|
||||
|
||||
def is_parent_locked(stack_item):
|
||||
'''Check if passed stack item (layer or group) is locked by parent groups'''
|
||||
if stack_item.parent_group:
|
||||
return is_locked(stack_item.parent_group)
|
||||
return False
|
||||
|
||||
## Check for nested hide
|
||||
def is_hidden(stack_item):
|
||||
'''Check if passed stack item (layer or group) is hidden
|
||||
either itself or by parent groups'''
|
||||
if stack_item.hide:
|
||||
return True
|
||||
if stack_item.parent_group:
|
||||
return is_hidden(stack_item.parent_group)
|
||||
return False
|
||||
|
||||
def is_parent_hidden(stack_item):
|
||||
'''Check if passed stack item (layer or group) is hidden by parent groups'''
|
||||
if stack_item.parent_group:
|
||||
return is_hidden(stack_item.parent_group)
|
||||
return False
|
||||
|
||||
def simple_draw_gp_stroke(pts, frame, width = 2, mat_id = 0):
|
||||
'''
|
||||
draw basic stroke by passing list of point 3D coordinate
|
||||
|
|
Loading…
Reference in New Issue