-
-
Save BigRoy/653379bd3b0b1c2f6d85d50d05addf29 to your computer and use it in GitHub Desktop.
# Fix Maya bug where you cannot duplicate a renderlayer correctly bug | |
# This is with Legacy Renderlayers, not Render Setup. | |
# Bug has been found in both Maya 2018 + 2019 | |
import maya.cmds as mc | |
# Recreate all renderlayer overrides (.adjustments) | |
for layer in mc.ls(type="renderLayer"): | |
attr = layer + ".adjustments" | |
indices = mc.getAttr(attr, multiIndices=True) or [] | |
connections = [] | |
for index in indices: | |
# Collect current connection | |
index_attr = "{plug}[{index}]".format(plug=attr, index=index) | |
src = cmds.listConnections(index_attr + ".plug", | |
source=True, | |
plugs=True)[0] | |
value = cmds.getAttr(index_attr + ".value") | |
connections.append((src, value)) | |
# Remove the entry and break any connections | |
mc.removeMultiInstance(index_attr, b=True) | |
# Recreate the overrides | |
for i, (src, value) in enumerate(connections): | |
cmds.connectAttr(src, layer + ".adjustments[{0}].plug".format(i)) |
Also had this Fix script that helped to connect and show the missing layers. However this still fails to set the right identification numbers for all layers, as sometimes Maya just did not allow to apply a specific identification number.
# Fix maya duplicated renderlayer not showing up in Render Layer editor
from colorbleed.lib import pairwise
from maya import cmds
from maya import mel
import re
from collections import defaultdict
layers = cmds.ls(type="renderLayer")
for layer in layers:
# Check for missing connection for renderLayer.renderInfo.identification
id_input = cmds.listConnections(layer + ".identification",
source=True,
destination=False) or []
if not id_input:
# Connect it to the render layer manager to show up
# in the render layer editor as that defines "all
# layers" by those connected to the renderlayer
# manager node.
layer_manager = cmds.ls(type="renderLayerManager")[0]
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
sources = [src for src, dest in pairwise(connections)]
indices = []
for source in sources:
match = re.match(r".*\[([0-9]+)\]$", source)
index = int(match.group(1)) + 1
indices.append(index)
indices.sort()
next_index = indices[-1] if indices else 0
src = "{0}.renderLayerId[{1}]".format(layer_manager, next_index)
dest = "{0}.identification".format(layer)
print("Fixing missing renderLayerId connection for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, force=True)
# Check for missing connection to defaultRenderingList
# (not sure if required)
outputs = cmds.listConnections(layer + ".message",
source=False,
destination=True)
outputs = cmds.ls(outputs, type="defaultRenderingList")
if not outputs:
src = layer + ".message"
dest = "defaultRenderingList1.rendering"
print("Fixing missing connection to defaultRenderingList for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, nextAvailable=True)
# Remove all non-connected renderlayer manager entries
layer_manager = cmds.ls(type="renderLayerManager")[0]
id_plug = layer_manager + ".renderLayerId"
for index in reversed(cmds.getAttr(id_plug, multiIndices=True)):
id_plug_index = "{0}[{1}]".format(id_plug, index)
if not cmds.listConnections(id_plug_index,
destination=True,
source=False):
print("Removing non-connected index %s" % id_plug_index)
cmds.removeMultiInstance(id_plug_index)
# Fix all numberings for renderlayer manager entries
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
for src, dest in pairwise(connections):
index = int(re.match(r".*\[([0-9]+)\]$", src).group(1))
if cmds.getAttr(src) != index:
cmds.setAttr(src, index)
# Force renderlayer editor refresh
mel.eval('updateEditorRenderLayer "RenderLayerTab"')
Hey Big Roy. Man I am so excited to see someone tackle this bug.
Tried the last script and get this error:
Error: ImportError: file line 2: No module named colorbleed.lib
Think the colorbleed.lib file is something local to your setup? I guess its part of this https://github.com/Colorbleed/colorbleed-config but no idea how to set this up.
Running legacy render layers in maya 2018
@RocketeerVFX Here's the script without those dependencies:
# Fix maya duplicated renderlayer not showing up in Render Layer editor
from maya import cmds
from maya import mel
import re
import itertools
from collections import defaultdict
def pairwise(iterable):
"""s -> (s0,s1), (s2,s3), (s4, s5), ..."""
a = iter(iterable)
return itertools.izip(a, a)
layers = cmds.ls(type="renderLayer")
for layer in layers:
# Check for missing connection for renderLayer.renderInfo.identification
id_input = cmds.listConnections(layer + ".identification",
source=True,
destination=False) or []
if not id_input:
# Connect it to the render layer manager to show up
# in the render layer editor as that defines "all
# layers" by those connected to the renderlayer
# manager node.
layer_manager = cmds.ls(type="renderLayerManager")[0]
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
sources = [src for src, dest in pairwise(connections)]
indices = []
for source in sources:
match = re.match(r".*\[([0-9]+)\]$", source)
index = int(match.group(1)) + 1
indices.append(index)
indices.sort()
next_index = indices[-1] if indices else 0
src = "{0}.renderLayerId[{1}]".format(layer_manager, next_index)
dest = "{0}.identification".format(layer)
print("Fixing missing renderLayerId connection for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, force=True)
# Check for missing connection to defaultRenderingList
# (not sure if required)
outputs = cmds.listConnections(layer + ".message",
source=False,
destination=True)
outputs = cmds.ls(outputs, type="defaultRenderingList")
if not outputs:
src = layer + ".message"
dest = "defaultRenderingList1.rendering"
print("Fixing missing connection to defaultRenderingList for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, nextAvailable=True)
# Remove all non-connected renderlayer manager entries
layer_manager = cmds.ls(type="renderLayerManager")[0]
id_plug = layer_manager + ".renderLayerId"
for index in reversed(cmds.getAttr(id_plug, multiIndices=True)):
id_plug_index = "{0}[{1}]".format(id_plug, index)
if not cmds.listConnections(id_plug_index,
destination=True,
source=False):
print("Removing non-connected index %s" % id_plug_index)
cmds.removeMultiInstance(id_plug_index)
# Fix all numberings for renderlayer manager entries
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
for src, dest in pairwise(connections):
index = int(re.match(r".*\[([0-9]+)\]$", src).group(1))
if cmds.getAttr(src) != index:
cmds.setAttr(src, index)
# Force renderlayer editor refresh
mel.eval('updateEditorRenderLayer "RenderLayerTab"')
Let me know if that works for you. Unfortunately this hasn't worked for me in all cases - in particular I had a scene recently that kept bugging out. I'd be happy to get some more faulty scenes to investigate where they overlap so if you can share anything definitely pass it on and I'll see if I can reproduce it and potentially fix it if either of these scripts don't work for you.
Didn't work :/
Error: TypeError: file line 63: argument to reversed() must be a sequence
@RocketeerVFX That's interesting. As if the renderLayerManager.renderLayerId
has zero indices, odd.
Anyway, this would work around that particular error:
# Fix maya duplicated renderlayer not showing up in Render Layer editor
from maya import cmds
from maya import mel
import re
import itertools
from collections import defaultdict
def pairwise(iterable):
"""s -> (s0,s1), (s2,s3), (s4, s5), ..."""
a = iter(iterable)
return itertools.izip(a, a)
layers = cmds.ls(type="renderLayer")
for layer in layers:
# Check for missing connection for renderLayer.renderInfo.identification
id_input = cmds.listConnections(layer + ".identification",
source=True,
destination=False) or []
if not id_input:
# Connect it to the render layer manager to show up
# in the render layer editor as that defines "all
# layers" by those connected to the renderlayer
# manager node.
layer_manager = cmds.ls(type="renderLayerManager")[0]
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
sources = [src for src, dest in pairwise(connections)]
indices = []
for source in sources:
match = re.match(r".*\[([0-9]+)\]$", source)
index = int(match.group(1)) + 1
indices.append(index)
indices.sort()
next_index = indices[-1] if indices else 0
src = "{0}.renderLayerId[{1}]".format(layer_manager, next_index)
dest = "{0}.identification".format(layer)
print("Fixing missing renderLayerId connection for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, force=True)
# Check for missing connection to defaultRenderingList
# (not sure if required)
outputs = cmds.listConnections(layer + ".message",
source=False,
destination=True)
outputs = cmds.ls(outputs, type="defaultRenderingList")
if not outputs:
src = layer + ".message"
dest = "defaultRenderingList1.rendering"
print("Fixing missing connection to defaultRenderingList for: %s" % layer)
print("\t{0} -> {1}".format(src, dest))
cmds.connectAttr(src, dest, nextAvailable=True)
# Remove all non-connected renderlayer manager entries
layer_manager = cmds.ls(type="renderLayerManager")[0]
id_plug = layer_manager + ".renderLayerId"
indices = cmds.getAttr(id_plug, multiIndices=True) or []
for index in reversed(indices):
id_plug_index = "{0}[{1}]".format(id_plug, index)
if not cmds.listConnections(id_plug_index,
destination=True,
source=False):
print("Removing non-connected index %s" % id_plug_index)
cmds.removeMultiInstance(id_plug_index)
# Fix all numberings for renderlayer manager entries
connections = cmds.listConnections(layer_manager + ".renderLayerId",
connections=True,
plugs=True) or []
for src, dest in pairwise(connections):
index = int(re.match(r".*\[([0-9]+)\]$", src).group(1))
if cmds.getAttr(src) != index:
cmds.setAttr(src, index)
# Force renderlayer editor refresh
mel.eval('updateEditorRenderLayer "RenderLayerTab"')
But not sure if it would actually end up perofrming what you'd need to fix the scene. You are using legacy renderlayers, right?
Anyway, if you have a simple reproducible scene I'd be happy to investigate and take a look.
Thanks I'll try that :)
Yeah its legacy renderlayers.
I wish I could share it, but its all on pipe with ftrack dependencies. Which is partly what I'm thinking is causing the issues anyways. Some reference or similar.
It ran this time but sadly no joy. :/
Force renderlayer editor refresh
mel.eval('updateEditorRenderLayer "RenderLayerTab"')
Fixing missing renderLayerId connection for: BTY_ASIA1
prop_bridge:renderLayerManager.renderLayerId[2] -> BTY_ASIA1.identification
Fixing missing connection to defaultRenderingList for: BTY_ASIA1
BTY_ASIA1.message -> defaultRenderingList1.rendering
This is what Maya uses to display the renderlayers in the Layer Editor:
So the invalid layers can be found by finding those that are not connected to
renderLayerManager.renderLayerId