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
|
||||
-->
|
||||
|
||||
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
|
||||
|
||||
- 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"}
|
||||
|
||||
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=(
|
||||
GPEXP_OT_auto_number_object,
|
||||
GPEXP_OT_lower_layers_name,
|
||||
GPEXP_OT_export_infos_for_compo,
|
||||
GPEXP_OT_layers_state,
|
||||
GPEXP_OT_check_masks,
|
||||
GPEXP_OT_select_layer_in_comp,
|
||||
)
|
||||
|
||||
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, 9, 6),
|
||||
"version": (0, 9, 7),
|
||||
"blender": (2, 93, 0),
|
||||
"location": "View3D",
|
||||
"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}')
|
||||
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
|
||||
def show_message_box(_message = "", _title = "Message Box", _icon = 'INFO'):
|
||||
'''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
|
||||
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':
|
||||
txt = f'{len([l for l in context.object.data.layers if l.select])} Layer(s) To Render'
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue