在公司给游戏部门弄一个导出fbx的插件,导出的时候需要将namespace去掉,这样方便他们导入UE里面,以前的操作是将Maya里的reference全部解除掉,变成导出的模式,这样去掉namespace后再导出fbx,但是这样呢有个问题,就是当一个文件里有相同的rig的时候,那么变成导入的时候就会多个后缀1,2之类的;而且另一方面将源文件也给破坏了,动画师如果再修改的话还得重新开文件,于是寻找下在Maya里有没有在不解除reference的情况下,去掉namespace,最后找到了,就是API了,借助API就可以实现了,下面是具体的代码,自己略加注解:
import maya.cmds as cmds
import maya.OpenMaya as om
class StripNamespace(object):
"""
Context manager use to temporarily strip a namespace from all dependency nodes within a namespace.
Sometimes also can be used to unparent some specific groups temporarily
This allows nodes to masquerade as if they never had namespace, including those considered read-only
due to file referencing.
Usage:
with StripNamespace('someNamespace') as stripped_nodes:
print cmds.ls(stripped_nodes)
or
with StripNamespace('someNamespace', unparent=['grp1', 'grp2']) as stripped_nodes:
print stripped_nodes
"""
@classmethod
def as_name(cls, uuid):
"""
Convenience method to extract the name from uuid
:type uuid: basestring
:rtype: unicode|None
"""
names = cmds.ls(uuid)
if names:
for name in names:
if ':' not in name:
return name
else:
return None
def __init__(self, namespace, unparent=[]):
if cmds.namespace(exists=namespace):
self.original_names = {} # (UUID, name_within_namespace)
self.parent = {}
self.namespace = cmds.namespaceInfo(namespace, fn=True)
self.unparent = unparent
else:
raise ValueError('Could not locate supplied namespace, "{0}"'.format(namespace))
def toMObject(self, node):
selList = om.MSelectionList()
selList.add(str(node))
mObject = om.MObject()
selList.getDependNode(0, mObject)
return mObject
def __enter__(self):
if self.unparent:
for item in self.unparent:
selList = om.MSelectionList()
api_obj = om.MObject()
om.MGlobal.getSelectionListByName(item, selList)
selList.getDependNode(0, api_obj)
dag_parent = cmds.listRelatives(item, p=1)
self.parent[item] = dag_parent[0]
dag_modi = om.MDagModifier()
dag_modi.reparentNode(api_obj)
dag_modi.doIt()
for absolute_name in cmds.namespaceInfo(self.namespace, listOnlyDependencyNodes=True, fullName=True):
# Ensure node was *not* auto-renamed (IE: shape nodes)
if cmds.objExists(absolute_name):
# get an api handle to the node
try:
selList = om.MSelectionList()
api_obj = om.MObject()
om.MGlobal.getSelectionListByName(absolute_name, selList)
selList.getDependNode(0, api_obj)
api_node = om.MFnDependencyNode(api_obj)
# remember the original name to return upon exit
uuid = api_node.uuid().asString()
self.original_names[uuid] = api_node.name()
# strip namespace by renaming via api, bypassing read-only restrictions
without_namespace = api_node.name().replace(self.namespace, '', 1)
api_node.setName(without_namespace)
except:
pass
return [self.as_name(uuid) for uuid in self.original_names]
def __exit__(self, exc_type, exc_val, exc_tb):
for uuid, original_name in self.original_names.iteritems():
try:
current_name = self.as_name(uuid)
selList = om.MSelectionList()
api_obj = om.MObject()
om.MGlobal.getSelectionListByName(current_name, selList)
selList.getDependNode(0, api_obj)
api_node = om.MFnDependencyNode(api_obj)
api_node.setName(original_name)
except:
pass
if self.parent:
for absolute_name, parent in self.parent.iteritems():
dag_modi = om.MDagModifier()
absolute_name_mobject = self.toMObject(absolute_name)
parent_mobject = self.toMObject(parent)
dag_modi.reparentNode(absolute_name_mobject, parent_mobject)
dag_modi.doIt()
里面有unparent的操作,为了是可以将某个组P出来再导出,也是满足游戏那边他们对FBX的层即结构的要求;最后补充一点的是,在Maya里如果一个物体被复制出来,那么他们uuid是相同的,所以在使用as_name的方法的时候,我们只需要获取不带namespace的物体,而带有namespace的物体是未被我们修改的。
这样以来,导出完FBX,文件未被破坏,动画师如果修改的话,也不用重开文件,也不会有对于的后缀了,方便动画这边出FBX了。