USoftSubdiv — exporting an Alembic cache from Maya
==================================================

These tools export an Alembic (.abc) cache from Maya that USoftSubdiv can read
in Unreal Engine with your material names intact.

They are Maya-side Python only. They need no USoftSubdiv licence and no Unreal
Engine installation, so they can be handed to an animator on their own. The
same files ship inside the plugin package under MayaContent/usoftsubdiv and as
a separate download at:

    https://license.usoftsubdiv.com/downloads/USoftSubdiv-MayaTools.zip


1. WHY A SEPARATE TOOL IS NEEDED
--------------------------------

Maya writes material assignments into an Alembic cache only where the material
was assigned to individual faces — a "face set". A material assigned to a whole
object never reaches the .abc file.

This is a limitation of the export, not a setting. Turning on "Write Face Sets"
does not change it, and neither does selecting every face and re-assigning the
material: Maya folds that back into an object-level assignment.

So before exporting, this tool writes a string attribute named usoftMaterial on
each mesh, holding the name of its shading group. USoftSubdiv reads that
attribute and groups meshes into material slots.

Order of preference: face set, then usoftMaterial, then the mesh name. Where
Maya already recorded the material correctly, the attribute is ignored.

Exporting without the attribute still works, but every mesh becomes its own
material slot named after the mesh. On a real character, 18 meshes produced 19
slots without the tool and 5 with it.


2. INSTALL
----------

RECOMMENDED: DRAG AND DROP

1. Extract USoftSubdiv-MayaTools.zip into any folder. Do not drag a file out
   of a zip viewer without extracting first -- install.py needs the
   usoftsubdiv folder next to it on disk, and a zip viewer does not put it
   there.
2. Drag install.py from that extracted folder into the Maya viewport.
3. A dialog reports what was installed and where. The USoftSubdiv shelf
   button (this tool) appears on a shelf tab named USoftSubdiv.

This tool has a separate, unrelated sibling -- the Reference Finder, which
repaths broken rig references and has nothing to do with subdivision. It
ships as its own download, USoftSubdiv-ReferenceFinder.zip, installed the
same drag-and-drop way. If you extract that archive's install.py next to
this one's usoftsubdiv folder -- for instance because you unpacked both
zips into the same folder -- dragging either install.py installs both
tools; each installer only ever installs what it finds beside itself.

Re-running install.py, for example after unzipping a newer version, replaces
the existing install, so it doubles as the updater.

FALLBACK: MANUAL INSTALL

If drag-and-drop is blocked in your setup, install by hand instead:

1. Copy the usoftsubdiv folder into your Maya scripts directory, usually:

       Documents/maya/scripts/

   Copy the whole folder -- the icons subfolder provides the shelf button image.

2. In Maya's Script Editor, select the PYTHON tab -- not the MEL tab -- and run:

       import usoftsubdiv
       usoftsubdiv.install_shelf()

   A line reading "# Result: True #" confirms it worked.

   If you see neither a result nor an error, you are on the MEL tab. That is
   the usual cause of "nothing happened": Python typed into the MEL tab fails
   silently, printing no error and no result. Switch to the Python tab and run
   it again.

3. A shelf tab named USoftSubdiv appears, with the export button on it. The tab
   is written into your Maya preferences, so it is still there after a restart.

   Re-installing replaces the button rather than adding a second one. Older
   versions put the button on the Custom shelf; that old button is removed
   automatically.


3. EXPORTING
------------

1. Select the meshes you want to export.
2. Press the USoftSubdiv shelf button.
3. Set the file path and the frame range. The frame range defaults to the
   scene's playback range.
4. Press "Tag + Export Selection".

The Script Editor reports how many meshes were tagged and how many were
skipped.

You can select a group and its meshes together — the tool filters the selection
down to the meshes and drops anything whose ancestor is already included.


4. WHICH MESHES GET TAGGED
--------------------------

  * One material on the whole object
        Tagged. This is exactly the case Maya does not write into the .abc.

  * Mixed: one material on the object, another on some faces
        Tagged with the object-level material's name. The per-face assignment
        travels on its own as a face set.

  * Several materials, all assigned per face
        Skipped. Every face is already covered by a face set, so there is
        nothing for the attribute to add.

  * No material at all
        Skipped. There is no name to write, and Unreal falls back to the mesh
        name.

A mesh with a single material is tagged whether that material sits on the
object or on its faces. That is deliberate: the most common case should not
depend on which internal form Maya happened to use. It does no harm, because
the plugin only reads the attribute for faces no face set covers.

A skipped mesh is not an error. But "tagged 0" means the selection was wrong,
or that every selected mesh was already assigned per face.


5. THINGS WORTH KNOWING
-----------------------

  * Tagging modifies the scene — on a referenced rig, as a reference edit.
    The whole tagging pass is a single undo block, so one Ctrl+Z reverts it no
    matter how many meshes were involved, and that holds even if the export
    itself then fails.

  * You do not need to save the rig. Tagging runs again on every export.

  * Tagging and exporting are one action on purpose. If tagging were a separate
    step, an artist who changed a material and forgot to re-tag would ship a
    cache carrying the old name — a silently wrong answer, which is worse than
    no answer.

  * Change a material and the next export updates the attribute by itself.

  * Namespaces are stripped: charA:Body_SG is written as Body_SG.

  * After changing materials and re-exporting, re-cook the cache in Unreal.
    Material slots are written at cook time, so an existing cooked asset keeps
    the old slots until you cook it again.

  * Frames between two cache samples are blended, so the surface keeps moving
    within a frame. This is what lets Movie Render Queue produce motion blur
    with more than one temporal sample. Turn "Interpolate Frames" off on the
    component for a deliberately stepped look, or to save render time on a
    heavy asset -- each sub-sample evaluates its own cage.


6. WHERE TO PUT THE .abc FILE
-----------------------------

USoftSubdiv does not import the cache as an Unreal asset. The file stays on
disk and the cage points are read from it every frame, so where the file lives
matters as much as where the asset lives.

Put it inside the Unreal project. Anywhere under the project folder works —
there is no required structure — and the recommended place is:

    <YourProject>/AlembicSource/

When the file is under the project, the asset stores the path relative to the
project (AlembicSource/Sherzod/S50.abc) instead of an absolute disk path
(D:\...). The plugin creates the AlembicSource folder on the first Alembic
cook, and the cook dialog's "Choose an Alembic cache" picker opens there, so
keeping caches in it saves navigation on every later cook. The folder is not
created in projects that never use Alembic.

A relative path buys two things:

  * Moving the project to another machine — by copying or zipping the folder —
    keeps the asset working, because the path does not depend on a drive letter
    or on where the project sits.

  * Unreal's Migrate tool carries the .abc along with the asset (see below).

A cache outside the project still works. The path is simply stored absolute, as
before. What you lose is portability and the automatic copy during Migrate.

LETTING THE COOK DIALOG DO IT

If you pick a cache that lives outside the project, the cook dialog shows a
checkbox reading "Copy cache into the project", with the destination path
underneath it. It is ticked by default, and it appears only when there is
something to copy — choose a file already inside the project and the row is
hidden entirely.

The copy lands in AlembicSource/<name of the folder the cache came from>/, so
two characters exported as output.abc from folders named after them do not
overwrite each other. If a file is already there, an identical one is passed
over silently and a different one raises the conflict dialog described below.

DO NOT PUT IT IN Saved/

Saved/ is Unreal's scratch directory. It is the target of the most commonly
recommended troubleshooting step ("delete Saved and Intermediate"), it is
usually in .gitignore, and cleanup scripts empty it first.

Keeping the only copy of a source cache there means keeping it somewhere it is
expected to be deleted. The moment someone runs the usual clean-and-rebuild,
every Alembic mesh in the project goes quietly empty.

Nothing in the code forbids it — Saved/ is under the project, so the path is
still relative and it still works. This is advice, not a rule.


7. WHAT MIGRATE DOES
--------------------

When an Alembic-sourced asset is migrated to another project:

  * A cache inside the project is copied automatically, to the same relative
    place in the destination (AlembicSource/Sherzod/S50.abc stays
    AlembicSource/Sherzod/S50.abc). Intermediate folders are created as needed.
    When the migration finishes, the asset opens and animates with no extra
    step.

  * If several assets share one cache, the file is copied once.

  * The migration report may show messages like these:

        "Copied Alembic cache '...' to '...'."
            Copied successfully.

        "...sources its Alembic cache from outside the project, so Migrate
        could not carry it..."
            The file was outside the project. Nothing was copied.

        "...was not found..."
            The source file was not on disk, so there was nothing to copy.

        "Could not create the destination folder..." / "Could not copy..."
            The copy failed — disk space or permissions, for instance. The rest
            of the migration still proceeds.

  * One edge case: if you point Migrate at a plugin's internal Content folder
    rather than another project's main Content folder, the cache is not copied
    and the report says so. Migrate to the main Content folder as usual.

THE CONFLICT DIALOG: REPLACE OR KEEP EXISTING

If the destination project already holds a file of that name:

  * Byte-for-byte identical files raise nothing. The result is the same either
    way, so you are not asked.

  * Different files raise a dialog showing both files stacked — "Source (this
    project)" above "Already at the destination" — with the size and modified
    date of each. That is deliberate: whether these are an old and a new copy
    of one cache, or two different characters whose files happen to share a
    name, is something no automatic check can determine. You can, from the size
    and the date.

  * The buttons are Replace (overwrite the destination file), Keep existing
    (leave it alone and copy nothing), and Replace all / Keep all, which apply
    the same answer to every remaining conflict in this migration.

  * There is no Cancel. By this point the assets have already been written to
    the destination, so cancelling would leave the migration half-finished. If
    you want the safest answer, choose Keep existing — it destroys nothing.

  * In an unattended migration, such as one driven by a script, the dialog does
    not appear at all: Keep existing is chosen automatically and the report
    records a warning.


8. WHAT CAN STILL GO WRONG
--------------------------

  * A cache outside the project is not carried by Migrate. The report warns
    about it, and the destination machine has to be able to reach that absolute
    path (D:\Alembic_Exports\S50.abc) by itself. The only way to avoid this is
    to keep the file inside the project — or to re-cook it there, with the copy
    checkbox ticked, in the source project.

  * If the file cannot be found — not carried across, deleted, renamed or
    moved — the mesh draws nothing and one Error line is written to the Output
    Log. Lines from the plugin start with "OpenSubdivUE:", so search the Output
    Log for that.

    Drawing nothing is deliberate. If the plugin held the last known pose
    instead, a missing file would read as "the animation is broken", which
    sends you looking in the wrong place.


9. VERSION
----------

This guide ships with the Maya tools. The version of the tools you have is
recorded in usoftsubdiv/__init__.py as __version__; the standalone download
carries no version in its filename, so that link always serves the current
tools.
