2021-09-10 18:32:50 +02:00
|
|
|
import bpy
|
|
|
|
from . import fn
|
|
|
|
|
|
|
|
## direct use (Pop up menu version below)
|
|
|
|
"""
|
|
|
|
class GPEXP_OT_clean_compo_tree(bpy.types.Operator):
|
|
|
|
bl_idname = "gp.clean_compo_tree"
|
|
|
|
bl_label = "Clean Compo Tree"
|
|
|
|
bl_description = "Reorder inputs/outputs and clear unused viewlayers"
|
|
|
|
bl_options = {"REGISTER"}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
return True
|
|
|
|
|
|
|
|
# mode : bpy.props.StringProperty(default='NORMAL', options={'SKIP_SAVE'})
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
render = bpy.data.scenes.get('Render')
|
|
|
|
if not render:
|
|
|
|
print('SKIP, no Render scene')
|
|
|
|
return {"CANCELLED"}
|
|
|
|
|
|
|
|
print('re-arranging frames')
|
|
|
|
fn.rearrange_frames(render.node_tree)
|
|
|
|
|
|
|
|
for n in render.node_tree.nodes:
|
|
|
|
if n.name.startswith('NG_'):
|
|
|
|
fn.reorder_inputs(n)
|
|
|
|
fn.reorder_outputs(n)
|
|
|
|
|
|
|
|
# get output node to reorder output
|
|
|
|
out = None
|
|
|
|
for s in n.outputs:
|
|
|
|
if not s.is_linked:
|
|
|
|
continue
|
|
|
|
out = s.links[0].to_node
|
|
|
|
if out.type == 'OUTPUT_FILE':
|
|
|
|
break
|
|
|
|
if out:
|
|
|
|
fn.reorder_fileout(out, ng=n)
|
|
|
|
|
|
|
|
|
|
|
|
## clear disconnected fileout ??...
|
|
|
|
# for fo in render.node_tree.nodes:
|
|
|
|
# if fo.type != 'OUTPUT_FILE':
|
|
|
|
# continue
|
|
|
|
# fn.clear_disconnected(fo)
|
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class GPEXP_OT_clean_compo_tree(bpy.types.Operator):
|
|
|
|
bl_idname = "gp.clean_compo_tree"
|
|
|
|
bl_label = "Clean Compo Tree"
|
|
|
|
bl_description = "Pop up menu with cleaning options"
|
|
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
|
|
|
|
clear_unused_view_layers : bpy.props.BoolProperty(name="Clear unused view layers",
|
|
|
|
description="Delete view layer that aren't used in the nodetree anymore",
|
|
|
|
default=True)
|
|
|
|
|
2021-12-09 12:14:57 +01:00
|
|
|
arrange_rl_nodes : bpy.props.BoolProperty(name="Arrange Render Node In Frames",
|
|
|
|
description="Re-arrange Render Layer Nodes Y positions within each existing frames" ,
|
|
|
|
default=True)
|
|
|
|
|
2021-09-10 18:32:50 +02:00
|
|
|
arrange_frames : bpy.props.BoolProperty(name="Arrange Frames",
|
|
|
|
description="Re-arrange all frames Y positions" ,
|
|
|
|
default=True)
|
|
|
|
|
|
|
|
reorder_inputs : bpy.props.BoolProperty(name="Reorder I/O Sockets",
|
|
|
|
description="Reorder inputs/outputs of all 'NG_' nodegroup and their connected file output",
|
|
|
|
default=True)
|
|
|
|
|
2022-01-26 16:32:33 +01:00
|
|
|
clear_isolated_node_in_groups : bpy.props.BoolProperty(name="Clear Isolated Node In Groups",
|
|
|
|
description="Clean content of 'NG_' nodegroup bpy deleting isolated nodes)",
|
|
|
|
default=True)
|
|
|
|
|
2021-09-10 18:32:50 +02:00
|
|
|
fo_clear_disconnected : bpy.props.BoolProperty(name="Remove Disconnected Export Inputs",
|
|
|
|
description="Clear any disconnected intput of every 'file output' node",
|
|
|
|
default=False)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def invoke(self, context, event):
|
|
|
|
# self.nodes = context.object
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
layout.prop(self, 'clear_unused_view_layers')
|
2021-12-09 12:14:57 +01:00
|
|
|
layout.prop(self, 'arrange_rl_nodes')
|
2021-09-10 18:32:50 +02:00
|
|
|
layout.prop(self, 'arrange_frames')
|
|
|
|
layout.prop(self, 'reorder_inputs')
|
2022-01-26 16:32:33 +01:00
|
|
|
layout.prop(self, 'clear_isolated_node_in_groups')
|
2021-09-10 18:32:50 +02:00
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
layout.prop(self, 'fo_clear_disconnected')
|
|
|
|
if self.fo_clear_disconnected:
|
|
|
|
layout.label(text='Disconnected inputs are not exported', icon='INFO')
|
|
|
|
|
|
|
|
# box = layout.box()
|
|
|
|
# box.prop(self, 'arrange_frames')
|
|
|
|
# box.prop(self, 'reorder_inputs')
|
|
|
|
# box.prop(self, 'fo_clear_disconnected')
|
|
|
|
|
|
|
|
def execute(self, context):
|
2021-09-30 18:51:49 +02:00
|
|
|
# render = bpy.data.scenes.get('Render')
|
|
|
|
# if not render:
|
|
|
|
# print('SKIP, no Render scene')
|
|
|
|
# return {"CANCELLED"}
|
|
|
|
render = context.scene
|
|
|
|
|
2021-09-10 18:32:50 +02:00
|
|
|
nodes = render.node_tree.nodes
|
|
|
|
if self.clear_unused_view_layers:
|
|
|
|
used_rlayer_names = [n.layer for n in nodes if n.type == 'R_LAYERS']
|
|
|
|
for rl in reversed(render.view_layers):
|
|
|
|
if rl.name in used_rlayer_names or rl.name == 'View Layer':
|
|
|
|
continue
|
|
|
|
render.view_layers.remove(rl)
|
|
|
|
|
2021-12-09 12:14:57 +01:00
|
|
|
if self.arrange_rl_nodes:
|
|
|
|
fn.rearrange_rlayers_in_frames(render.node_tree)
|
|
|
|
|
2021-09-10 18:32:50 +02:00
|
|
|
if self.arrange_frames:
|
|
|
|
fn.rearrange_frames(render.node_tree)
|
|
|
|
|
|
|
|
if self.reorder_inputs:
|
|
|
|
for n in nodes:
|
2021-09-15 18:28:16 +02:00
|
|
|
if n.type != 'GROUP' or not n.name.startswith('NG_'):
|
|
|
|
continue
|
|
|
|
fn.reorder_inputs(n)
|
|
|
|
fn.reorder_outputs(n)
|
|
|
|
|
|
|
|
# get output node to reorder output
|
|
|
|
out = None
|
|
|
|
for s in n.outputs:
|
|
|
|
if not s.is_linked:
|
|
|
|
continue
|
|
|
|
out = s.links[0].to_node
|
|
|
|
if out.type == 'OUTPUT_FILE':
|
|
|
|
break
|
|
|
|
if out:
|
|
|
|
fn.reorder_fileout(out, ng=n)
|
|
|
|
|
|
|
|
# Clear input that do not exists
|
|
|
|
fn.clean_nodegroup_inputs(n, skip_existing_pass=True)
|
2021-10-01 12:42:21 +02:00
|
|
|
|
|
|
|
fn.bridge_reconnect_nodegroup(n)
|
2021-09-10 18:32:50 +02:00
|
|
|
|
2022-01-26 16:32:33 +01:00
|
|
|
if self.clear_isolated_node_in_groups:
|
|
|
|
for n in nodes:
|
|
|
|
if n.type != 'GROUP' or not n.name.startswith('NG_'):
|
|
|
|
continue
|
|
|
|
fn.clear_nodegroup_content_if_disconnected(n.node_tree)
|
|
|
|
|
2021-09-10 18:32:50 +02:00
|
|
|
if self.fo_clear_disconnected:
|
|
|
|
for fo in nodes:
|
|
|
|
if fo.type != 'OUTPUT_FILE':
|
|
|
|
continue
|
|
|
|
fn.clear_disconnected(fo)
|
|
|
|
|
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes=(
|
|
|
|
GPEXP_OT_clean_compo_tree,
|
|
|
|
)
|
|
|
|
|
|
|
|
def register():
|
|
|
|
for cls in classes:
|
|
|
|
bpy.utils.register_class(cls)
|
|
|
|
|
|
|
|
def unregister():
|
|
|
|
for cls in reversed(classes):
|
|
|
|
bpy.utils.unregister_class(cls)
|