mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-26 05:42:15 +01:00
Support multiple UV sets in Alembic (Maya 2017+)
This commit is contained in:
parent
7b34e1b28b
commit
e97fa88a12
4 changed files with 107 additions and 92 deletions
|
|
@ -1179,3 +1179,58 @@ def iter_parents(node):
|
|||
|
||||
node = split[0]
|
||||
yield node
|
||||
|
||||
|
||||
def remove_other_uv_sets(mesh):
|
||||
"""Remove all other UV sets than the current UV set.
|
||||
|
||||
Keep only current UV set and ensure it's the renamed to default 'map1'.
|
||||
|
||||
"""
|
||||
|
||||
uvSets = cmds.polyUVSet(mesh, query=True, allUVSets=True)
|
||||
current = cmds.polyUVSet(mesh, query=True, currentUVSet=True)[0]
|
||||
|
||||
# Copy over to map1
|
||||
if current != 'map1':
|
||||
cmds.polyUVSet(mesh, uvSet=current, newUVSet='map1', copy=True)
|
||||
cmds.polyUVSet(mesh, currentUVSet=True, uvSet='map1')
|
||||
current = 'map1'
|
||||
|
||||
# Delete all non-current UV sets
|
||||
deleteUVSets = [uvSet for uvSet in uvSets if uvSet != current]
|
||||
uvSet = None
|
||||
|
||||
# Maya Bug (tested in 2015/2016):
|
||||
# In some cases the API's MFnMesh will report less UV sets than
|
||||
# maya.cmds.polyUVSet. This seems to happen when the deletion of UV sets
|
||||
# has not triggered a cleanup of the UVSet array attribute on the mesh
|
||||
# node. It will still have extra entries in the attribute, though it will
|
||||
# not show up in API or UI. Nevertheless it does show up in
|
||||
# maya.cmds.polyUVSet. To ensure we clean up the array we'll force delete
|
||||
# the extra remaining 'indices' that we don't want.
|
||||
|
||||
# TODO: Implement a better fix
|
||||
# The best way to fix would be to get the UVSet indices from api with
|
||||
# MFnMesh (to ensure we keep correct ones) and then only force delete the
|
||||
# other entries in the array attribute on the node. But for now we're
|
||||
# deleting all entries except first one. Note that the first entry could
|
||||
# never be removed (the default 'map1' always exists and is supposed to
|
||||
# be undeletable.)
|
||||
try:
|
||||
for uvSet in deleteUVSets:
|
||||
cmds.polyUVSet(mesh, delete=True, uvSet=uvSet)
|
||||
except RuntimeError as exc:
|
||||
log.warning('Error uvSet: %s - %s', uvSet, exc)
|
||||
indices = cmds.getAttr('{0}.uvSet'.format(mesh),
|
||||
multiIndices=True)
|
||||
if not indices:
|
||||
log.warning("No uv set found indices for: %s", mesh)
|
||||
return
|
||||
|
||||
# Delete from end to avoid shifting indices
|
||||
# and remove the indices in the attribute
|
||||
indices = reversed(indices[1:])
|
||||
for i in indices:
|
||||
attr = '{0}.uvSet[{1}]'.format(mesh, i)
|
||||
cmds.removeMultiInstance(attr, b=True)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from colorbleed.maya.lib import extract_alembic
|
|||
class ExtractColorbleedAnimation(colorbleed.api.Extractor):
|
||||
"""Produce an alembic of just point positions and normals.
|
||||
|
||||
Positions and normals are preserved, but nothing more,
|
||||
Positions and normals, uvs, creases are preserved, but nothing more,
|
||||
for plain and predictable point caches.
|
||||
|
||||
"""
|
||||
|
|
@ -49,18 +49,26 @@ class ExtractColorbleedAnimation(colorbleed.api.Extractor):
|
|||
filename = "{name}.abc".format(**instance.data)
|
||||
path = os.path.join(parent_dir, filename)
|
||||
|
||||
options = {
|
||||
"step": instance.data.get("step", 1.0),
|
||||
"attr": ["cbId"],
|
||||
"writeVisibility": True,
|
||||
"writeCreases": True,
|
||||
"uvWrite": True,
|
||||
"selection": True
|
||||
}
|
||||
|
||||
if int(cmds.about(version=True)) >= 2017:
|
||||
# Since Maya 2017 alembic supports multiple uv sets - write them.
|
||||
options["writeUVSets"] = True
|
||||
|
||||
with avalon.maya.suspended_refresh():
|
||||
with avalon.maya.maintained_selection():
|
||||
cmds.select(nodes, noExpand=True)
|
||||
extract_alembic(file=path,
|
||||
startFrame=start,
|
||||
endFrame=end,
|
||||
**{"step": instance.data.get("step", 1.0),
|
||||
"attr": ["cbId"],
|
||||
"writeVisibility": True,
|
||||
"writeCreases": True,
|
||||
"uvWrite": True,
|
||||
"selection": True})
|
||||
**options)
|
||||
|
||||
if "files" not in instance.data:
|
||||
instance.data["files"] = list()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from colorbleed.maya.lib import extract_alembic
|
|||
class ExtractColorbleedAlembic(colorbleed.api.Extractor):
|
||||
"""Produce an alembic of just point positions and normals.
|
||||
|
||||
Positions and normals are preserved, but nothing more,
|
||||
Positions and normals, uvs, creases are preserved, but nothing more,
|
||||
for plain and predictable point caches.
|
||||
|
||||
"""
|
||||
|
|
@ -44,19 +44,27 @@ class ExtractColorbleedAlembic(colorbleed.api.Extractor):
|
|||
filename = "{name}.abc".format(**instance.data)
|
||||
path = os.path.join(parent_dir, filename)
|
||||
|
||||
options = {
|
||||
"step": instance.data.get("step", 1.0),
|
||||
"attr": ["cbId"],
|
||||
"writeVisibility": True,
|
||||
"writeCreases": True,
|
||||
"writeColorSets": writeColorSets,
|
||||
"uvWrite": True,
|
||||
"selection": True
|
||||
}
|
||||
|
||||
if int(cmds.about(version=True)) >= 2017:
|
||||
# Since Maya 2017 alembic supports multiple uv sets - write them.
|
||||
options["writeUVSets"] = True
|
||||
|
||||
with avalon.maya.suspended_refresh():
|
||||
with avalon.maya.maintained_selection():
|
||||
cmds.select(nodes, noExpand=True)
|
||||
extract_alembic(file=path,
|
||||
startFrame=start,
|
||||
endFrame=end,
|
||||
**{"step": instance.data.get("step", 1.0),
|
||||
"attr": ["cbId"],
|
||||
"writeVisibility": True,
|
||||
"writeCreases": True,
|
||||
"writeColorSets": writeColorSets,
|
||||
"uvWrite": True,
|
||||
"selection": True})
|
||||
**options)
|
||||
|
||||
if "files" not in instance.data:
|
||||
instance.data["files"] = list()
|
||||
|
|
|
|||
|
|
@ -2,10 +2,17 @@ from maya import cmds
|
|||
|
||||
import pyblish.api
|
||||
import colorbleed.api
|
||||
import colorbleed.maya.lib as lib
|
||||
|
||||
|
||||
class ValidateMeshSingleUVSet(pyblish.api.InstancePlugin):
|
||||
"""Ensure no multiple UV sets exist for each polygon mesh"""
|
||||
"""Warn on multiple UV sets existing for each polygon mesh.
|
||||
|
||||
On versions prior to Maya 2017 this will force no multiple uv sets because
|
||||
the Alembic exports in Maya prior to 2017 don't support writing multiple
|
||||
UV sets.
|
||||
|
||||
"""
|
||||
|
||||
order = colorbleed.api.ValidateMeshOrder
|
||||
hosts = ['maya']
|
||||
|
|
@ -42,83 +49,20 @@ class ValidateMeshSingleUVSet(pyblish.api.InstancePlugin):
|
|||
invalid = self.get_invalid(instance)
|
||||
|
||||
if invalid:
|
||||
raise ValueError("Nodes found with multiple "
|
||||
"UV sets: {0}".format(invalid))
|
||||
|
||||
message = "Nodes found with multiple UV sets: {0}".format(invalid)
|
||||
|
||||
# Maya 2017 and up allows multiple UV sets in Alembic exports
|
||||
# so we allow it, yet just warn the user to ensure they know about
|
||||
# the other UV sets.
|
||||
allowed = int(cmds.about(version=True)) >= 2017
|
||||
|
||||
if allowed:
|
||||
self.log.warning(message)
|
||||
else:
|
||||
raise ValueError(message)
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
for mesh in cls.get_invalid(instance):
|
||||
cls._repair_mesh(mesh)
|
||||
|
||||
@classmethod
|
||||
def _repair_mesh(cls, mesh):
|
||||
"""Process a single mesh, deleting other UV sets than the active one.
|
||||
|
||||
Keep only current UV set and ensure it's the default 'map1'
|
||||
|
||||
"""
|
||||
from maya import cmds
|
||||
|
||||
uvSets = cmds.polyUVSet(mesh,
|
||||
query=True,
|
||||
allUVSets=True)
|
||||
current = cmds.polyUVSet(mesh,
|
||||
query=True,
|
||||
currentUVSet=True)[0]
|
||||
|
||||
# Copy over to map1
|
||||
if current != 'map1':
|
||||
cmds.polyUVSet(mesh,
|
||||
uvSet=current,
|
||||
newUVSet='map1',
|
||||
copy=True)
|
||||
cmds.polyUVSet(mesh,
|
||||
currentUVSet=True,
|
||||
uvSet='map1')
|
||||
current = 'map1'
|
||||
|
||||
# Delete all non-current UV sets
|
||||
deleteUVSets = [uvSet for uvSet in uvSets if uvSet != current]
|
||||
uvSet = None
|
||||
|
||||
# Maya Bug (tested in 2015/2016):
|
||||
# In some cases the API's MFnMesh will report less UV sets
|
||||
# than maya.cmds.polyUVSet.
|
||||
# This seems to happen when the deletion of UV sets has not
|
||||
# triggered a cleanup of the UVSet array
|
||||
# attribute on the mesh node. It will still have extra
|
||||
# entries in the attribute, though it will not
|
||||
# show up in API or UI. Nevertheless it does show up in
|
||||
# maya.cmds.polyUVSet.
|
||||
# To ensure we clean up the array we'll force delete the
|
||||
# extra remaining 'indices' that we don't want.
|
||||
|
||||
# TODO: Implement a better fix
|
||||
# The best way to fix would be to get the UVSet
|
||||
# indices from api with MFnMesh (to ensure we keep
|
||||
# correct ones) and then only force delete the other
|
||||
# entries in the array attribute on the node.
|
||||
# But for now we're deleting all entries except first
|
||||
# one. Note that the first entry could never
|
||||
# be removed (the default 'map1' always exists and is
|
||||
# supposed to be undeletable.)
|
||||
try:
|
||||
for uvSet in deleteUVSets:
|
||||
cmds.polyUVSet(mesh, delete=True, uvSet=uvSet)
|
||||
except RuntimeError, e:
|
||||
cls.log.warning('uvSet: {0} - '
|
||||
'Error: {1}'.format(uvSet, e))
|
||||
|
||||
indices = cmds.getAttr('{0}.uvSet'.format(mesh),
|
||||
multiIndices=True)
|
||||
if not indices:
|
||||
cls.log.warning(
|
||||
"No uv set found indices for: {0}".format(mesh))
|
||||
return
|
||||
|
||||
# Delete from end to avoid shifting indices
|
||||
# and remove the indices in the attribute
|
||||
indices = reversed(indices[1:])
|
||||
for i in indices:
|
||||
attr = '{0}.uvSet[{1}]'.format(mesh, i)
|
||||
cmds.removeMultiInstance(attr, b=True)
|
||||
lib.remove_other_uv_sets(mesh)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue