160 lines
4.3 KiB
Python
160 lines
4.3 KiB
Python
|
info = {
|
||
|
'icon': 'TRIA_DOWN_BAR',
|
||
|
'description': 'Merge layers',
|
||
|
}
|
||
|
|
||
|
import fnmatch
|
||
|
import glob
|
||
|
import os
|
||
|
import re
|
||
|
from math import degrees, radians
|
||
|
from os import listdir
|
||
|
from os.path import basename, dirname, exists, isdir, isfile, join, splitext
|
||
|
from pathlib import Path
|
||
|
import bpy
|
||
|
C = bpy.context
|
||
|
D = bpy.data
|
||
|
|
||
|
|
||
|
def random_color(alpha=False):
|
||
|
import random
|
||
|
if alpha:
|
||
|
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1), 1)
|
||
|
return (random.uniform(0,1), random.uniform(0,1), random.uniform(0,1))
|
||
|
|
||
|
def create_node(type, tree=None, **kargs):
|
||
|
tree = tree or bpy.context.scene.node_tree
|
||
|
|
||
|
node = tree.nodes.new(type)
|
||
|
for k,v in kargs.items():
|
||
|
setattr(node, k, v)
|
||
|
|
||
|
return node
|
||
|
|
||
|
def new_aa_node(tree):
|
||
|
'''create AA node'''
|
||
|
aa = create_node('CompositorNodeAntiAliasing', tree) # type = ANTIALIASING
|
||
|
aa.threshold = 0.5
|
||
|
aa.contrast_limit = 0.5
|
||
|
aa.corner_rounding = 0.25
|
||
|
aa.hide = True
|
||
|
return aa
|
||
|
|
||
|
def get_render_scene():
|
||
|
render = bpy.data.scenes.get('Render')
|
||
|
if not render:
|
||
|
render = bpy.data.scenes.new('Render')
|
||
|
render.use_nodes = True
|
||
|
return render
|
||
|
|
||
|
|
||
|
def merge_layers(rlayers, obname=None):
|
||
|
print(f'Merging {len(rlayers)} layers')
|
||
|
print('->', [r.layer for r in rlayers])
|
||
|
print()
|
||
|
|
||
|
if not rlayers:
|
||
|
return ('ERROR', 'No render layer sent to merge')
|
||
|
|
||
|
ng = rlayers[0].outputs[0].links[0].to_node
|
||
|
rlayers.sort(key=lambda x: x.location.y, reverse=True)
|
||
|
|
||
|
# change colors of those nodes
|
||
|
color = random_color()
|
||
|
for n in rlayers:
|
||
|
n.use_custom_color = True
|
||
|
n.color = color
|
||
|
|
||
|
|
||
|
# get inside socket (group input) from outside socket list (should be already ordered)
|
||
|
|
||
|
## by name
|
||
|
# for i, inp in enumerate(ng.node_tree.inputs):
|
||
|
# if inp.name ==
|
||
|
|
||
|
# by connection order
|
||
|
|
||
|
socket_list = []
|
||
|
grp_sockets = []
|
||
|
|
||
|
for n in rlayers:
|
||
|
if n.outputs[0].links[0].to_node != ng:
|
||
|
print(f'Skip {n.layer}, connect to {n.outputs[0].links[0].to_node} instead of {ng.name}')
|
||
|
continue
|
||
|
|
||
|
sock_in = n.outputs[0].links[0].to_socket
|
||
|
for i, s in enumerate(ng.inputs):
|
||
|
if s == sock_in:
|
||
|
print(i, s.name)
|
||
|
socket_list.append(s)
|
||
|
grp_sockets.append(ng.node_tree.nodes['Group Input'].outputs[i])
|
||
|
break
|
||
|
|
||
|
# debug
|
||
|
for inp, grps in zip(socket_list, grp_sockets):
|
||
|
if inp.name != grps.name:
|
||
|
print(f'\n! Problem ! : {inp.name}, {grps.name}')
|
||
|
return
|
||
|
|
||
|
##
|
||
|
# JUST CREATE ANOTHER GROUP NODE FOR THE MERGE !
|
||
|
##
|
||
|
|
||
|
|
||
|
def merge_selected_layers():
|
||
|
'''Merge command from selected GP layers'''
|
||
|
ob = bpy.context.object
|
||
|
layer_names = [l.info for l in ob.data.layers if l.select and not l.hide]
|
||
|
print("layer_names", layer_names)#Dbg
|
||
|
|
||
|
if len(layer_names) < 2:
|
||
|
print(f'Should select multiple layers for merging')
|
||
|
return
|
||
|
|
||
|
render = bpy.data.scenes.get('Render')
|
||
|
if render:
|
||
|
nodes = render.node_tree.nodes
|
||
|
|
||
|
clean_ob_name = bpy.path.clean_name(ob.name)
|
||
|
rlayers = []
|
||
|
for l in layer_names:
|
||
|
## identifier is clean_name(ob.name).layer_name
|
||
|
|
||
|
idname = f'{clean_ob_name}.{l}'
|
||
|
|
||
|
# check the render layer that have a parent frame
|
||
|
rlayer = [n for n in nodes if n.type == 'R_LAYERS' and n.layer == idname and n.parent]
|
||
|
if not rlayer:
|
||
|
# send to function to generate the rlayer and connect
|
||
|
# rlayer = creation
|
||
|
continue
|
||
|
|
||
|
rlayers.append(rlayer)
|
||
|
|
||
|
merge_layers(rlayers, obname=clean_ob_name)
|
||
|
|
||
|
|
||
|
def merge_selected_render_layers():
|
||
|
'''Merge command from selected render layers nodes'''
|
||
|
render = bpy.data.scenes.get('Render')
|
||
|
if not render:
|
||
|
print('No render scene')
|
||
|
return
|
||
|
|
||
|
nodes = render.node_tree.nodes
|
||
|
selection = [n for n in nodes if n.select and n.type == 'R_LAYERS']
|
||
|
|
||
|
# should be from the same object:
|
||
|
assert all(selection[0].layer.split('.')[0] == n.layer.split('.')[0] for n in selection), 'Not every nodes start with the same object'
|
||
|
|
||
|
# obname = selection[0].layer.split('.')[0]
|
||
|
merge_layers(selection)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
# merge_selected_layers() # function to merge from GP dopesheet
|
||
|
|
||
|
merge_selected_render_layers() # function to merge from nodegroup
|
||
|
|