Allow conversion from legacy renderlayer singleton instances

This commit is contained in:
Roy Nieterau 2023-05-30 20:08:54 +02:00
parent 2045344b7e
commit dfaad2d1df
2 changed files with 116 additions and 22 deletions

View file

@ -333,11 +333,7 @@ class RenderlayerCreator(NewCreator, MayaCreatorBase):
# A Renderlayer is never explicitly created using the create method.
# Instead, renderlayers from the scene are collected. Thus "create"
# would only ever be called to say, 'hey, please refresh collect'
# Only allow a single render instance to exist
if self._get_singleton_node():
raise CreatorError("A Render instance already exists - only "
"one can be configured.")
self.create_singleton_node()
# if no render layers are present, create default one with
# asterisk selector
@ -347,16 +343,23 @@ class RenderlayerCreator(NewCreator, MayaCreatorBase):
collection = render_layer.createCollection("defaultCollection")
collection.getSelector().setPattern('*')
# By RenderLayerCreator.create we make it so that the renderlayer
# instances directly appear even though it just collects scene
# renderlayers. This doesn't actually 'create' any scene contents.
self.collect_instances()
def create_singleton_node(self):
if self._get_singleton_node():
raise CreatorError("A Render instance already exists - only "
"one can be configured.")
with lib.undo_chunk():
node = cmds.sets(empty=True, name=self.singleton_node_name)
lib.imprint(node, data={
"pre_creator_identifier": self.identifier
})
# By RenderLayerCreator.create we make it so that the renderlayer
# instances directly appear even though it just collects scene
# renderlayers. This doesn't actually 'create' any scene contents.
self.collect_instances()
return node
def collect_instances(self):
@ -449,11 +452,6 @@ class RenderlayerCreator(NewCreator, MayaCreatorBase):
layer = instance.transient_data["layer"]
instance_node = self._create_layer_instance_node(layer)
instance.data["instance_node"] = instance_node
else:
# TODO: Keep name in sync with the actual renderlayer?
self.log.warning("No instance node found for to be updated "
"instance: {}".format(instance))
continue
self.imprint_instance_node(instance_node,
data=instance.data_to_store())

View file

@ -1,5 +1,9 @@
from openpype.pipeline.create.creator_plugins import SubsetConvertorPlugin
from openpype.hosts.maya.api import plugin
from openpype.hosts.maya.api.lib import read
from maya import cmds
from maya.app.renderSetup.model import renderSetup
class MayaLegacyConvertor(SubsetConvertorPlugin,
@ -18,6 +22,12 @@ class MayaLegacyConvertor(SubsetConvertorPlugin,
"""
identifier = "io.openpype.creators.maya.legacy"
# Cases where the identifier or new family doesn't correspond to the
# original family on the legacy instances
special_family_conversions = {
"rendering": "io.openpype.creators.maya.renderlayer",
}
def find_instances(self):
self.cache_subsets(self.collection_shared_data)
@ -53,17 +63,103 @@ class MayaLegacyConvertor(SubsetConvertorPlugin,
"{}".format(identifier))
family_to_id[family] = identifier
family_to_id.update(self.special_family_conversions)
# We also embed the current 'task' into the instance since legacy
# instances didn't store that data on the instances. The old style
# logic was thus to be live to the current task to begin with.
data = dict()
data["task"] = self.create_context.get_current_task_name()
for family, instance_nodes in legacy.items():
if family in family_to_id:
# We only imprint the creator identifier for it to identify
# as the new style creator
creator_id = family_to_id[family]
data["creator_identifier"] = creator_id
for instance_node in instance_nodes:
self.imprint_instance_node(instance_node,
data=data.copy())
if family not in family_to_id:
self.log.warning(
"Unable to convert legacy instance with family '{}'"
" because there is no matching new creator's family"
"".format(family)
)
continue
creator_id = family_to_id[family]
creator = self.create_context.manual_creators[creator_id]
data["creator_identifier"] = creator_id
if isinstance(creator, plugin.RenderlayerCreator):
self._convert_per_renderlayer(instance_nodes, data, creator)
else:
self._convert_regular(instance_nodes, data)
def _convert_regular(self, instance_nodes, data):
# We only imprint the creator identifier for it to identify
# as the new style creator
for instance_node in instance_nodes:
self.imprint_instance_node(instance_node,
data=data.copy())
def _convert_per_renderlayer(self, instance_nodes, data, creator):
# Split the instance into an instance per layer
rs = renderSetup.instance()
layers = rs.getRenderLayers()
if not layers:
self.log.error(
"Can't convert legacy renderlayer instance because no existing"
" renderSetup layers exist in the scene."
)
return
creator_attribute_names = {
attr_def.key for attr_def in creator.get_instance_attr_defs()
}
for instance_node in instance_nodes:
# Ensure we have the new style singleton node generated
# TODO: Make function public
singleton_node = creator._get_singleton_node()
if singleton_node:
self.log.error(
"Can't convert legacy renderlayer instance '{}' because"
" new style instance '{}' already exists".format(
instance_node,
singleton_node
)
)
continue
creator.create_singleton_node()
# We are creating new nodes to replace the original instance
# Copy the attributes of the original instance to the new node
original_data = read(instance_node)
# The family gets converted to the new family (this is due to
# "rendering" family being converted to "renderlayer" family)
original_data["family"] = creator.family
# Convert to creator attributes when relevant
creator_attributes = {}
for key in list(original_data.keys()):
# Iterate in order of the original attributes to preserve order
# in the output creator attributes
if key in creator_attribute_names:
creator_attributes[key] = original_data.pop(key)
original_data["creator_attributes"] = creator_attributes
# For layer in maya layers
for layer in layers:
layer_instance_node = creator.find_layer_instance_node(layer)
if not layer_instance_node:
# TODO: Make function public
layer_instance_node = creator._create_layer_instance_node(
layer
)
# Transfer the main attributes of the original instance
layer_data = original_data.copy()
layer_data.update(data)
self.imprint_instance_node(layer_instance_node,
data=layer_data)
# Delete the legacy instance node
cmds.delete(instance_node)