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 errorsmain
parent
a9c9de2f76
commit
d43e59b7c7
|
@ -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)
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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
33
fn.py
|
@ -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
1
ui.py
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue