From 16a4014da9a0264bd44177d4592a45d0124b7ffe Mon Sep 17 00:00:00 2001 From: pullusb Date: Wed, 17 Apr 2024 14:37:44 +0200 Subject: [PATCH] Fix file output base path 1.7.1 - fix: file output base path depending on file format - fix: problem when connecting render layers --- CHANGELOG.md | 5 +++++ README.md | 4 ++++ __init__.py | 2 +- fn.py | 37 ++++++++++++++++++++++++------------- gen_vlayer.py | 40 +++++++++++++++++++++++++--------------- 5 files changed, 59 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55a6458..12334e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ Activate / deactivate layer opacity according to prefix Activate / deactivate all masks using MA layers --> +1.7.1 + +- fix: file output base path depending on file format +- fix: problem when connecting render layers + 1.7.0 - fix: problem when removing render layers diff --git a/README.md b/README.md index 3720583..1b46b78 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ # GP Render Organise export of gp layers through compositor output + +### Environment variables + +`FILE_FORMAT` : Define file_format used for output. If not specified, use `OPEN_EXR_MULTILAYER` (set `OPEN_EXR` for separate sequences) \ No newline at end of file diff --git a/__init__.py b/__init__.py index 01504bf..fd5c622 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, 7, 0), + "version": (1, 7, 1), "blender": (3, 0, 0), "location": "View3D", "warning": "", diff --git a/fn.py b/fn.py index 21b4abe..84c2602 100644 --- a/fn.py +++ b/fn.py @@ -1906,18 +1906,20 @@ def connect_to_file_output(node_list, file_out=None): fo.name = out_name if node.parent: fo.parent = node.parent - fo.base_path = f'//render/{out_base}' + + if fo.format.file_format == 'OPEN_EXR_MULTILAYER': + fo.base_path = f'//render/{out_base}/{out_base}_' + else: + fo.base_path = f'//render/{out_base}' for o in outs: - # if o.name == 'Deprecated': - # continue - - ## Skip if already connected to current FO - # if next((l for l in o.links if l.to_node == fo), None): if next((l for l in o.links if recursive_node_connect_check(l, fo)), None): continue slot_name = bpy.path.clean_name(o.name) - slot_name = f'{slot_name}/{slot_name}_' + if fo.format.file_format == 'OPEN_EXR_MULTILAYER': + slot_name = slot_name + else: + slot_name = f'{slot_name}/{slot_name}_' fo.file_slots.new(slot_name) out_input = fo.inputs[-1] links.new(o, out_input) @@ -1933,15 +1935,18 @@ def connect_to_file_output(node_list, file_out=None): 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' + set_file_output_format(fo) # OPEN_EXR_MULTILAYER, RGBA, ZIP 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_' + + if fo.format.file_format == 'OPEN_EXR_MULTILAYER': + ## FIXME: find a better organization for separated crypto pass + fo.base_path = f'//render/{out_base}/cryptos/cryptos_' + else: + fo.base_path = f'//render/{out_base}' + # fo.base_path = f'//render/{out_base}/cryptos' for o in cryptout: ## Skip already connected @@ -1949,8 +1954,14 @@ def connect_to_file_output(node_list, file_out=None): # if next((l for l in o.links if l.to_node == fo), None): if next((l for l in o.links if recursive_node_connect_check(l, fo)), None): continue + slot_name = bpy.path.clean_name(o.name) # directly use name in multi layer exr - # slot_name = f'{slot_name}/{slot_name}_' + + if fo.format.file_format == 'OPEN_EXR_MULTILAYER': + slot_name = slot_name + else: + slot_name = f'{slot_name}/{slot_name}_' + fo.file_slots.new(slot_name) out_input = fo.inputs[-1] links.new(o, out_input) diff --git a/gen_vlayer.py b/gen_vlayer.py index e2842ef..a6b2e23 100644 --- a/gen_vlayer.py +++ b/gen_vlayer.py @@ -103,18 +103,19 @@ def connect_render_layer(rlayer, ng=None, out=None, frame=None): ng.node_tree = ngroup ng.name = ngroup.name - ng_in = fn.create_node('NodeGroupInput', tree=ngroup, location=(-600,0)) - ng_out = fn.create_node('NodeGroupOutput', tree=ngroup, location=(600,0)) - else: ngroup = ng.node_tree - ng_in = ngroup.nodes.get('Group Input') - ng_out = ngroup.nodes.get('Group Output') + + if not (ng_in := ngroup.nodes.get('Group Input')): + ng_in = fn.create_node('NodeGroupInput', tree=ngroup, location=(-600,0)) + + if not (ng_out := ngroup.nodes.get('Group Output')): + ng_out = fn.create_node('NodeGroupOutput', tree=ngroup, location=(600,0)) # Connect rlayer to nodegroup if not rlayer.outputs['Image'].is_linked: sockin = ng.inputs.get(vl_name) - if not sockin: + if not sockin: if bpy.app.version < (4,0,0): sockin = ng.node_tree.inputs.new('NodeSocketColor', vl_name) else: @@ -127,14 +128,19 @@ def connect_render_layer(rlayer, ng=None, out=None, frame=None): # rl_nodes = [n for n in nodes if n.type == 'R_LAYERS' and n.layer != 'View Layer' and n.parent == frame] # auto clean : if an input exists but is not linked and name not exists in rlayers of current frame - for s in reversed(ng.inputs): - if not s.is_linked: # and not any(x.layer == s.name for x in rl_nodes) - print(f'removing grp unlinked input {s.name}') - # ng.inputs.remove(s) - if bpy.app.version < (4,0,0): - ng.node_tree.inputs.remove(s) - else: - ng.node_tree.interface.items_tree.remove(s) + + if bpy.app.version < (4,0,0): + for s in reversed(ng.inputs): + if not s.is_linked: # and not any(x.layer == s.name for x in rl_nodes) + print(f'Removing unlinked input {s.name}') + ng.inputs.remove(s) + else: + g_inputs = [s for s in ngroup.interface.items_tree if s.in_out == 'INPUT'] + # g_outputs = [s for s in ngroup.interface.items_tree if s.in_out == 'OUTPUT'] + for i in range(len(ng.inputs))[::-1]: + if not ng.inputs[i].is_linked: + print(f'Removing unlinked input {ng.inputs[i].name}') + ngroup.interface.remove(g_inputs[i]) ## get nodes from linked NG inputs ??? maybe more clear... # rl_nodes = [s.links[0].from_node for s in ng.inputs if s.links and s.links[0].from_node and s.links[0].from_node.type == 'R_LAYERS'] @@ -228,7 +234,11 @@ def connect_render_layer(rlayer, ng=None, out=None, frame=None): fn.set_file_output_format(out) out.name = out_name out.parent = frame - out.base_path = f'//render/{bpy.path.clean_name(obname)}' + out_base = {bpy.path.clean_name(obname)} + if out.format.file_format == 'OPEN_EXR_MULTILAYER': + out.base_path = f'//render/{out_base}/{out_base}_' + else: + out.base_path = f'//render/{out_base}' ## out_input = out.inputs.get(slot_name) # ok for non-numbered outputs