parent
df0231ac28
commit
9044134d79
|
@ -12,6 +12,12 @@ Activate / deactivate layer opaticty according to prefix
|
||||||
Activate / deactivate all masks using MA layers
|
Activate / deactivate all masks using MA layers
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
0.2.8
|
||||||
|
|
||||||
|
- fix: added AA nodegroup
|
||||||
|
- fix: added exclude viewlayer for unused layers
|
||||||
|
- fix: added preview as main output (else main composite output go anywhere !)
|
||||||
|
|
||||||
0.2.7
|
0.2.7
|
||||||
|
|
||||||
- feat: check layer states (check use light, opacity, blend mode) and correct if needed
|
- feat: check layer states (check use light, opacity, blend mode) and correct if needed
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import bpy
|
import bpy
|
||||||
from .import gen_vlayer
|
from . import gen_vlayer, fn
|
||||||
|
|
||||||
class GPEXP_OT_add_layer_to_render(bpy.types.Operator):
|
class GPEXP_OT_add_layer_to_render(bpy.types.Operator):
|
||||||
bl_idname = "gp.add_layer_to_render"
|
bl_idname = "gp.add_layer_to_render"
|
||||||
|
@ -22,29 +22,42 @@ class GPEXP_OT_add_layer_to_render(bpy.types.Operator):
|
||||||
|
|
||||||
ct = 0
|
ct = 0
|
||||||
# send scene ?
|
# send scene ?
|
||||||
|
hided = 0
|
||||||
for l in ob.data.layers:
|
for l in ob.data.layers:
|
||||||
if not l.select:
|
if not l.select:
|
||||||
|
if not l.viewlayer_render:
|
||||||
|
# TODO : need to link, can reaise error if object is not linked in Render scene yet
|
||||||
|
l.viewlayer_render == fn.get_view_layer('exclude')
|
||||||
continue
|
continue
|
||||||
gen_vlayer.get_set_viewlayer_from_gp(ob, l)
|
gen_vlayer.get_set_viewlayer_from_gp(ob, l)
|
||||||
ct += 1
|
|
||||||
if ct:
|
|
||||||
self.report({'INFO'}, f'{ct} layer(s) added to scene "Render"')
|
|
||||||
|
|
||||||
|
if l.hide:
|
||||||
|
hided += 1
|
||||||
|
ct += 1
|
||||||
|
|
||||||
|
if hided:
|
||||||
|
self.report({'WARNING'}, f'{hided}/{ct} layers are hided !')
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.report({'INFO'}, f'{ct} layer(s) added to scene "Render"')
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
def export_gp_objects(oblist, exclude_list=['MA', 'IN']):
|
def export_gp_objects(oblist, exclude_list=[]):
|
||||||
# Skip layer containing element in excluyde list
|
# Skip layer containing element in excluyde list
|
||||||
if not isinstance(oblist, list):
|
if not isinstance(oblist, list):
|
||||||
oblist = [oblist]
|
oblist = [oblist]
|
||||||
|
|
||||||
for ob in oblist:
|
for ob in oblist:
|
||||||
for l in ob.data.layers:
|
for l in ob.data.layers:
|
||||||
if any(x + '_' in l.info for x in exclude_list):
|
# if l.hide:
|
||||||
|
# continue
|
||||||
|
if l.hide or any(x + '_' in l.info for x in exclude_list): # exclude hided ?
|
||||||
|
l.viewlayer_render = fn.get_view_layer('exclude') # assign "exclude"
|
||||||
continue
|
continue
|
||||||
if l.hide:
|
|
||||||
continue
|
_vl, _cp = gen_vlayer.get_set_viewlayer_from_gp(ob, l) # scene=fn.get_render_scene())
|
||||||
vl, cp = gen_vlayer.get_set_viewlayer_from_gp(ob, l) # scene=fn.get_render_scene())
|
|
||||||
|
|
||||||
|
|
||||||
## send operator with mode ALL or SELECTED to batch build
|
## send operator with mode ALL or SELECTED to batch build
|
||||||
|
@ -61,15 +74,18 @@ class GPEXP_OT_add_objects_to_render(bpy.types.Operator):
|
||||||
mode : bpy.props.StringProperty(default='ALL', options={'SKIP_SAVE'})
|
mode : bpy.props.StringProperty(default='ALL', options={'SKIP_SAVE'})
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
# create render scene
|
||||||
|
fn.get_render_scene()
|
||||||
|
excludes = [] # ['MA', 'IN'] # Get list dynamically
|
||||||
if self.mode == 'SELECTED':
|
if self.mode == 'SELECTED':
|
||||||
export_gp_objects([o for o in context.selected_objects if o.type == 'GPENCIL'])
|
export_gp_objects([o for o in context.selected_objects if o.type == 'GPENCIL'], exclude_list=excludes) # excludes
|
||||||
|
|
||||||
elif self.mode == 'ALL':
|
elif self.mode == 'ALL':
|
||||||
scn = bpy.data.scenes.get('Scene')
|
scn = bpy.data.scenes.get('Scene')
|
||||||
if not scn:
|
if not scn:
|
||||||
self.report({'ERROR'}, 'Could not found default scene')
|
self.report({'ERROR'}, 'Could not found default scene')
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
export_gp_objects([o for o in scn.objects if o.type == 'GPENCIL' and not o.hide_get()])
|
export_gp_objects([o for o in scn.objects if o.type == 'GPENCIL' and not o.hide_get()], exclude_list=excludes) # excludes
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,9 @@
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
|
||||||
- fix frame problem
|
- set exlude VL on non-used layers
|
||||||
- bring cameras (and lights ?) from original scene
|
- set real AA nodegroup
|
||||||
|
|
||||||
|
- multi-merge : also merge merged NG automatically disabling AA without group (or externalise AA node ?)
|
||||||
|
- opt : How to disable main output
|
||||||
|
- disable all masks
|
|
@ -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, 2, 7),
|
"version": (0, 2, 8),
|
||||||
"blender": (2, 93, 0),
|
"blender": (2, 93, 0),
|
||||||
"location": "View3D",
|
"location": "View3D",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
|
64
fn.py
64
fn.py
|
@ -18,15 +18,49 @@ def create_node(type, tree=None, **kargs):
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def new_aa_node(tree):
|
def new_aa_node(tree, **kargs):
|
||||||
'''create AA node'''
|
'''create AA node'''
|
||||||
aa = create_node('CompositorNodeAntiAliasing', tree) # type = ANTIALIASING
|
aa = create_node('CompositorNodeAntiAliasing', tree) # type = ANTIALIASING
|
||||||
aa.threshold = 0.5 # 1.0
|
aa.threshold = 1.0 # 0.5
|
||||||
aa.contrast_limit = 0.5 # 0.25
|
aa.contrast_limit = 0.25 # 0.5
|
||||||
aa.corner_rounding = 0.25
|
aa.corner_rounding = 0.25
|
||||||
aa.hide = True
|
aa.hide = True
|
||||||
|
|
||||||
|
for k,v in kargs.items():
|
||||||
|
setattr(aa, k, v)
|
||||||
return aa
|
return aa
|
||||||
|
|
||||||
|
def create_aa_nodegroup(tree):
|
||||||
|
ngroup = bpy.data.node_groups.get('AA')
|
||||||
|
if not ngroup:
|
||||||
|
ngroup = bpy.data.node_groups.new('AA', 'CompositorNodeTree')
|
||||||
|
ng_in = create_node('NodeGroupInput', tree=ngroup, location=(-600,0))
|
||||||
|
ng_out = create_node('NodeGroupOutput', tree=ngroup, location=(600,0))
|
||||||
|
|
||||||
|
sep = create_node('CompositorNodeSepRGBA', tree=ngroup, location=(-300,0))
|
||||||
|
comb = create_node('CompositorNodeCombRGBA', tree=ngroup, location=(200,25))
|
||||||
|
ngroup.links.new(ng_in.outputs[0], sep.inputs[0])
|
||||||
|
for i in range(3):
|
||||||
|
ngroup.links.new(sep.outputs[i], comb.inputs[i])
|
||||||
|
|
||||||
|
# alpha AA
|
||||||
|
alpha_aa = new_aa_node(ngroup, location=(-50,-150))
|
||||||
|
ngroup.links.new(sep.outputs[3], alpha_aa.inputs[0])
|
||||||
|
ngroup.links.new(alpha_aa.outputs[0], comb.inputs[3])
|
||||||
|
|
||||||
|
# outpout AA (maybe externalize ?)
|
||||||
|
# ngroup.links.new(comb.outputs[0], ng_out.inputs[0]) # <- connect without out AA
|
||||||
|
aa = new_aa_node(ngroup, location=(380, 0))
|
||||||
|
ngroup.links.new(comb.outputs[0], aa.inputs[0])
|
||||||
|
ngroup.links.new(aa.outputs[0], ng_out.inputs[0])
|
||||||
|
|
||||||
|
|
||||||
|
ng = create_node('CompositorNodeGroup', tree=tree)
|
||||||
|
ng.node_tree = ngroup
|
||||||
|
ng.name = ngroup.name
|
||||||
|
ng.hide=True
|
||||||
|
return ng
|
||||||
|
|
||||||
|
|
||||||
def copy_settings(obj_a, obj_b):
|
def copy_settings(obj_a, obj_b):
|
||||||
exclusion = ['bl_rna', 'id_data', 'identifier','name_property','rna_type','properties', 'stamp_note_text','use_stamp_note',
|
exclusion = ['bl_rna', 'id_data', 'identifier','name_property','rna_type','properties', 'stamp_note_text','use_stamp_note',
|
||||||
|
@ -66,29 +100,27 @@ def set_settings(scene=None):
|
||||||
|
|
||||||
def get_render_scene():
|
def get_render_scene():
|
||||||
'''Get / Create a scene named Render'''
|
'''Get / Create a scene named Render'''
|
||||||
render = bpy.data.scenes.get('Render')
|
render_scn = bpy.data.scenes.get('Render')
|
||||||
if not render:
|
if not render_scn:
|
||||||
current = bpy.context.scene
|
current = bpy.context.scene
|
||||||
render = bpy.data.scenes.new('Render')
|
render_scn = bpy.data.scenes.new('Render')
|
||||||
## copy original settings over to new scene
|
## copy original settings over to new scene
|
||||||
# copy_settings(current, render) # BAD
|
# copy_settings(current, render_scn) # BAD
|
||||||
for attr in ['frame_start', 'frame_end', 'frame_current', 'camera', 'world']:
|
for attr in ['frame_start', 'frame_end', 'frame_current', 'camera', 'world']:
|
||||||
setattr(render, attr, getattr(current, attr))
|
setattr(render_scn, attr, getattr(current, attr))
|
||||||
copy_settings(current.render, render.render)
|
copy_settings(current.render, render_scn.render)
|
||||||
|
|
||||||
## link cameras (and lights ?)
|
## link cameras (and lights ?)
|
||||||
for ob in bpy.context.scene.objects:
|
for ob in bpy.context.scene.objects:
|
||||||
if ob.type in ('CAMERA', 'LIGHT'):
|
if ob.type in ('CAMERA', 'LIGHT'):
|
||||||
render.collection.objects.link(ob)
|
render_scn.collection.objects.link(ob)
|
||||||
|
|
||||||
# use same cam and world
|
render_scn.render.filepath = '//render/preview/preview_'
|
||||||
# render.camera = current.camera
|
|
||||||
# render.world = current.world
|
|
||||||
|
|
||||||
# set adapted render settings (no AA)
|
# set adapted render settings (no AA)
|
||||||
set_settings(render)
|
set_settings(render_scn)
|
||||||
render.use_nodes = True
|
render_scn.use_nodes = True
|
||||||
return render
|
return render_scn
|
||||||
|
|
||||||
def get_view_layer(name, scene=None):
|
def get_view_layer(name, scene=None):
|
||||||
'''get viewlayer name
|
'''get viewlayer name
|
||||||
|
|
|
@ -137,7 +137,7 @@ def connect_render_layer(rlayer, ng=None, out=None, frame=None):
|
||||||
|
|
||||||
if not connected:
|
if not connected:
|
||||||
# add AA and connect
|
# add AA and connect
|
||||||
aa = fn.new_aa_node(ngroup)
|
aa = fn.create_aa_nodegroup(ngroup)# fn.new_aa_node(ngroup)
|
||||||
groupout = ng.outputs.get(vl_name)
|
groupout = ng.outputs.get(vl_name)
|
||||||
if not groupout:
|
if not groupout:
|
||||||
ng.outputs.new('NodeSocketColor', vl_name) # assigning direcly doesn't link well
|
ng.outputs.new('NodeSocketColor', vl_name) # assigning direcly doesn't link well
|
||||||
|
@ -350,4 +350,4 @@ def get_set_viewlayer_from_gp(ob, l, scene=None):
|
||||||
# re-arrange all frames (since the offset probably overlapped)
|
# re-arrange all frames (since the offset probably overlapped)
|
||||||
fn.rearrange_frames(node_tree)
|
fn.rearrange_frames(node_tree)
|
||||||
|
|
||||||
return vl, cp
|
return vl, cp
|
||||||
|
|
Loading…
Reference in New Issue