From 1a97f75692744c77b14f2b6e0a5f15e6d8d7bcdd Mon Sep 17 00:00:00 2001 From: pullusb Date: Tue, 16 Jan 2024 16:55:07 +0100 Subject: [PATCH] connect selection to new or existing fileout --- CHANGELOG.md | 4 +++ OP_manage_outputs.py | 21 ++++++++++++ __init__.py | 2 +- fn.py | 78 ++++++++++++++++++++++++++++++++++++++++++++ ui.py | 1 + 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71ca392..9f4d1b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ Activate / deactivate layer opacity according to prefix Activate / deactivate all masks using MA layers --> +1.6.0 + +- added: Connect selection to new or existing fileout + 1.5.0 - added: swf export (include binary for linux and windows) diff --git a/OP_manage_outputs.py b/OP_manage_outputs.py index 8eeb776..6293202 100644 --- a/OP_manage_outputs.py +++ b/OP_manage_outputs.py @@ -256,6 +256,26 @@ class GPEXP_OT_reset_render_settings(bpy.types.Operator): return {"FINISHED"} +class GPEXP_OT_connect_selected_to_file_out(bpy.types.Operator): + bl_idname = "gp.connect_selected_to_file_out" + bl_label = "Connect Selected To File Output" + bl_description = "Connect Selected Nodes to a fileoutput node\ + \nIf a fileoutput node is selected, socket are added to it" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + scn = context.scene + nodes = scn.node_tree.nodes + selected = [n for n in nodes if n.select] + outfile = next((n for n in selected if n.type == 'OUTPUT_FILE'), None) + # Exclude output file from + selected = [n for n in selected if n.type != 'OUTPUT_FILE'] + + # fn.connect_to_file_output(selected, outfile) + for n in selected: + fn.connect_to_file_output(n, outfile) + return {"FINISHED"} + classes=( GPEXP_OT_mute_toggle_output_nodes, GPEXP_OT_set_output_node_format, @@ -263,6 +283,7 @@ GPEXP_OT_number_outputs, GPEXP_OT_enable_all_viewlayers, GPEXP_OT_activate_only_selected_layers, GPEXP_OT_reset_render_settings, +GPEXP_OT_connect_selected_to_file_out, # GPEXP_OT_normalize_outnames, ) diff --git a/__init__.py b/__init__.py index e7226b7..03cc72a 100644 --- a/__init__.py +++ b/__init__.py @@ -2,7 +2,7 @@ bl_info = { "name": "GP Render", "description": "Organise export of gp layers through compositor output", "author": "Samuel Bernou", - "version": (1, 5, 1), + "version": (1, 6, 0), "blender": (3, 0, 0), "location": "View3D", "warning": "", diff --git a/fn.py b/fn.py index 7f1d9e9..d147846 100644 --- a/fn.py +++ b/fn.py @@ -1787,3 +1787,81 @@ def clean_mats_duplication(ob, skip_different_materials=True): if diff_ct: print(f'{diff_ct} mat skipped >> same name but different color settings!') # return ('INFO', f'{diff_ct} mat skipped >> same name but different color settings!') + +def connect_to_file_output(node_list, file_out=None): + scene = bpy.context.scene + nodes = scene.node_tree.nodes + links = scene.node_tree.links + if not isinstance(node_list, list): + node_list = [node_list] + node_list = [n for n in node_list if n.type != 'OUTPUT_FILE'] + if not node_list: + return + + for node in node_list: + ## create one output facing node and connect all + outs = [o for o in node.outputs if not o.is_unavailable and not 'crypto' in o.name.lower()] + cryptout = [o for o in node.outputs if not o.is_unavailable and 'crypto' in o.name.lower()] + + if node.type == 'R_LAYERS': + out_base = node.layer + elif node.label: + out_base = node.label + else: + out_base = node.name + bpy.path.clean_name(out_base) + out_name = f'OUT_{out_base}' + + if outs: + fo = file_out + if not fo: + fo = nodes.get(out_name) + if not fo: + # color = (0.2,0.3,0.5) + fo = create_node('CompositorNodeOutputFile', tree=scene.node_tree, location=(real_loc(node)[0]+500, real_loc(node)[1]+50), width=600) + set_file_output_format(fo) + fo.name = out_name + if node.parent: + fo.parent = node.parent + fo.base_path = f'//render/{out_base}' + + for o in outs: + # if o.name == 'Deprecated': + # continue + slot_name = bpy.path.clean_name(o.name) + slot_name = f'{slot_name}/{slot_name}_' + fo.file_slots.new(slot_name) + out_input = fo.inputs[-1] + links.new(o, out_input) + clear_disconnected(fo) + fo.update() + + ## Create separate file out for cryptos + if cryptout: + out_name += '_cryptos' + fo = file_out + if not fo: + fo = nodes.get(out_name) + if not fo: + # color = (0.2,0.3,0.5) + fo = create_node('CompositorNodeOutputFile', tree=scene.node_tree, location=(real_loc(node)[0]+400, real_loc(node)[1]-200), width=220) + set_file_output_format(fo) + fo.format.file_format = 'OPEN_EXR_MULTILAYER' + fo.format.color_mode = 'RGBA' + fo.format.color_depth = '32' + fo.format.exr_codec = 'ZIP' + fo.name = out_name + if node.parent: + fo.parent = node.parent + fo.base_path = f'//render/{out_base}/cryptos/cryptos_' + + for o in cryptout: + slot_name = bpy.path.clean_name(o.name) # directly use name in multi layer exr + # slot_name = f'{slot_name}/{slot_name}_' + fo.file_slots.new(slot_name) + out_input = fo.inputs[-1] + links.new(o, out_input) + clear_disconnected(fo) + fo.update() + + \ No newline at end of file diff --git a/ui.py b/ui.py index 3d73acf..e5bc558 100644 --- a/ui.py +++ b/ui.py @@ -134,6 +134,7 @@ class GPEXP_PT_gp_node_ui(Panel): subcol.operator('gp.set_output_node_format', icon='OUTPUT', text='Copy Active Output Format') subcol.operator('gp.set_active_fileout_to_compout', icon='OUTPUT', text='Active Slot to Composite') + col.operator('gp.connect_selected_to_file_out', icon='OUTPUT', text='Connect Selection To Ouput') layout.separator()