Merged in Aardschok/config/fixes (pull request #17)

Mayor fixes for plugins
This commit is contained in:
Wijnand Koreman 2017-09-11 11:02:22 +00:00
commit b27c17a2a9
16 changed files with 167 additions and 143 deletions

View file

@ -84,7 +84,7 @@ class CollectLook(pyblish.api.InstancePlugin):
# Discover related object sets
self.log.info("Gathering sets..")
sets = self.gather_sets(instance)
sets = self.gather_sets(cmds.ls(instance, shapes=True))
# Lookup with absolute names (from root namespace)
instance_lookup = set([str(x) for x in cmds.ls(instance, long=True)])
@ -148,21 +148,16 @@ class CollectLook(pyblish.api.InstancePlugin):
"""
sets = dict()
for node in instance:
related_sets = lib.get_related_sets(node)
if not related_sets:
continue
self.log.info("Found sets %s for %s", related_sets, node)
for objset in related_sets:
if objset in sets:
continue
sets[objset] = {"uuid": lib.get_id(objset),
"members": list()}
sets[objset] = {"uuid": lib.get_id(objset), "members": list()}
return sets
@ -178,8 +173,8 @@ class CollectLook(pyblish.api.InstancePlugin):
for objset, data in sets.items():
if not data['members']:
self.log.debug("Removing redundant set information: "
"%s" % objset)
self.log.info("Removing redundant set information: "
"%s" % objset)
sets.pop(objset)
return sets
@ -213,8 +208,7 @@ class CollectLook(pyblish.api.InstancePlugin):
self.log.error("Node '{}' has no attribute 'cbId'".format(node))
return
member_data = {"name": node,
"uuid": cmds.getAttr("{}.cbId".format(node))}
member_data = {"name": node, "uuid": lib.get_id(node)}
# Include components information when components are assigned
if components:
@ -242,6 +236,9 @@ class CollectLook(pyblish.api.InstancePlugin):
attributes = []
for node in instance:
# get history to ignore original shapes
cmds.listHistory(node)
# Collect changes to "custom" attributes
node_attrs = get_look_attrs(node)
@ -251,11 +248,13 @@ class CollectLook(pyblish.api.InstancePlugin):
node_attributes = {}
for attr in node_attrs:
if not cmds.attributeQuery(attr, node=node, exists=True):
continue
attribute = "{}.{}".format(node, attr)
node_attributes[attr] = cmds.getAttr(attribute)
attributes.append({"name": node,
"uuid": cmds.getAttr("{}.cbId".format(node)),
"uuid": lib.get_id(node),
"attributes": node_attributes})
return attributes

View file

@ -12,6 +12,7 @@ class CollectMindbenderMayaRenderlayers(pyblish.api.ContextPlugin):
order = pyblish.api.CollectorOrder
hosts = ["maya"]
label = "Render Layers"
optional = True
def process(self, context):

View file

@ -16,7 +16,8 @@ class ExtractColorbleedAlembic(colorbleed.api.Extractor):
"""
label = "Alembic"
families = ["colorbleed.model", "colorbleed.pointcache"]
families = ["colorbleed.model",
"colorbleed.pointcache"]
optional = True
def process(self, instance):

View file

@ -58,7 +58,11 @@ class ExtractColorbleedAnimation(colorbleed.api.Extractor):
startFrame=start,
endFrame=end,
**{"step": instance.data.get("step", 1.0),
"attr": ["cbId"]})
"attr": ["cbId"],
"writeVisibility": True,
"writeCreases": True,
"uvWrite": True,
"selection": True})
if "files" not in instance.data:
instance.data["files"] = list()

View file

@ -26,26 +26,16 @@ class ValidateFrameRange(pyblish.api.InstancePlugin):
end = instance.data.get("endFrame", None)
handles = instance.data.get("handles", None)
# Check if any of the values are present. If not we'll assume the
# current instance does not require any time values.
if all(value is None for value in [start, end, handles]):
self.log.debug("No time values for this instance. "
"(Missing `startFrame`, `endFrame` or `handles`)")
return
# Check if any of the values are present
if any(value is None for value in [start, end]):
raise ValueError("No time values for this instance. "
"(Missing `startFrame` or `endFrame`)")
# If only one of the two raise an error, it will require both.
has_start = int(start is not None)
has_end = int(end is not None)
if has_start + has_end == 1:
raise RuntimeError("Only a start frame or an end frame is provided"
" instead of both.")
if has_start and has_end:
self.log.info("Comparing start (%s) and end (%s)" % (start, end))
if start > end:
raise RuntimeError("The start frame is a higher value "
"than the end frame: "
"{0}>{1}".format(start, end))
self.log.info("Comparing start (%s) and end (%s)" % (start, end))
if start > end:
raise RuntimeError("The start frame is a higher value "
"than the end frame: "
"{0}>{1}".format(start, end))
if handles is not None:
if handles < 0.0:

View file

@ -1,7 +1,6 @@
import pyblish.api
import colorbleed.api
import cbra.utils.maya.node_uuid as id_utils
import colorbleed.maya.lib as lib
class ValidateLayoutNodeIds(pyblish.api.InstancePlugin):
@ -29,7 +28,7 @@ class ValidateLayoutNodeIds(pyblish.api.InstancePlugin):
invalid = []
for node in non_referenced:
if not id_utils.get_id(node):
if not lib.get_id(node):
invalid.append(node)
return invalid

View file

@ -2,8 +2,7 @@ from maya import cmds
import pyblish.api
import colorbleed.api
import cbra.utils.maya.node_uuid as id_utils
import colorbleed.maya.lib as lib
def get_id_from_history(node):
@ -22,7 +21,7 @@ def get_id_from_history(node):
similar = cmds.ls(history, exactType=nodeType, long=True)
for node in similar:
id = id_utils.get_id(node)
id = lib.get_id(node)
if id:
return id
@ -76,7 +75,7 @@ class CopyUUIDsFromHistoryAction(pyblish.api.Action):
mapping[shape] = id
# Add the ids to the nodes
id_utils.add_ids(mapping)
# id_utils.add_ids(mapping)
self.log.info("Generated ids on nodes: {0}".format(mapping.values()))
@ -136,7 +135,7 @@ class ValidateLayoutShapeNodeIds(pyblish.api.InstancePlugin):
invalid = []
for node in non_referenced:
if not id_utils.get_id(node):
if not lib.get_id(node):
invalid.append(node)
return invalid

View file

@ -1,7 +1,6 @@
import pyblish.api
import colorbleed.api
import cbra.utils.maya.node_uuid as id_utils
import colorbleed.maya.lib as lib
class ValidateLayoutUniqueNodeIds(pyblish.api.InstancePlugin):
@ -28,7 +27,7 @@ class ValidateLayoutUniqueNodeIds(pyblish.api.InstancePlugin):
from collections import defaultdict
ids = defaultdict(list)
for member in members:
id = id_utils.get_id(member)
id = lib.get_id(member)
ids[id].append(member)
# Skip those without IDs (if everything should have an ID that should

View file

@ -2,8 +2,9 @@ from maya import cmds
import pyblish.api
import colorbleed.api
import colorbleed.maya.lib as lib
from cbra.utils.maya.node_uuid import get_id, add_ids
# from cbra.utils.maya.node_uuid import add_ids
def get_deformed_history_id_mapping(shapes):
@ -33,7 +34,8 @@ def get_deformed_history_id_mapping(shapes):
deformed_shapes = [x for x in deformed_shapes if not is_referenced(x)]
# Shapes without id
deformed_shapes_without_id = [x for x in deformed_shapes if not get_id(x)]
deformed_shapes_without_id = [x for x in deformed_shapes
if not lib.get_id(x)]
mapping = {}
for shape in deformed_shapes_without_id:
@ -45,7 +47,7 @@ def get_deformed_history_id_mapping(shapes):
continue
for history_shape in history_shapes:
id = get_id(history_shape)
id = lib.get_id(history_shape)
if not id:
continue
@ -81,11 +83,11 @@ class CopyUUIDsFromHistory(pyblish.api.Action):
mapping = get_deformed_history_id_mapping(invalid)
for destination, source in mapping.items():
ids_map[destination] = get_id(source)
ids_map[destination] = lib.get_id(source)
if not ids_map:
return
add_ids(ids_map)
self.log.info(ids_map)
class ValidateLookDeformedShapes(pyblish.api.InstancePlugin):

View file

@ -28,13 +28,29 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin):
label = 'Look No Default Shaders'
actions = [colorbleed.api.SelectInvalidAction]
def process(self, instance):
"""Process all the nodes in the instance"""
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError("Invalid node relationships found: "
"{0}".format(invalid))
@classmethod
def get_invalid(cls, instance):
disallowed = ["lambert1", "initialShadingGroup",
"initialParticleSE", "particleCloud1"]
disallowed = set(disallowed)
disallowed = set(["lambert1",
"initialShadingGroup",
"initialParticleSE",
"particleCloud1"])
# Check if there are any skinClusters present
# If so ensure nodes which are skinned
intermediate = []
skinclusters = cmds.ls(type="skinCluster")
cls.log.info("Found skinClusters, will skip original shapes")
if skinclusters:
intermediate += cmds.ls(intermediateObjects=True,
shapes=True,
long=True)
invalid = set()
for node in instance:
@ -48,6 +64,8 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin):
# Maya.
if (cmds.objectType(node, isAType="surfaceShape") and
not cmds.ls(object_sets, type="shadingEngine")):
if node in intermediate:
continue
cls.log.error("Detected shape without shading engine: "
"'{}'".format(node))
invalid.add(node)
@ -64,11 +82,3 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin):
invalid.add(node)
return list(invalid)
def process(self, instance):
"""Process all the nodes in the instance"""
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError("Invalid node relationships found: "
"{0}".format(invalid))

View file

@ -3,6 +3,8 @@ from colorbleed.maya import lib
import pyblish.api
import colorbleed.api
from cb.utils.maya import context
class ValidateLookSets(pyblish.api.InstancePlugin):
"""Validate if any sets are missing from the instance and look data
@ -41,40 +43,44 @@ class ValidateLookSets(pyblish.api.InstancePlugin):
"'{}'".format(instance.name))
relationships = instance.data["lookData"]["relationships"]
invalid = []
for node in instance:
# get the connected objectSets of the node
sets = lib.get_related_sets(node)
if not sets:
continue
# check if any objectSets are not present ion the relationships
missing_sets = [s for s in sets if s not in relationships]
if missing_sets:
# A set of this node is not coming along, this is wrong!
cls.log.error("Missing sets '{}' for node "
"'{}'".format(missing_sets, node))
invalid.append(node)
continue
# Ensure the node is in the sets that are collected
for shaderset, data in relationships.items():
if shaderset not in sets:
# no need to check for a set if the node
# isn't in it anyway
layer = instance.data.get("renderlayer", "defaultRenderLayer")
with context.renderlayer(layer):
for node in instance:
# get the connected objectSets of the node
sets = lib.get_related_sets(node)
if not sets:
continue
member_nodes = [member['name'] for member in data['members']]
if node not in member_nodes:
# The node is not found in the collected set
# relationships
cls.log.error("Missing '{}' in collected set node "
"'{}'".format(node, shaderset))
# check if any objectSets are not present ion the relationships
missing_sets = [s for s in sets if s not in relationships]
if missing_sets:
# A set of this node is not coming along, this is wrong!
cls.log.error("Missing sets '{}' for node "
"'{}'".format(missing_sets, node))
invalid.append(node)
continue
# Ensure the node is in the sets that are collected
for shaderset, data in relationships.items():
if shaderset not in sets:
# no need to check for a set if the node
# isn't in it anyway
continue
member_nodes = [member['name'] for member in data['members']]
if node not in member_nodes:
# The node is not found in the collected set
# relationships
cls.log.error("Missing '{}' in collected set node "
"'{}'".format(node, shaderset))
invalid.append(node)
continue
return invalid
@classmethod
def repair(cls, context, instance):
pass

View file

@ -16,11 +16,20 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
label = "Rig Controllers"
hosts = ["maya"]
families = ["colorbleed.rig"]
actions = [colorbleed.api.RepairAction]
actions = [colorbleed.api.RepairAction,
colorbleed.api.SelectInvalidAction]
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError('{} failed, see log '
'information'.format(self.label))
@classmethod
def get_invalid(cls, instance):
error = False
invalid = []
is_keyed = list()
not_locked = list()
is_offset = list()
@ -29,7 +38,7 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
assert controls, "Must have controls in rig controls_SET"
for control in controls:
valid_keyed = self.validate_keyed_state(control)
valid_keyed = cls.validate_keyed_state(control)
if not valid_keyed:
is_keyed.append(control)
@ -39,30 +48,34 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
if not locked:
not_locked.append(control)
valid_transforms = self.validate_transforms(control)
valid_transforms = cls.validate_transforms(control)
if not valid_transforms:
is_offset.append(control)
if is_keyed:
self.log.error("No controls can be keyes. Failed :\n"
cls.log.error("No controls can be keyes. Failed :\n"
"%s" % is_keyed)
error = True
if is_offset:
self.log.error("All controls default transformation values. "
cls.log.error("All controls default transformation values. "
"Failed :\n%s" % is_offset)
error = True
if not_locked:
self.log.error("All controls must have visibility "
cls.log.error("All controls must have visibility "
"attribute locked. Failed :\n"
"%s" % not_locked)
error = True
if error:
raise RuntimeError("Invalid rig controllers. See log for details.")
invalid = is_keyed + not_locked + is_offset
cls.log.error("Invalid rig controllers. See log for details.")
def validate_transforms(self, control):
return invalid
@staticmethod
def validate_transforms(control):
tolerance = 1e-30
identity = [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
@ -71,10 +84,12 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
matrix = cmds.xform(control, query=True, matrix=True, objectSpace=True)
if not all(abs(x - y) < tolerance for x, y in zip(identity, matrix)):
log.error("%s matrix : %s" % (control, matrix))
return False
return True
def validate_keyed_state(self, control):
@staticmethod
def validate_keyed_state(control):
"""Check if the control has an animation curve attached
Args:
control:
@ -90,13 +105,21 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
@classmethod
def repair(cls, instance):
identity = [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]
# lock all controllers in controls_SET
controls = cmds.sets("controls_SET", query=True)
for control in controls:
log.info("Repairing visibility")
attr = "{}.visibility".format(control)
locked = cmds.getAttr(attr, lock=True)
if not locked:
print("Locking visibility for %s" % control)
log.info("Locking visibility for %s" % control)
cmds.setAttr(attr, lock=True)
continue
log.info("Repairing matrix")
if not cls.validate_transforms(control):
cmds.xform(control, matrix=identity, objectSpace=True)

View file

@ -2,9 +2,8 @@ import maya.cmds as cmds
import pyblish.api
import colorbleed.api
import cbra.lib
import cbra.utils.maya.node_uuid as id_utils
import colorbleed.maya.lib as lib
import avalon.io as io
class ValidateRigPointcacheRelatedNodeIds(pyblish.api.InstancePlugin):
@ -27,6 +26,17 @@ class ValidateRigPointcacheRelatedNodeIds(pyblish.api.InstancePlugin):
ignore_types = ("constraint",)
def process(self, instance):
"""Process all meshes"""
print ">>>", instance.data
# Ensure all nodes have a cbId
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError("Nodes found with non-related "
"asset IDs: {0}".format(invalid))
@classmethod
def get_pointcache_nodes(cls, instance):
@ -57,49 +67,23 @@ class ValidateRigPointcacheRelatedNodeIds(pyblish.api.InstancePlugin):
@classmethod
def get_invalid(cls, instance):
# Get a full context from the instance context
context = instance.data['instanceContext']
item_path = context['itemPath']
context = cbra.lib.parse_context(item_path)
invalid_items = []
# get asset id
nodes = cls.get_pointcache_nodes(instance)
def to_item(id):
"""Split the item id part from a node id"""
return id.rsplit(":", 1)[0]
# Generate a fake id in the current context to retrieve the item
# id prefix that should match with ids on the nodes
fake_node = "__node__"
ids = id_utils.generate_ids(context, [fake_node])
id = ids[fake_node]
item_prefix = to_item(id)
# Parse the invalid
invalid = list()
invalid_items = set()
for member in nodes:
member_id = id_utils.get_id(member)
# skip nodes without ids
if not member_id:
continue
if not member_id.startswith(item_prefix):
invalid.append(member)
invalid_items.add(to_item(member_id))
for node in nodes:
node_id = lib.get_id(node)
if not node_id:
invalid_items.append(node)
# Log invalid item ids
if invalid_items:
for item_id in sorted(invalid_items):
cls.log.warning("Found invalid item id: {0}".format(item_id))
return invalid
return invalid_items
def process(self, instance):
"""Process all meshes"""
# Ensure all nodes have a cbId
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError("Nodes found with non-related "
"asset IDs: {0}".format(invalid))
@staticmethod
def to_item(id):
"""Split the item id part from a node id"""
return id.rsplit(":", 1)[0]

View file

@ -76,6 +76,9 @@ class CollectAssumedDestination(pyblish.api.InstancePlugin):
"name": asset_name,
"parent": project["_id"]})
assert asset, ("No asset found by the name '{}' "
"in project '{}'".format(asset_name, project_name))
subset = io.find_one({"type": "subset",
"name": subset_name,
"parent": asset["_id"]})
@ -87,6 +90,7 @@ class CollectAssumedDestination(pyblish.api.InstancePlugin):
version = io.find_one({"type": "version",
"parent": subset["_id"]},
sort=[("name", -1)])
# if there is a subset there ought to be version
if version is not None:
version_number += version["name"]

View file

@ -13,7 +13,7 @@ if "%CB_MAYA_SHARED%" == "" (
:: For scripts menu tool
set PYTHONPATH=%CB_PIPELINE%\git\scriptsmenu\python;%PYTHONPATH%
set PYTHONPATH=%C:\Users\User\Documents\development\scriptsmenu\python;%PYTHONPATH%
set CB_SCRIPTS=%CB_PIPELINE%\git\cbMayaScripts\cbMayaScripts
set COLORBLEED_SCRIPTS=%CB_SCRIPTS%

View file

@ -27,4 +27,7 @@ set PYTHONPATH=%CB_PIPELINE%\git\Qt.py;%PYTHONPATH%
::set PYTHONPATH=%CB_PIPELINE%\git\ftrack-connect\source;%PYTHONPATH%
:: FFMPEG
set FFMPEG_PATH=%CB_APP_SHARED%\ffmpeg\bin\ffmpeg.exe
set FFMPEG_PATH=%CB_APP_SHARED%\ffmpeg\bin\ffmpeg.exe
:: Latest tools - might be unstable
set AVALON_EARLY_ADOPTER=1