Select node from layers

0.9.7

- feat: `Select Nodes` added in Dopesheet. Select nodes associated with selected gp layers and report if there are errors
main
Pullusb 2022-02-07 16:05:47 +01:00
parent a9c9de2f76
commit d43e59b7c7
5 changed files with 109 additions and 1 deletions

View File

@ -14,6 +14,10 @@ Activate / deactivate layer opaticty according to prefix
Activate / deactivate all masks using MA layers Activate / deactivate all masks using MA layers
--> -->
0.9.7
- feat: `Select Nodes` added in Dopesheet. Select nodes associated with selected gp layers and report if there are errors
0.9.6 0.9.6
- added: `Check layers` disable multiframe-edit in all gp data. Seemed to cause artifacts on some renders (tested on 2.93.5) - added: `Check layers` disable multiframe-edit in all gp data. Seemed to cause artifacts on some renders (tested on 2.93.5)

View File

@ -534,12 +534,82 @@ class GPEXP_OT_check_masks(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class GPEXP_OT_select_layer_in_comp(bpy.types.Operator):
bl_idname = "gp.select_layer_in_comp"
bl_label = "Select Layer In Compositor"
bl_description = "Select associated render_layer node in compositing"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.object and context.object.type == 'GPENCIL'
def execute(self, context):
gp = context.object.data
act = gp.layers.active
pool = fn.build_layers_targets_from_dopesheet(context)
if not pool:
self.report({'ERROR'}, 'No layers found in current GP dopesheet')
return {"CANCELLED"}
if not context.scene.node_tree:
self.report({'ERROR'}, 'No compo node-tree in active scene')
return {"CANCELLED"}
nodes = context.scene.node_tree.nodes
rl_nodes = [n for n in nodes if n.type == 'R_LAYERS']
if not rl_nodes:
self.report({'ERROR'}, 'No render layers nodes in active scene')
return {"CANCELLED"}
used_vl = [n.layer for n in rl_nodes]
selected = []
infos = []
for l in pool:
if not l.select:
continue
vl_name = l.viewlayer_render
if not vl_name:
mess = f'{l.info} has no viewlayers'
print(mess)
infos.append(mess)
continue
if not context.scene.view_layers.get(vl_name):
mess = f'/!\ {l.info}: view layer "{vl_name}" does not exists '
print(mess)
infos.append(mess)
continue
if not vl_name in used_vl:
mess = f'{l.info}: view layer "{vl_name}" not used in scene renderlayer nodes'
print(mess)
infos.append(mess)
continue
for n in rl_nodes:
if n.layer == vl_name:
print(f'{l.info} -> Select node {n.name}')
selected.append(n.name)
n.select = True
if not infos and not selected:
self.report({'ERROR'}, 'Nothing selected')
return {"CANCELLED"}
infos = infos + [f'-- Selected {len(selected)} nodes --'] + selected
fn.show_message_box(_message=infos, _title="Selected viewlayer in compo", _icon='INFO')
return {"FINISHED"}
classes=( classes=(
GPEXP_OT_auto_number_object, GPEXP_OT_auto_number_object,
GPEXP_OT_lower_layers_name, GPEXP_OT_lower_layers_name,
GPEXP_OT_export_infos_for_compo, GPEXP_OT_export_infos_for_compo,
GPEXP_OT_layers_state, GPEXP_OT_layers_state,
GPEXP_OT_check_masks, GPEXP_OT_check_masks,
GPEXP_OT_select_layer_in_comp,
) )
def register(): def register():

View File

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

33
fn.py
View File

@ -835,6 +835,39 @@ def normalize_layer_name(layer, prefix='', desc='', suffix='', lower=True, dash_
print(f' - updated in {ob.name} modifier {m.name}') print(f' - updated in {ob.name} modifier {m.name}')
m.layer = new m.layer = new
# unused currently
def build_dope_gp_list(layer_list):
'''Take a list of GP layers return a dict with pairs {gp data : own layer list}'''
from collections import defaultdict
gps = defaultdict(list)
for l in layer_list:
gps[l.id_data].append(l)
return gps
def build_layers_targets_from_dopesheet(context):
'''Return all selected layers on context GP dopesheet according to seelction and filters'''
ob = context.object
gpl = context.object.data.layers
act = gpl.active
dopeset = context.space_data.dopesheet
if dopeset.show_only_selected:
pool = [o for o in context.selected_objects if o.type == 'GPENCIL']
else:
pool = [o for o in context.scene.objects if o.type == 'GPENCIL']
if not dopeset.show_hidden:
pool = [o for o in pool if o.visible_get()]
layer_pool = [l for o in pool for l in o.data.layers]
layer_pool = list(set(layer_pool)) # remove dupli-layers from same data source with
# apply search filter
if dopeset.filter_text:
layer_pool = [l for l in layer_pool if (dopeset.filter_text.lower() in l.info.lower()) ^ dopeset.use_filter_invert]
return layer_pool
""" # old show message gox without operator support """ # old show message gox without operator support
def show_message_box(_message = "", _title = "Message Box", _icon = 'INFO'): def show_message_box(_message = "", _title = "Message Box", _icon = 'INFO'):
'''get a str to display or a list of [str, str] '''get a str to display or a list of [str, str]

1
ui.py
View File

@ -187,6 +187,7 @@ class GPEXP_PT_gp_dopesheet_ui(Panel):
## On layers ## On layers
col = layout.column() col = layout.column()
col.operator('gp.select_layer_in_comp', icon='RESTRICT_SELECT_OFF', text='Select Nodes')
if context.object and context.object.type == 'GPENCIL': 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' txt = f'{len([l for l in context.object.data.layers if l.select])} Layer(s) To Render'
else: else: