-
Notifications
You must be signed in to change notification settings - Fork 9
/
wrap_alembic.py
159 lines (116 loc) · 4.24 KB
/
wrap_alembic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
"""Wrap bare alembic files into a Maya ASCII
Published assets are designed for Maya referencing, but alembics
have problems with this (need proof) and so they are first
embedded into a Maya scene file that is later referenced, in place
of referencing the bare alembic.
"""
import os
import json
import shutil
import tempfile
import subprocess
import contextlib
import pyblish.api
CREATE_NO_WINDOW = 0x08000000
class WrapAlembics(pyblish.api.Extractor):
"""Wrap alembic files with a Maya scene
This plug-in launches Maya Standalone in a subprocess
and wraps each pointcache instance into an additional
Maya scene.
Output from this subprocess is provided as DEBUG
log records.
"""
label = "Wrap Alembics"
families = ["pointcache"]
order = pyblish.api.Extractor.order + 0.1
optional = True
def process(self, context):
tempdir = tempfile.mkdtemp()
temppath = os.path.join(tempdir, "code.py")
paths = list()
for instance in context:
if instance.data("family") != "pointcache":
continue
extract_dir = instance.data("extractDir")
if not extract_dir:
self.log.warning("%s did not have an extractDir" % instance)
continue
paths.append(extract_dir)
source = code.format(paths=json.dumps(paths))
self.log.info("Running source in Maya Standalone: %s" % source)
self.log.info("temp_file: %s" % temp_file)
with temp_file(source) as filename:
self.log.debug("Starting subprocess..")
# Don't include Pyblish nor Magenta
environment = os.environ.copy()
environment.pop("PYTHONPATH", None)
popen = subprocess.Popen(["mayapy", filename],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
creationflags=CREATE_NO_WINDOW,
env=environment)
# Include full output, including any traceback
for line in iter(popen.stdout.readline, b""):
self.log.debug(line.strip())
popen.communicate() # Block till finished
assert popen.returncode == 0, (
"An error occured, see debug log messages for details")
self.log.info("Alembics wrapped successfully")
code = r"""
# Wrap alembic in a Maya ASCII file
#
# This is written and run through maya.standalone
#
# Note:
# Couldn't use inspect.getsource() on a function, due to a bug
# in caching: https://bugs.python.org/issue1218234
# Causing the getsource() to not return the latest update
# on plug-in reload.
#
import os
import sys
import json
print("Initialising Maya..")
import pymel.core
from maya import cmds
cmds.loadPlugin('AbcImport', quiet=True)
paths = {paths} # Provided at run-time
for path in paths:
path = os.path.realpath(path)
assert os.path.isdir(path)
for alembic in os.listdir(path):
alembic = os.path.join(path, alembic)
if not alembic.endswith(".abc"):
continue
cmds.file(new=True, force=True)
print("Importing %s" % alembic)
cmds.AbcImport(alembic,
mode="import",
fitTimeRange=True,
setToStartFrame=True)
# Sanity check
for node in cmds.ls(type="AlembicNode"):
print("%s.startFrame: %s" % (node, cmds.getAttr(node + ".startFrame")))
wrapper = os.path.splitext(alembic)[0] + ".ma"
wrapper = os.path.join(path, wrapper).replace("\\", "/")
print("Exporting to %s" % wrapper)
cmds.file(wrapper,
exportAll=True,
force=True,
type="mayaAscii",
constructionHistory=True)
print("Exported successfully")
# Unless we explicitly exit, the process may
# throw a SegmentationFault.
sys.exit(0)
"""
@contextlib.contextmanager
def temp_file(source):
tempdir = tempfile.mkdtemp()
temppath = os.path.join(tempdir, "source.py")
try:
with open(temppath, "w") as f:
f.write(source)
yield temppath
finally:
shutil.rmtree(tempdir)