Set composite output from fileout node

0.8.0

- feat: Select a file output node. Set active file slot path and settings to main Scene output.
    - Button in GP render panel with `Advanced` options active.
    - Or search operator label `Set Active File Output To Composite`
    - if Composite is already linked, pop-up ask if link should be replaced
main
Pullusb 2021-12-16 19:10:00 +01:00
parent f02ab79a06
commit 55f9248c6a
5 changed files with 133 additions and 2 deletions

View File

@ -14,6 +14,12 @@ Activate / deactivate layer opaticty according to prefix
Activate / deactivate all masks using MA layers Activate / deactivate all masks using MA layers
--> -->
0.8.0
- feat: Select a file output node. Set active file slot path and settings to main Scene output.
- Button in GP render panel with `Advanced` options active.
- Or search operator label `Set Active File Output To Composite`
- if Composite is already linked, pop-up ask if link should be replaced
0.7.0 0.7.0

View File

@ -135,9 +135,95 @@ class GPEXP_OT_delete_render_layer(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class GPEXP_OT_set_active_fileout_to_compout(bpy.types.Operator):
bl_idname = "gp.set_active_fileout_to_compout"
bl_label = "Set Active File Output To Composite"
bl_description = "Use active slot of active file output node to set scene output settings (swap connection)"
bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return context.scene.use_nodes\
and context.scene.node_tree\
and context.scene.node_tree.nodes.active\
and context.scene.node_tree.nodes.active.type == 'OUTPUT_FILE'
relink_composite : bpy.props.BoolProperty(
name='Relink Composite',
default=True,
description='In case file slot is linked, swap link to Composite file',
options={'SKIP_SAVE'},
)
def invoke(self, context, event):
self.fo = context.scene.node_tree.nodes.active
if not len(self.fo.file_slots):
self.report({'ERROR'}, 'no slots in active file output')
return {'CANCELLED'}
# check if active slot has a source
if not self.fo.inputs[self.fo.active_input_index].is_linked:
return self.execute(context)
# check if composite linked
out = context.scene.node_tree.nodes.get('Composite')
if not out or not out.inputs[0].is_linked:
self.compo_out_from_link = ''
return self.execute(context)
# compo linked, pop panel to choose replace or not
self.compo_out_from_link = out.inputs[0].links[0].from_node.name
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text=f'Composite node connected to: {self.compo_out_from_link}')
col.label(text=f'Would you like to replace by file output slot source ?')
layout.prop(self, 'relink_composite')
def execute(self, context):
# if comp
fn.set_scene_output_from_active_fileout_item()
idx = self.fo.active_input_index
sl = self.fo.file_slots[idx]
sk = self.fo.inputs[idx]
if not sk.is_linked:
self.report({'INFO'}, f'Outut changed to match {sl.path} (slot was not linked)')
return {'FINISHED'}
## If linked replace links to Composite node
if not self.relink_composite:
return {'FINISHED'}
ntree = context.scene.node_tree
links = context.scene.node_tree.links
nodes = context.scene.node_tree.nodes
out = nodes.get('Composite')
if not out:
out = fn.create_node('COMPOSITE', tree=ntree)
fo_loc = fn.real_loc(self.fo)
out.location = (fo_loc.x, fo_loc.y + 160)
# if out.inputs[0].is_linked:
# self.report({'WARNING'}, f'Outut changed to match {sl.path} (Composite node already linked)')
lnk = sk.links[0]
from_sk = sk.links[0].from_socket
links.remove(lnk)
links.new(from_sk, out.inputs[0])
return {"FINISHED"}
classes=( classes=(
GPEXP_OT_reconnect_render_layer, GPEXP_OT_reconnect_render_layer,
GPEXP_OT_delete_render_layer, GPEXP_OT_delete_render_layer,
GPEXP_OT_set_active_fileout_to_compout,
) )
def register(): def register():

View File

@ -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, 7, 0), "version": (0, 8, 0),
"blender": (2, 93, 0), "blender": (2, 93, 0),
"location": "View3D", "location": "View3D",
"warning": "", "warning": "",

38
fn.py
View File

@ -1,5 +1,6 @@
from typing import Coroutine from typing import Coroutine
import bpy import bpy
import os
import re import re
from mathutils import Vector from mathutils import Vector
from pathlib import Path from pathlib import Path
@ -1199,3 +1200,40 @@ def clear_frame_out_of_range_all_object():
ct += nct ct += nct
print(f'{ct} gp frames deleted') print(f'{ct} gp frames deleted')
return ct return ct
def set_scene_output_from_active_fileout_item():
scn = bpy.context.scene
rd = scn.render
ntree =scn.node_tree
fo = ntree.nodes.active
if fo.type != 'OUTPUT_FILE':
return
sl = fo.file_slots[fo.active_input_index]
full_path = os.path.join(fo.base_path, sl.path)
rd.filepath = full_path
fmt = fo.format if sl.use_node_format else sl.format
## set those attr first to avoid error settings other attributes in next loop
rd.image_settings.file_format = fmt.file_format
rd.image_settings.color_mode = fmt.color_mode
rd.image_settings.color_depth = fmt.color_depth if fmt.color_depth else 8 # Force set since Sometimes it's weirdly set to "" (not in enum choice)
excluded = ['file_format', 'color_mode', 'color_depth',
'view_settings', 'views_format']
''' ## all attrs
# 'cineon_black', 'cineon_gamma', 'cineon_white',
# 'color_depth', 'color_mode', 'compression', 'display_settings',
# 'exr_codec', 'file_format', 'jpeg2k_codec', 'quality',
# 'rna_type', 'stereo_3d_format', 'tiff_codec', 'use_cineon_log',
# 'use_jpeg2k_cinema_48', 'use_jpeg2k_cinema_preset', 'use_jpeg2k_ycc',
# 'use_preview', 'use_zbuffer']
'''
for attr in dir(fmt):
if attr.startswith('__') or attr.startswith('bl_') or attr in excluded:
continue
if hasattr(scn.render.image_settings, attr) and not scn.render.image_settings.is_property_readonly(attr):
setattr(scn.render.image_settings, attr, getattr(fmt, attr))

3
ui.py
View File

@ -120,8 +120,9 @@ class GPEXP_PT_gp_node_ui(Panel):
if advanced: if advanced:
subcol.operator('gp.set_output_node_format', icon='OUTPUT', text='Copy Active Output Format') 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')
layout.separator() layout.separator()
col=layout.column() col=layout.column()