import os
import argparse
import time
from cgl.plugins.maya import standalone
[docs]
def detect_export_frame_range():
"""
Autodetect frame range of file based on animations curves and various nodes
"""
from maya import cmds
nodes = cmds.ls(type=["animCurve", "cacheFile", "AlembicNode", "expression"])
if not nodes:
return 1, 1 # no animated nodes
start_frame = None
end_frame = None
for node in nodes:
if cmds.nodeType(node) == "AlembicNode":
start = cmds.getAttr(f"{node}.startFrame")
end = cmds.getAttr(f"{node}.endFrame")
# TODO look deeper into how Alembic Node calculates frame range
# just do this hack for now
play_start = int(cmds.playbackOptions(query=True, animationStartTime=True))
play_end = int(cmds.playbackOptions(query=True, animationEndTime=True))
start = min(start, play_start)
end = max(end, play_end)
elif cmds.nodeType(node) in ("expression", 'cacheFile'):
# not really clear what the frame range might be
# make sure range is at least the length of timeline
start = int(cmds.playbackOptions(query=True, animationStartTime=True))
end = int(cmds.playbackOptions(query=True, animationEndTime=True))
else:
keyframes = cmds.keyframe(node, query=True)
if not keyframes:
continue
start = int(min(keyframes))
end = int(max(keyframes))
if start_frame is None or start < start_frame:
start_frame = start
if end_frame is None or end > end_frame:
end_frame = end
return start_frame, end_frame
[docs]
def has_uv(mesh):
if not cmds.polyUVSet(mesh, query=True, allUVSets=True):
return False
uv_info = cmds.polyEvaluate(mesh, uv=True)
return uv_info['minU'] !=0 or uv_info['minV'] != 0
[docs]
def maya_auto_uvs(nodes = None):
from maya import cmds
start = time.time()
if not nodes:
nodes = cmds.ls(type="mesh") or []
for mesh in nodes:
if cmds.nodeType(mesh) != 'mesh':
continue
# if has_uv(mesh):
# print("auto uvs: {mesh} skipping has uvs")
# continue
print(f"auto uvs: {mesh} ",end="", flush=True)
s = time.time()
cmds.polyAutoProjection(mesh,
constructionHistory=False,
caching=True,
optimize=True)
print(f"{time.time() - s : 10.4f} secs")
print(f"auto uvs in {time.time() - start} secs")
[docs]
def convert_to_abc(src_path, dst_path, auto_uvs=False, **kwargs):
from maya import cmds
start = time.time()
for plugin in ('AbcImport', 'AbcExport', "fbxmaya"):
if not cmds.pluginInfo(plugin, q=True, loaded=True):
print(f'Loading {plugin} plugin...')
cmds.loadPlugin(plugin)
print(f"opening {src_path}")
cmds.file(src_path, open=True, force=True)
if auto_uvs:
print("running auto uvs")
maya_auto_uvs()
attrs = ['-file', dst_path]
defaults = {}
defaults['autoSubd'] = True
defaults['uvWrite'] = True
defaults['writeColorSets'] = True
defaults['writeFaceSets'] = True
defaults['writeVisibility'] = True
defaults['writeUVSets'] = True
defaults['dataFormat'] = 'Ogawa'
defaults['frameRange'] = detect_export_frame_range()
# set defaults
for key, value in defaults.items():
if key not in kwargs:
kwargs[key] = value
# Add kwargs to attrs
for key, value in kwargs.items():
if value is True:
attrs.append(f"-{key}")
elif value is False:
continue
elif isinstance(value, (tuple, list)):
# This takes multiple arguments.
if key == 'frameRange':
attrs.append(f"-{key}")
attrs.extend(value)
else:
for val in value:
attrs.extend((f"-{key}", val))
else:
attrs.extend((f"-{key}", value))
flags = ' '.join(str(attr) for attr in attrs)
print(f'AbcExport -v -j "{flags}"')
cmds.AbcExport(verbose=True, j=flags)
print(f"AbcExport in {time.time() - start} secs")
[docs]
def standalone_convert_to_abc(src_path, dst_path, auto_uvs=False, **kwargs):
entrypoint = "cgl.plugins.maya.convert_to_abc:convert_to_abc"
return standalone.run_in_maya_standalone(entrypoint, src_path, dst_path, auto_uvs, **kwargs)
[docs]
def main():
parser = argparse.ArgumentParser(description="Convert maya compatable file to abc")
parser.add_argument("src_file")
parser.add_argument("-o", "--output")
parser.add_argument("--autouvs",default=False, action="store_true", help="run maya auto uvs on every mesh")
args = parser.parse_args()
if not args.output:
name, _ = os.path.splitext(args.src_file)
args.output = name + '.abc'
standalone_convert_to_abc(args.src_file, args.output, auto_uvs=args.autouvs)
if __name__ == "__main__":
main()
# from cgl.plugins.maya.convert_to_abc import standalone_convert_to_abc
# standalone_convert_to_abc(src_path, dst_path)