rename config folder

This commit is contained in:
Jakub Jezek 2018-10-02 22:55:04 +02:00
parent bb17ef7221
commit 7667674317
182 changed files with 272 additions and 272 deletions

View file

@ -0,0 +1,48 @@
import pype.maya.plugin
class AbcLoader(pype.maya.plugin.ReferenceLoader):
"""Specific loader of Alembic for the avalon.animation family"""
families = ["studio.animation",
"studio.camera",
"studio.pointcache"]
representations = ["abc"]
label = "Reference animation"
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
import maya.cmds as cmds
from avalon import maya
cmds.loadPlugin("AbcImport.mll", quiet=True)
# Prevent identical alembic nodes from being shared
# Create unique namespace for the cameras
# Get name from asset being loaded
# Assuming name is subset name from the animation, we split the number
# suffix from the name to ensure the namespace is unique
name = name.split("_")[0]
namespace = maya.unique_namespace("{}_".format(name),
format="%03d",
suffix="_abc")
# hero_001 (abc)
# asset_counter{optional}
nodes = cmds.file(self.fname,
namespace=namespace,
sharedReferenceFile=False,
groupReference=True,
groupName="{}:{}".format(namespace, name),
reference=True,
returnNewNodes=True)
# load studio ID attribute
self[:] = nodes
return nodes

View file

@ -0,0 +1,147 @@
"""A module containing generic loader actions that will display in the Loader.
"""
from avalon import api
class SetFrameRangeLoader(api.Loader):
"""Specific loader of Alembic for the avalon.animation family"""
families = ["studio.animation",
"studio.camera",
"studio.pointcache"]
representations = ["abc"]
label = "Set frame range"
order = 11
icon = "clock-o"
color = "white"
def load(self, context, name, namespace, data):
import maya.cmds as cmds
version = context['version']
version_data = version.get("data", {})
start = version_data.get("startFrame", None)
end = version_data.get("endFrame", None)
if start is None or end is None:
print("Skipping setting frame range because start or "
"end frame data is missing..")
return
cmds.playbackOptions(minTime=start,
maxTime=end,
animationStartTime=start,
animationEndTime=end)
class SetFrameRangeWithHandlesLoader(api.Loader):
"""Specific loader of Alembic for the avalon.animation family"""
families = ["studio.animation",
"studio.camera",
"studio.pointcache"]
representations = ["abc"]
label = "Set frame range (with handles)"
order = 12
icon = "clock-o"
color = "white"
def load(self, context, name, namespace, data):
import maya.cmds as cmds
version = context['version']
version_data = version.get("data", {})
start = version_data.get("startFrame", None)
end = version_data.get("endFrame", None)
if start is None or end is None:
print("Skipping setting frame range because start or "
"end frame data is missing..")
return
# Include handles
handles = version_data.get("handles", 0)
start -= handles
end += handles
cmds.playbackOptions(minTime=start,
maxTime=end,
animationStartTime=start,
animationEndTime=end)
class ImportMayaLoader(api.Loader):
"""Import action for Maya (unmanaged)
Warning:
The loaded content will be unmanaged and is *not* visible in the
scene inventory. It's purely intended to merge content into your scene
so you could also use it as a new base.
"""
representations = ["ma"]
families = ["*"]
label = "Import"
order = 10
icon = "arrow-circle-down"
color = "#775555"
def load(self, context, name=None, namespace=None, data=None):
import maya.cmds as cmds
from avalon import maya
from avalon.maya import lib
choice = self.display_warning()
if choice is False:
return
asset = context['asset']
namespace = namespace or lib.unique_namespace(
asset["name"] + "_",
prefix="_" if asset["name"][0].isdigit() else "",
suffix="_",
)
with maya.maintained_selection():
cmds.file(self.fname,
i=True,
namespace=namespace,
returnNewNodes=True,
groupReference=True,
groupName="{}:{}".format(namespace, name))
# We do not containerize imported content, it remains unmanaged
return
def display_warning(self):
"""Show warning to ensure the user can't import models by accident
Returns:
bool
"""
from avalon.vendor.Qt import QtWidgets
accept = QtWidgets.QMessageBox.Ok
buttons = accept | QtWidgets.QMessageBox.Cancel
message = "Are you sure you want import this"
state = QtWidgets.QMessageBox.warning(None,
"Are you sure?",
message,
buttons=buttons,
defaultButton=accept)
return state == accept

View file

@ -0,0 +1,33 @@
import pype.maya.plugin
class AbcLoader(pype.maya.plugin.ReferenceLoader):
"""Specific loader of Alembic for the avalon.animation family"""
families = ["studio.animation",
"studio.pointcache"]
label = "Reference animation"
representations = ["abc"]
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
import maya.cmds as cmds
cmds.loadPlugin("AbcImport.mll", quiet=True)
nodes = cmds.file(self.fname,
namespace=namespace,
sharedReferenceFile=False,
groupReference=True,
groupName="{}:{}".format(namespace, name),
reference=True,
returnNewNodes=True)
self[:] = nodes
return nodes
def switch(self, container, representation):
self.update(container, representation)

View file

@ -0,0 +1,45 @@
import pype.maya.plugin
class CameraLoader(pype.maya.plugin.ReferenceLoader):
"""Specific loader of Alembic for the avalon.animation family"""
families = ["studio.camera"]
label = "Reference camera"
representations = ["abc", "ma"]
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
import maya.cmds as cmds
# Get family type from the context
cmds.loadPlugin("AbcImport.mll", quiet=True)
nodes = cmds.file(self.fname,
namespace=namespace,
sharedReferenceFile=False,
groupReference=True,
groupName="{}:{}".format(namespace, name),
reference=True,
returnNewNodes=True)
cameras = cmds.ls(nodes, type="camera")
# Check the Maya version, lockTransform has been introduced since
# Maya 2016.5 Ext 2
version = int(cmds.about(version=True))
if version >= 2016:
for camera in cameras:
cmds.camera(camera, edit=True, lockTransform=True)
else:
self.log.warning("This version of Maya does not support locking of"
" transforms of cameras.")
self[:] = nodes
return nodes
def switch(self, container, representation):
self.update(container, representation)

View file

@ -0,0 +1,40 @@
import pype.maya.plugin
class LookLoader(pype.maya.plugin.ReferenceLoader):
"""Specific loader for lookdev"""
families = ["studio.look"]
representations = ["ma"]
label = "Reference look"
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
"""
Load and try to ssign Lookdev to nodes based on relationship data
Args:
name:
namespace:
context:
data:
Returns:
"""
import maya.cmds as cmds
from avalon import maya
with maya.maintained_selection():
nodes = cmds.file(self.fname,
namespace=namespace,
reference=True,
returnNewNodes=True)
self[:] = nodes
def switch(self, container, representation):
self.update(container, representation)

View file

@ -0,0 +1,33 @@
import pype.maya.plugin
class MayaAsciiLoader(pype.maya.plugin.ReferenceLoader):
"""Load the model"""
families = ["pype.mayaAscii"]
representations = ["ma"]
label = "Reference Maya Ascii"
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
import maya.cmds as cmds
from avalon import maya
with maya.maintained_selection():
nodes = cmds.file(self.fname,
namespace=namespace,
reference=True,
returnNewNodes=True,
groupReference=True,
groupName="{}:{}".format(namespace, name))
self[:] = nodes
return nodes
def switch(self, container, representation):
self.update(container, representation)

View file

@ -0,0 +1,125 @@
from avalon import api
import pype.maya.plugin
class ModelLoader(pype.maya.plugin.ReferenceLoader):
"""Load the model"""
families = ["studio.model"]
representations = ["ma"]
label = "Reference Model"
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
import maya.cmds as cmds
from avalon import maya
with maya.maintained_selection():
nodes = cmds.file(self.fname,
namespace=namespace,
reference=True,
returnNewNodes=True,
groupReference=True,
groupName="{}:{}".format(namespace, name))
self[:] = nodes
return nodes
def switch(self, container, representation):
self.update(container, representation)
class GpuCacheLoader(api.Loader):
"""Load model Alembic as gpuCache"""
families = ["studio.model"]
representations = ["abc"]
label = "Import Gpu Cache"
order = -5
icon = "code-fork"
color = "orange"
def load(self, context, name, namespace, data):
import maya.cmds as cmds
import avalon.maya.lib as lib
from avalon.maya.pipeline import containerise
asset = context['asset']['name']
namespace = namespace or lib.unique_namespace(
asset + "_",
prefix="_" if asset[0].isdigit() else "",
suffix="_",
)
cmds.loadPlugin("gpuCache", quiet=True)
# Root group
label = "{}:{}".format(namespace, name)
root = cmds.group(name=label, empty=True)
# Create transform with shape
transform_name = label + "_GPU"
transform = cmds.createNode("transform", name=transform_name,
parent=root)
cache = cmds.createNode("gpuCache",
parent=transform,
name="{0}Shape".format(transform_name))
# Set the cache filepath
cmds.setAttr(cache + '.cacheFileName', self.fname, type="string")
cmds.setAttr(cache + '.cacheGeomPath', "|", type="string") # root
# Lock parenting of the transform and cache
cmds.lockNode([transform, cache], lock=True)
nodes = [root, transform, cache]
self[:] = nodes
return containerise(
name=name,
namespace=namespace,
nodes=nodes,
context=context,
loader=self.__class__.__name__)
def update(self, container, representation):
import maya.cmds as cmds
path = api.get_representation_path(representation)
# Update the cache
members = cmds.sets(container['objectName'], query=True)
caches = cmds.ls(members, type="gpuCache", long=True)
assert len(caches) == 1, "This is a bug"
for cache in caches:
cmds.setAttr(cache + ".cacheFileName", path, type="string")
cmds.setAttr(container["objectName"] + ".representation",
str(representation["_id"]),
type="string")
def switch(self, container, representation):
self.update(container, representation)
def remove(self, container):
import maya.cmds as cmds
members = cmds.sets(container['objectName'], query=True)
cmds.lockNode(members, lock=False)
cmds.delete([container['objectName']] + members)
# Clean up the namespace
try:
cmds.namespace(removeNamespace=container['namespace'],
deleteNamespaceContent=True)
except RuntimeError:
pass

View file

@ -0,0 +1,70 @@
from maya import cmds
import pype.maya.plugin
from avalon import api, maya
class RigLoader(pype.maya.plugin.ReferenceLoader):
"""Specific loader for rigs
This automatically creates an instance for animators upon load.
"""
families = ["studio.rig"]
representations = ["ma"]
label = "Reference rig"
order = -10
icon = "code-fork"
color = "orange"
def process_reference(self, context, name, namespace, data):
nodes = cmds.file(self.fname,
namespace=namespace,
reference=True,
returnNewNodes=True,
groupReference=True,
groupName="{}:{}".format(namespace, name))
# Store for post-process
self[:] = nodes
if data.get("post_process", True):
self._post_process(name, namespace, context, data)
return nodes
def _post_process(self, name, namespace, context, data):
# TODO(marcus): We are hardcoding the name "out_SET" here.
# Better register this keyword, so that it can be used
# elsewhere, such as in the Integrator plug-in,
# without duplication.
output = next((node for node in self if
node.endswith("out_SET")), None)
controls = next((node for node in self if
node.endswith("controls_SET")), None)
assert output, "No out_SET in rig, this is a bug."
assert controls, "No controls_SET in rig, this is a bug."
# Find the roots amongst the loaded nodes
roots = cmds.ls(self[:], assemblies=True, long=True)
assert roots, "No root nodes in rig, this is a bug."
asset = api.Session["AVALON_ASSET"]
dependency = str(context["representation"]["_id"])
# Create the animation instance
with maya.maintained_selection():
cmds.select([output, controls] + roots, noExpand=True)
api.create(name=namespace,
asset=asset,
family="studio.animation",
options={"useSelection": True},
data={"dependencies": dependency})
def switch(self, container, representation):
self.update(container, representation)

View file

@ -0,0 +1,80 @@
from avalon import api
class SetDressLoader(api.Loader):
families = ["studio.setdress"]
representations = ["json"]
label = "Load Set Dress"
order = -9
icon = "code-fork"
color = "orange"
def load(self, context, name, namespace, data):
from avalon.maya.pipeline import containerise
from avalon.maya import lib
asset = context['asset']['name']
namespace = namespace or lib.unique_namespace(
asset + "_",
prefix="_" if asset[0].isdigit() else "",
suffix="_",
)
from config import setdress_api
containers = setdress_api.load_package(filepath=self.fname,
name=name,
namespace=namespace)
self[:] = containers
# Only containerize if any nodes were loaded by the Loader
nodes = self[:]
if not nodes:
return
return containerise(
name=name,
namespace=namespace,
nodes=nodes,
context=context,
loader=self.__class__.__name__)
def update(self, container, representation):
from config import setdress_api
return setdress_api.update_package(container,
representation)
def remove(self, container):
"""Remove all sub containers"""
from avalon import api
from config import setdress_api
import maya.cmds as cmds
# Remove all members
member_containers = setdress_api.get_contained_containers(container)
for member_container in member_containers:
self.log.info("Removing container %s",
member_container['objectName'])
api.remove(member_container)
# Remove alembic hierarchy reference
# TODO: Check whether removing all contained references is safe enough
members = cmds.sets(container['objectName'], query=True) or []
references = cmds.ls(members, type="reference")
for reference in references:
self.log.info("Removing %s", reference)
fname = cmds.referenceQuery(reference, filename=True)
cmds.file(fname, removeReference=True)
# Delete container and its contents
if cmds.objExists(container['objectName']):
members = cmds.sets(container['objectName'], query=True) or []
cmds.delete([container['objectName']] + members)
# TODO: Ensure namespace is gone

View file

@ -0,0 +1,144 @@
from avalon.maya import lib
from avalon import api
import maya.cmds as cmds
class VRayProxyLoader(api.Loader):
"""Load VRayMesh proxy"""
families = ["studio.vrayproxy"]
representations = ["vrmesh"]
label = "Import VRay Proxy"
order = -10
icon = "code-fork"
color = "orange"
def load(self, context, name, namespace, data):
from avalon.maya.pipeline import containerise
from pype.maya.lib import namespaced
asset_name = context['asset']["name"]
namespace = namespace or lib.unique_namespace(
asset_name + "_",
prefix="_" if asset_name[0].isdigit() else "",
suffix="_",
)
# Ensure V-Ray for Maya is loaded.
cmds.loadPlugin("vrayformaya", quiet=True)
with lib.maintained_selection():
cmds.namespace(addNamespace=namespace)
with namespaced(namespace, new=False):
nodes = self.create_vray_proxy(name,
filename=self.fname)
self[:] = nodes
if not nodes:
return
return containerise(
name=name,
namespace=namespace,
nodes=nodes,
context=context,
loader=self.__class__.__name__)
def update(self, container, representation):
node = container['objectName']
assert cmds.objExists(node), "Missing container"
members = cmds.sets(node, query=True) or []
vraymeshes = cmds.ls(members, type="VRayMesh")
assert vraymeshes, "Cannot find VRayMesh in container"
filename = api.get_representation_path(representation)
for vray_mesh in vraymeshes:
cmds.setAttr("{}.fileName".format(vray_mesh),
filename,
type="string")
# Update metadata
cmds.setAttr("{}.representation".format(node),
str(representation["_id"]),
type="string")
def remove(self, container):
# Delete container and its contents
if cmds.objExists(container['objectName']):
members = cmds.sets(container['objectName'], query=True) or []
cmds.delete([container['objectName']] + members)
# Remove the namespace, if empty
namespace = container['namespace']
if cmds.namespace(exists=namespace):
members = cmds.namespaceInfo(namespace, listNamespace=True)
if not members:
cmds.namespace(removeNamespace=namespace)
else:
self.log.warning("Namespace not deleted because it "
"still has members: %s", namespace)
def switch(self, container, representation):
self.update(container, representation)
def create_vray_proxy(self, name, filename):
"""Re-create the structure created by VRay to support vrmeshes
Args:
name(str): name of the asset
Returns:
nodes(list)
"""
# Create nodes
vray_mesh = cmds.createNode('VRayMesh', name="{}_VRMS".format(name))
mesh_shape = cmds.createNode("mesh", name="{}_GEOShape".format(name))
vray_mat = cmds.createNode("VRayMeshMaterial",
name="{}_VRMM".format(name))
vray_mat_sg = cmds.createNode("shadingEngine",
name="{}_VRSG".format(name))
cmds.setAttr("{}.fileName".format(vray_mesh),
filename,
type="string")
# Create important connections
cmds.connectAttr("time1.outTime",
"{0}.currentFrame".format(vray_mesh))
cmds.connectAttr("{}.fileName2".format(vray_mesh),
"{}.fileName".format(vray_mat))
cmds.connectAttr("{}.instancing".format(vray_mesh),
"{}.instancing".format(vray_mat))
cmds.connectAttr("{}.output".format(vray_mesh),
"{}.inMesh".format(mesh_shape))
cmds.connectAttr("{}.overrideFileName".format(vray_mesh),
"{}.overrideFileName".format(vray_mat))
cmds.connectAttr("{}.currentFrame".format(vray_mesh),
"{}.currentFrame".format(vray_mat))
# Set surface shader input
cmds.connectAttr("{}.outColor".format(vray_mat),
"{}.surfaceShader".format(vray_mat_sg))
# Connect mesh to shader
cmds.sets([mesh_shape], addElement=vray_mat_sg)
group_node = cmds.group(empty=True, name="{}_GRP".format(name))
mesh_transform = cmds.listRelatives(mesh_shape,
parent=True, fullPath=True)
cmds.parent(mesh_transform, group_node)
nodes = [vray_mesh, mesh_shape, vray_mat, vray_mat_sg, group_node]
# Fix: Force refresh so the mesh shows correctly after creation
cmds.refresh()
cmds.setAttr("{}.geomType".format(vray_mesh), 2)
return nodes

View file

@ -0,0 +1,298 @@
import os
import json
import re
import glob
from collections import defaultdict
from maya import cmds
from avalon import api
from avalon.maya import lib as avalon_lib, pipeline
from pype.maya import lib
class YetiCacheLoader(api.Loader):
families = ["studio.yeticache", "studio.yetiRig"]
representations = ["fur"]
label = "Load Yeti Cache"
order = -9
icon = "code-fork"
color = "orange"
def load(self, context, name=None, namespace=None, data=None):
# Build namespace
asset = context["asset"]
if namespace is None:
namespace = self.create_namespace(asset["name"])
# Ensure Yeti is loaded
if not cmds.pluginInfo("pgYetiMaya", query=True, loaded=True):
cmds.loadPlugin("pgYetiMaya", quiet=True)
# Get JSON
fname, ext = os.path.splitext(self.fname)
settings_fname = "{}.fursettings".format(fname)
with open(settings_fname, "r") as fp:
fursettings = json.load(fp)
# Check if resources map exists
# Get node name from JSON
if "nodes" not in fursettings:
raise RuntimeError("Encountered invalid data, expect 'nodes' in "
"fursettings.")
node_data = fursettings["nodes"]
nodes = self.create_nodes(namespace, node_data)
group_name = "{}:{}".format(namespace, name)
group_node = cmds.group(nodes, name=group_name)
nodes.append(group_node)
self[:] = nodes
return pipeline.containerise(name=name,
namespace=namespace,
nodes=nodes,
context=context,
loader=self.__class__.__name__)
def remove(self, container):
from maya import cmds
namespace = container["namespace"]
container_name = container["objectName"]
self.log.info("Removing '%s' from Maya.." % container["name"])
container_content = cmds.sets(container_name, query=True)
nodes = cmds.ls(container_content, long=True)
nodes.append(container_name)
try:
cmds.delete(nodes)
except ValueError:
# Already implicitly deleted by Maya upon removing reference
pass
cmds.namespace(removeNamespace=namespace, deleteNamespaceContent=True)
def update(self, container, representation):
namespace = container["namespace"]
container_node = container["objectName"]
path = api.get_representation_path(representation)
# Get all node data
fname, ext = os.path.splitext(path)
settings_fname = "{}.fursettings".format(fname)
with open(settings_fname, "r") as fp:
settings = json.load(fp)
# Collect scene information of asset
set_members = cmds.sets(container["objectName"], query=True)
container_root = lib.get_container_transforms(container,
members=set_members,
root=True)
scene_nodes = cmds.ls(set_members, type="pgYetiMaya", long=True)
# Build lookup with cbId as keys
scene_lookup = defaultdict(list)
for node in scene_nodes:
cb_id = lib.get_id(node)
scene_lookup[cb_id].append(node)
# Re-assemble metadata with cbId as keys
meta_data_lookup = {n["cbId"]: n for n in settings["nodes"]}
# Compare look ups and get the nodes which ar not relevant any more
to_delete_lookup = {cb_id for cb_id in scene_lookup.keys() if
cb_id not in meta_data_lookup}
if to_delete_lookup:
# Get nodes and remove entry from lookup
to_remove = []
for _id in to_delete_lookup:
# Get all related nodes
shapes = scene_lookup[_id]
# Get the parents of all shapes under the ID
transforms = cmds.listRelatives(shapes,
parent=True,
fullPath=True) or []
to_remove.extend(shapes + transforms)
# Remove id from look uop
scene_lookup.pop(_id, None)
cmds.delete(to_remove)
for cb_id, data in meta_data_lookup.items():
# Update cache file name
file_name = data["name"].replace(":", "_")
cache_file_path = "{}.%04d.fur".format(file_name)
data["attrs"]["cacheFileName"] = os.path.join(path, cache_file_path)
if cb_id not in scene_lookup:
self.log.info("Creating new nodes ..")
new_nodes = self.create_nodes(namespace, [data])
cmds.sets(new_nodes, addElement=container_node)
cmds.parent(new_nodes, container_root)
else:
# Update the matching nodes
scene_nodes = scene_lookup[cb_id]
lookup_result = meta_data_lookup[cb_id]["name"]
# Remove namespace if any (e.g.: "character_01_:head_YNShape")
node_name = lookup_result.rsplit(":", 1)[-1]
for scene_node in scene_nodes:
# Get transform node, this makes renaming easier
transforms = cmds.listRelatives(scene_node,
parent=True,
fullPath=True) or []
assert len(transforms) == 1, "This is a bug!"
# Get scene node's namespace and rename the transform node
lead = scene_node.rsplit(":", 1)[0]
namespace = ":{}".format(lead.rsplit("|")[-1])
new_shape_name = "{}:{}".format(namespace, node_name)
new_trans_name = new_shape_name.rsplit("Shape", 1)[0]
transform_node = transforms[0]
cmds.rename(transform_node,
new_trans_name,
ignoreShape=False)
# Get the newly named shape node
yeti_nodes = cmds.listRelatives(new_trans_name,
children=True)
yeti_node = yeti_nodes[0]
for attr, value in data["attrs"].items():
lib.set_attribute(attr, value, yeti_node)
cmds.setAttr("{}.representation".format(container_node),
str(representation["_id"]),
typ="string")
def switch(self, container, representation):
self.update(container, representation)
# helper functions
def create_namespace(self, asset):
"""Create a unique namespace
Args:
asset (dict): asset information
"""
asset_name = "{}_".format(asset)
prefix = "_" if asset_name[0].isdigit()else ""
namespace = avalon_lib.unique_namespace(asset_name,
prefix=prefix,
suffix="_")
return namespace
def validate_cache(self, filename, pattern="%04d"):
"""Check if the cache has more than 1 frame
All caches with more than 1 frame need to be called with `%04d`
If the cache has only one frame we return that file name as we assume
it is a snapshot.
Args:
filename(str)
pattern(str)
Returns:
str
"""
glob_pattern = filename.replace(pattern, "*")
escaped = re.escape(filename)
re_pattern = escaped.replace(pattern, "-?[0-9]+")
files = glob.glob(glob_pattern)
files = [str(f) for f in files if re.match(re_pattern, f)]
if len(files) == 1:
return files[0]
elif len(files) == 0:
self.log.error("Could not find cache files for '%s'" % filename)
return filename
def create_nodes(self, namespace, settings):
"""Create nodes with the correct namespace and settings
Args:
namespace(str): namespace
settings(list): list of dictionaries
Returns:
list
"""
nodes = []
for node_settings in settings:
# Create pgYetiMaya node
original_node = node_settings["name"]
node_name = "{}:{}".format(namespace, original_node)
yeti_node = cmds.createNode("pgYetiMaya", name=node_name)
# Create transform node
transform_node = node_name.rstrip("Shape")
lib.set_id(transform_node, node_settings["transform"]["cbId"])
lib.set_id(yeti_node, node_settings["cbId"])
nodes.extend([transform_node, yeti_node])
# Ensure the node has no namespace identifiers
attributes = node_settings["attrs"]
# Check if cache file name is stored
if "cacheFileName" not in attributes:
file_name = original_node.replace(":", "_")
cache_name = "{}.%04d.fur".format(file_name)
cache = os.path.join(self.fname, cache_name)
self.validate_cache(cache)
attributes["cacheFileName"] = cache
# Update attributes with requirements
attributes.update({"viewportDensity": 0.1,
"verbosity": 2,
"fileMode": 1})
# Apply attributes to pgYetiMaya node
for attr, value in attributes.items():
lib.set_attribute(attr, value, yeti_node)
# Fix for : YETI-6
# Fixes the render stats (this is literally taken from Perigrene's
# ../scripts/pgYetiNode.mel script)
cmds.setAttr("{}.visibleInReflections".format(yeti_node), True)
cmds.setAttr("{}.visibleInRefractions".format(yeti_node), True)
# Connect to the time node
cmds.connectAttr("time1.outTime", "%s.currentTime" % yeti_node)
return nodes

View file

@ -0,0 +1,31 @@
import pype.maya.plugin
class YetiRigLoader(pype.maya.plugin.ReferenceLoader):
families = ["studio.yetiRig"]
representations = ["ma"]
label = "Load Yeti Rig"
order = -9
icon = "code-fork"
color = "orange"
def process_reference(self, context, name=None, namespace=None, data=None):
import maya.cmds as cmds
from avalon import maya
with maya.maintained_selection():
nodes = cmds.file(self.fname,
namespace=namespace,
reference=True,
returnNewNodes=True,
groupReference=True,
groupName="{}:{}".format(namespace, name))
self[:] = nodes
self.log.info("Yeti Rig Connection Manager will be available soon")
return nodes