Refactor to allow separate gp render scene and compositing scene

1.7.0

- fix: problem when removing render layers
- changed: node distribution refactor, allow separate compositing scene
  - Compositing scene (holding nodes) can be separated from render scene (holding GP objects and related viewlayers)
  - Default render named changed from `Render` to `RenderGP`
  - New properties in exposed Dopesheet N panel to manually set Render scene and Compo scene
  - Operator expose a `node_scene` parameter to separate where to send nodes
  - Switch scene button can have an extra button to go in compo scene if found
This commit is contained in:
pullusb
2024-04-16 18:01:10 +02:00
parent fb810c1256
commit c6c9c7f56c
18 changed files with 538 additions and 263 deletions
+46 -34
View File
@@ -2,9 +2,10 @@ import bpy
import re
from pathlib import Path
from . import gen_vlayer, fn
from bpy.props import (BoolProperty, StringProperty)
def batch_setup_render_scene(context=None, render_scn=None, preview=True):
def batch_setup_render_scene(context=None, render_scn=None, node_scene=None, preview=True):
'''A series of setup actions for Render scene:
- renumber fileout
- Clean compo Tree
@@ -15,10 +16,12 @@ def batch_setup_render_scene(context=None, render_scn=None, preview=True):
if context is None:
context = bpy.context
if render_scn is None:
render_scn = bpy.data.scenes.get('Render')
render_scn = fn.get_render_scene(create=False)
if not render_scn:
print('"Render" scene not found in batch_setup_render_scene')
print('Render scene not found in batch_setup_render_scene')
return
if node_scene is None:
node_scene = render_scn
## Renumber File outputs
print('Renumber File outputs')
@@ -49,8 +52,7 @@ def batch_setup_render_scene(context=None, render_scn=None, preview=True):
## Clean compo Tree
print('Clean compo Tree')
bpy.ops.gp.clean_compo_tree('EXEC_DEFAULT', use_render_scene=True)
# bpy.ops.gp.clean_compo_tree('INVOKE_DEFAULT', use_render_scene=True)
bpy.ops.gp.clean_compo_tree('EXEC_DEFAULT', scene=render_scn.name, node_scene=node_scene.name)
## Trigger check file before finishing ?
# bpy.ops.gp.check_render_scene('INVOKE_DEFAULT')
@@ -63,55 +65,57 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
bl_description = "Trigger all operation to make build render scene with default settings"
bl_options = {"REGISTER"}
# @classmethod
# def poll(cls, context):
# return context.object and context.object.type == 'GPENCIL'
scene : StringProperty(name="Target Scene Name",
description="Render scene to send GP to on a named scene, abort if not exists (not exposed)",
default='', options={'SKIP_SAVE'})
# timer : bpy.props.FloatProperty(default=0.1, options={'SKIP_SAVE'})
node_scene : StringProperty(name="Compositing Scene",
description="Name of the scene holding compositing nodes",
default='', options={'SKIP_SAVE'})
make_gp_single_user : bpy.props.BoolProperty(name='Set Single User Data', default=True,
make_gp_single_user : BoolProperty(name='Set Single User Data', default=True,
description='Set single user on all objects GP data')
excluded_prefix : bpy.props.StringProperty(
excluded_prefix : StringProperty(
name='Excluded Layer By Prefix', default='GP, RG, PO, MA',
description='Exclude layer to send to render by prefix (comma separated list)')
clean_name_and_visibility : bpy.props.BoolProperty(name='Clean Name And Visibility', default=True,
clean_name_and_visibility : BoolProperty(name='Clean Name And Visibility', default=True,
description='Add object name to layer name when there is only prefix (ex: "CO_")\
\nEnable visibility for layer with prefix included in Prefix Filter')
clean_material_duplication : bpy.props.BoolProperty(name='Clean Material Duplication', default=True,
clean_material_duplication : BoolProperty(name='Clean Material Duplication', default=True,
description='Clean material stack. i.e: Replace "mat.001" in material stack if "mat" exists and has same color')
prefix_filter : bpy.props.StringProperty(name='Prefix Filter', default='CO, CU, FX, TO', # , MA # exclude MA if mask are applied
prefix_filter : StringProperty(name='Prefix Filter', default='CO, CU, FX, TO', # , MA # exclude MA if mask are applied
description='Comma separated prefix to render. Set the other prefix and non-prefixed layer to exluded viewlayer')
set_layers_colors : bpy.props.BoolProperty(name='Set Layers Colors', default=True,
set_layers_colors : BoolProperty(name='Set Layers Colors', default=True,
description='Set colors for on layers according to prefix (hadrcoded color set)')
trigger_rename_lowercase : bpy.props.BoolProperty(name='Trigger Rename Lowercase', default=True,
trigger_rename_lowercase : BoolProperty(name='Trigger Rename Lowercase', default=True,
description='Rename all layer names lowercase')
trigger_renumber_by_distance : bpy.props.BoolProperty(name='Trigger Renumber By Distance', default=True,
trigger_renumber_by_distance : BoolProperty(name='Trigger Renumber By Distance', default=True,
description='Renumber object accordind to distance from camera and In-Front value')
export_layer_infos : bpy.props.BoolProperty(name='Export Layer Infos', default=True,
export_layer_infos : BoolProperty(name='Export Layer Infos', default=True,
description='Export layers infos to a Json file')
group_all_adjacent_layer_type : bpy.props.BoolProperty(name='Group All Adjacent Layer Type', default=False,
group_all_adjacent_layer_type : BoolProperty(name='Group All Adjacent Layer Type', default=False,
description='Fuse output Viewlayer according to adjacent Prefix in layer stack')
change_to_gp_workspace : bpy.props.BoolProperty(name='Change To Gp Workspace', default=True,
change_to_gp_workspace : BoolProperty(name='Change To Gp Workspace', default=True,
description='Switch to "GP Render" workspace shipped with addon')
batch_setup_render_scene : bpy.props.BoolProperty(name='Batch Setup Render Scene', default=True,
batch_setup_render_scene : BoolProperty(name='Batch Setup Render Scene', default=True,
description='- Renumber fileoutputs\
\n- Clean compo Tree\
\n- Go to camera view in visible viewports\
\n- Swap to bg cam'
)
add_preview : bpy.props.BoolProperty(name='Add Preview', default=True,
add_preview : BoolProperty(name='Add Preview', default=True,
description='Create preview with stacked alpha over on render layers')
def invoke(self, context, event):
@@ -153,10 +157,21 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
prefix_to_render = [p.strip() for p in self.prefix_filter.split(',')]
print('prefix_to_render: ', prefix_to_render)
render_scn = bpy.data.scenes.get('Render')
if render_scn:
self.report({'ERROR'}, 'A "Render" scene already exists')
return {'CANCELLED'}
render_scn = fn.get_render_scene(create=False)
if self.scene:
render_scn = bpy.data.scenes.get(self.scene)
if render_scn:
self.report({'ERROR'}, f'Abort, scene "{render_scn.name}" already exists')
return {'CANCELLED'}
if self.node_scene:
node_scene = fn.get_compo_scene(scene_name=self.node_scene, create=True) # create if not exists
## Set scene target in source scene
context.scene.gp_render_settings.node_scene = node_scene.name
else:
node_scene = fn.get_compo_scene(create=True)
if not node_scene:
node_scene = render_scn
all_gp_objects = [o for o in context.scene.objects if o.type == 'GPENCIL']
@@ -206,13 +221,11 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
if self.trigger_rename_lowercase:
print('Trigger rename lowercase')
bpy.ops.gp.lower_layers_name('EXEC_DEFAULT')
# bpy.ops.gp.lower_layers_name('INVOKE_DEFAULT')
## Trigger renumber by distance
if self.trigger_renumber_by_distance:
print('Trigger renumber by distance')
bpy.ops.gp.auto_number_object('EXEC_DEFAULT')
# bpy.ops.gp.auto_number_object('INVOKE_DEFAULT')
## Export layer infos ? (skip if json already exists)
if self.export_layer_infos:
@@ -226,13 +239,13 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
o.data = o.data.copy()
## Send all GP to render scene
print('Send all GP to render scene')
print('Send all GP to render scene (Create render scene if needed)')
# bpy.ops.gp.add_object_to_render(mode="ALL") # Ops to send all
gen_vlayer.export_gp_objects(ob_list, exclude_list=self.excluded_prefix) # Create render scene OTF
gen_vlayer.export_gp_objects(ob_list, exclude_list=self.excluded_prefix, scene=render_scn, node_scene=node_scene) # Create render scene OTF
## Switch to new Render Scene
print('Switch to new Render Scene')
render_scn = bpy.data.scenes.get('Render')
render_scn = fn.get_render_scene(create=False)
if not render_scn:
self.report({'ERROR'}, 'No render scene found')
return {'CANCELLED'}
@@ -268,13 +281,13 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
# context.scene.update_tag()
## Batch setup render scene
batch_setup_render_scene(render_scn=render_scn)
batch_setup_render_scene(render_scn=render_scn, node_scene=node_scene)
## create preview
if self.add_preview:
from .OP_merge_layers import merge_compositor_preview
merge_compositor_preview(scene=render_scn)
merge_compositor_preview(scene=node_scene)
## No need for timer anymore !
# if batch_setup_render_scene:
@@ -295,7 +308,6 @@ class GPEXP_OT_render_auto_build(bpy.types.Operator):
# bpy.ops.gp.check_render_scene('INVOKE_DEFAULT')
## Note: After all these operation, a ctrl+Z might crash
print('\nDone.\n')
return {"FINISHED"}