Skip to content

alembic

extract_alembic(file, attr=None, attrPrefix=None, dataFormat='ogawa', endFrame=None, eulerFilter=True, frameRange='', melPerFrameCallback=None, melPostJobCallback=None, noNormals=False, preRoll=False, preRollStartFrame=None, pythonPerFrameCallback=None, pythonPostJobCallback=None, renderableOnly=False, root=None, selection=True, startFrame=None, step=1.0, stripNamespaces=True, userAttr=None, userAttrPrefix=None, uvsOnly=False, uvWrite=True, verbose=False, wholeFrameGeo=False, worldSpace=False, writeColorSets=False, writeCreases=False, writeFaceSets=False, writeUVSets=False, writeVisibility=False)

Extract a single Alembic Cache.

This extracts an Alembic cache using the -selection flag to minimize the extracted content to solely what was Collected into the instance.

Parameters:

Name Type Description Default
file str

The filepath to write the alembic file to.

required
attr list of str

A specific geometric attribute to write out. Defaults to [].

None
attrPrefix list of str

Prefix filter for determining which geometric attributes to write out. Defaults to ["ABC_"].

None
dataFormat str

The data format to use for the cache, defaults to "ogawa"

'ogawa'
endFrame float

End frame of output. Ignored if frameRange provided.

None
eulerFilter bool

When on, X, Y, and Z rotation data is filtered with an Euler filter. Euler filtering helps resolve irregularities in rotations especially if X, Y, and Z rotations exceed 360 degrees. Defaults to True.

True
frameRange tuple or str

Two-tuple with start and end frame or a string formatted as: "startFrame endFrame". This argument overrides startFrame and endFrame arguments.

''
melPerFrameCallback Optional[str]

MEL callback run per frame.

None
melPostJobCallback Optional[str]

MEL callback after last frame is written.

None
noNormals bool

When on, normal data from the original polygon objects is not included in the exported Alembic cache file.

False
preRoll bool

This frame range will not be sampled. Defaults to False.

False
preRollStartFrame Optional[float]

The frame to start scene evaluation at. This is used to set the starting frame for time dependent translations and can be used to evaluate run-up that isn't actually translated. Defaults to None, meaning no pre-roll start frame will be used to roll from.

None
pythonPerFrameCallback Optional[str]

Python callback run per frame.

None
pythonPostJobCallback Optional[str]

Python callback after last frame is written.

None
renderableOnly bool

When on, any non-renderable nodes or hierarchy, such as hidden objects, are not included in the Alembic file. Defaults to False.

False
root list of str

Maya dag path which will be parented to the root of the Alembic file. Defaults to [], which means the entire scene will be written out.

None
selection bool

Write out all all selected nodes from the active selection list that are descendents of the roots specified with -root. Defaults to False.

True
startFrame float

Start frame of output. Ignored if frameRange provided.

None
step float

The time interval (expressed in frames) at which the frame range is sampled. Additional samples around each frame can be specified with -frs. Defaults to 1.0.

1.0
stripNamespaces bool

When on, any namespaces associated with the exported objects are removed from the Alembic file. For example, an object with the namespace taco:foo:bar appears as bar in the Alembic file.

True
userAttr list of str

A specific user defined attribute to write out. Defaults to [].

None
userAttrPrefix list of str

Prefix filter for determining which user defined attributes to write out. Defaults to [].

None
uvsOnly bool

When on, only uv data for PolyMesh and SubD shapes will be written to the Alembic file.

False
uvWrite bool

When on, UV data from polygon meshes and subdivision objects are written to the Alembic file. Only the current UV map is included.

True
verbose bool

When on, outputs frame number information to the Script Editor or output window during extraction.

False
wholeFrameGeo bool

Data for geometry will only be written out on whole frames. Defaults to False.

False
worldSpace bool

When on, the top node in the node hierarchy is stored as world space. By default, these nodes are stored as local space. Defaults to False.

False
writeColorSets bool

Write all color sets on MFnMeshes as color 3 or color 4 indexed geometry parameters with face varying scope. Defaults to False.

False
writeCreases bool

If the mesh has crease edges or crease vertices, the mesh (OPolyMesh) would now be written out as an OSubD and crease info will be stored in the Alembic file. Otherwise, creases info won't be preserved in Alembic file unless a custom Boolean attribute SubDivisionMesh has been added to mesh node and its value is true. Defaults to False.

False
writeFaceSets bool

Write all Face sets on MFnMeshes. Defaults to False.

False
writeUVSets bool

Write all uv sets on MFnMeshes as vector 2 indexed geometry parameters with face varying scope. Defaults to False.

False
writeVisibility bool

Visibility state will be stored in the Alembic file. Otherwise everything written out is treated as visible. Defaults to False.

False
Source code in client/ayon_maya/api/alembic.py
 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
def extract_alembic(
    file,
    attr=None,
    attrPrefix=None,
    dataFormat="ogawa",
    endFrame=None,
    eulerFilter=True,
    frameRange="",
    melPerFrameCallback=None,
    melPostJobCallback=None,
    noNormals=False,
    preRoll=False,
    preRollStartFrame=None,
    pythonPerFrameCallback=None,
    pythonPostJobCallback=None,
    renderableOnly=False,
    root=None,
    selection=True,
    startFrame=None,
    step=1.0,
    stripNamespaces=True,
    userAttr=None,
    userAttrPrefix=None,
    uvsOnly=False,
    uvWrite=True,
    verbose=False,
    wholeFrameGeo=False,
    worldSpace=False,
    writeColorSets=False,
    writeCreases=False,
    writeFaceSets=False,
    writeUVSets=False,
    writeVisibility=False
):
    """Extract a single Alembic Cache.

    This extracts an Alembic cache using the `-selection` flag to minimize
    the extracted content to solely what was Collected into the instance.

    Arguments:
        file (str): The filepath to write the alembic file to.

        attr (list of str, optional): A specific geometric attribute to write
            out. Defaults to [].

        attrPrefix (list of str, optional): Prefix filter for determining which
            geometric attributes to write out. Defaults to ["ABC_"].

        dataFormat (str): The data format to use for the cache,
                          defaults to "ogawa"

        endFrame (float): End frame of output. Ignored if `frameRange`
            provided.

        eulerFilter (bool): When on, X, Y, and Z rotation data is filtered with
            an Euler filter. Euler filtering helps resolve irregularities in
            rotations especially if X, Y, and Z rotations exceed 360 degrees.
            Defaults to True.

        frameRange (tuple or str): Two-tuple with start and end frame or a
            string formatted as: "startFrame endFrame". This argument
            overrides `startFrame` and `endFrame` arguments.

        melPerFrameCallback (Optional[str]): MEL callback run per frame.

        melPostJobCallback (Optional[str]): MEL callback after last frame is
            written.

        noNormals (bool): When on, normal data from the original polygon
            objects is not included in the exported Alembic cache file.

        preRoll (bool): This frame range will not be sampled.
            Defaults to False.

        preRollStartFrame (Optional[float]): The frame to start scene
            evaluation at.  This is used to set the starting frame for time
            dependent translations and can be used to evaluate run-up that
            isn't actually translated. Defaults to None, meaning no pre-roll
            start frame will be used to roll from.

        pythonPerFrameCallback (Optional[str]): Python callback run per frame.

        pythonPostJobCallback (Optional[str]): Python callback after last frame
            is written.

        renderableOnly (bool): When on, any non-renderable nodes or hierarchy,
            such as hidden objects, are not included in the Alembic file.
            Defaults to False.

        root (list of str): Maya dag path which will be parented to
            the root of the Alembic file. Defaults to [], which means the
            entire scene will be written out.

        selection (bool): Write out all all selected nodes from the
            active selection list that are descendents of the roots specified
            with -root. Defaults to False.

        startFrame (float): Start frame of output. Ignored if `frameRange`
            provided.

        step (float): The time interval (expressed in frames) at
            which the frame range is sampled. Additional samples around each
            frame can be specified with -frs. Defaults to 1.0.

        stripNamespaces (bool): When on, any namespaces associated with the
            exported objects are removed from the Alembic file. For example, an
            object with the namespace taco:foo:bar appears as bar in the
            Alembic file.

        userAttr (list of str, optional): A specific user defined attribute to
            write out. Defaults to [].

        userAttrPrefix (list of str, optional): Prefix filter for determining
            which user defined attributes to write out. Defaults to [].

        uvsOnly (bool): When on, only uv data for PolyMesh and SubD shapes
            will be written to the Alembic file.

        uvWrite (bool): When on, UV data from polygon meshes and subdivision
            objects are written to the Alembic file. Only the current UV map is
            included.

        verbose (bool): When on, outputs frame number information to the
            Script Editor or output window during extraction.

        wholeFrameGeo (bool): Data for geometry will only be written
            out on whole frames. Defaults to False.

        worldSpace (bool): When on, the top node in the node hierarchy is
            stored as world space. By default, these nodes are stored as local
            space. Defaults to False.

        writeColorSets (bool): Write all color sets on MFnMeshes as
            color 3 or color 4 indexed geometry parameters with face varying
            scope. Defaults to False.

        writeCreases (bool): If the mesh has crease edges or crease
            vertices, the mesh (OPolyMesh) would now be written out as an OSubD
            and crease info will be stored in the Alembic file. Otherwise,
            creases info won't be preserved in Alembic file unless a custom
            Boolean attribute SubDivisionMesh has been added to mesh node and
            its value is true. Defaults to False.

        writeFaceSets (bool): Write all Face sets on MFnMeshes.
            Defaults to False.

        writeUVSets (bool): Write all uv sets on MFnMeshes as vector
            2 indexed geometry parameters with face varying scope. Defaults to
            False.

        writeVisibility (bool): Visibility state will be stored in
            the Alembic file.  Otherwise everything written out is treated as
            visible. Defaults to False.
    """

    # Ensure alembic exporter is loaded
    cmds.loadPlugin('AbcExport', quiet=True)

    # Alembic Exporter requires forward slashes
    file = file.replace('\\', '/')

    # Ensure list arguments are valid.
    attr = attr or []
    attrPrefix = attrPrefix or []
    userAttr = userAttr or []
    userAttrPrefix = userAttrPrefix or []
    root = root or []

    # Pass the start and end frame on as `frameRange` so that it
    # never conflicts with that argument
    if not frameRange:
        # Fallback to maya timeline if no start or end frame provided.
        if startFrame is None:
            startFrame = cmds.playbackOptions(query=True,
                                              animationStartTime=True)
        if endFrame is None:
            endFrame = cmds.playbackOptions(query=True,
                                            animationEndTime=True)

        # Ensure valid types are converted to frame range
        assert isinstance(startFrame, ALEMBIC_ARGS["startFrame"])
        assert isinstance(endFrame, ALEMBIC_ARGS["endFrame"])
        frameRange = "{0} {1}".format(startFrame, endFrame)
    else:
        # Allow conversion from tuple for `frameRange`
        if isinstance(frameRange, (list, tuple)):
            assert len(frameRange) == 2
            frameRange = "{0} {1}".format(frameRange[0], frameRange[1])

    # Assemble options
    options = {
        "selection": selection,
        "frameRange": frameRange,
        "eulerFilter": eulerFilter,
        "noNormals": noNormals,
        "preRoll": preRoll,
        "root": root,
        "renderableOnly": renderableOnly,
        "uvWrite": uvWrite,
        "uvsOnly": uvsOnly,
        "writeColorSets": writeColorSets,
        "writeFaceSets": writeFaceSets,
        "wholeFrameGeo": wholeFrameGeo,
        "worldSpace": worldSpace,
        "writeVisibility": writeVisibility,
        "writeUVSets": writeUVSets,
        "writeCreases": writeCreases,
        "dataFormat": dataFormat,
        "step": step,
        "attr": attr,
        "attrPrefix": attrPrefix,
        "userAttr": userAttr,
        "userAttrPrefix": userAttrPrefix,
        "stripNamespaces": stripNamespaces,
    }

    # Validate options
    for key, value in options.copy().items():

        # Discard unknown options
        if key not in ALEMBIC_ARGS:
            log.warning("extract_alembic() does not support option '%s'. "
                        "Flag will be ignored..", key)
            options.pop(key)
            continue

        # Validate value type
        valid_types = ALEMBIC_ARGS[key]
        if not isinstance(value, valid_types):
            raise TypeError("Alembic option unsupported type: "
                            "{0} (expected {1})".format(value, valid_types))

        # Ignore empty values, like an empty string, since they mess up how
        # job arguments are built
        if isinstance(value, (list, tuple)):
            value = [x for x in value if x.strip()]

            # Ignore option completely if no values remaining
            if not value:
                options.pop(key)
                continue

            options[key] = value

    # The `writeCreases` argument was changed to `autoSubd` in Maya 2018+
    maya_version = int(cmds.about(version=True))
    if maya_version >= 2018:
        options['autoSubd'] = options.pop('writeCreases', False)

    # Only add callbacks if they are set so that we're not passing `None`
    callbacks = {
        "melPerFrameCallback": melPerFrameCallback,
        "melPostJobCallback": melPostJobCallback,
        "pythonPerFrameCallback": pythonPerFrameCallback,
        "pythonPostJobCallback": pythonPostJobCallback,
    }
    for key, callback in callbacks.items():
        if callback:
            options[key] = str(callback)

    # Format the job string from options
    job_args = list()
    for key, value in options.items():
        if isinstance(value, (list, tuple)):
            for entry in value:
                job_args.append("-{} {}".format(key, entry))
        elif isinstance(value, bool):
            # Add only when state is set to True
            if value:
                job_args.append("-{0}".format(key))
        else:
            job_args.append("-{0} {1}".format(key, value))

    job_str = " ".join(job_args)
    job_str += ' -file "%s"' % file

    # Ensure output directory exists
    parent_dir = os.path.dirname(file)
    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)

    if verbose:
        log.debug("Preparing Alembic export with options: %s",
                  json.dumps(options, indent=4))
        log.debug("Extracting Alembic with job arguments: %s", job_str)

    # Perform extraction
    print("Alembic Job Arguments : {}".format(job_str))

    # Disable the parallel evaluation temporarily to ensure no buggy
    # exports are made. (PLN-31)
    # TODO: Make sure this actually fixes the issues
    with evaluation("off"):
        cmds.AbcExport(
            j=job_str,
            verbose=verbose,
            preRollStartFrame=preRollStartFrame
        )

    if verbose:
        log.debug("Extracted Alembic to: %s", file)

    return file