[Maya] Differientiating between "File Save" and "File Save As" in a callback

We have special behavior that is applied during a “Save As” operation that is not applied during a “Save”.
Basically we store meta data inside our Maya files (GUIDs) that should not be present in multiple files.

Thus when an artist tries to save a copy of a file, we clear the meta data during the Save As operation. We hooked our custom code in by overriding the defaultRunTime command for File_SaveAs, but this approach is an ugly hack and I would like to use one of the MEventMessage or MSceneMessage callbacks.

However, there doesn’t seem to be a way to determine if the user is Saving or using Save As. In fact, the documentation makes it clear the events trigger for both operations.

Anyone got a pro tip on how to distinguish between a regular Save and Save As operation?

you’d have to use the kBeforeSave and kAfterSave events and somehow track the filenames between the steps. globals seems dirty as well as a temp file. Off the top of my head im not sure how else you’d persist the data between the two callbacks.

You might try to save another bit of data saying “my last saved name is”, and then trigger if the save name does not match that. It won’t match on the first save, or after a saveAs.

This seems to work, thoughts? Any holes I might’ve missed?

import os
import maya.OpenMaya as om

def _cacheFilename():
    fn = os.path.normpath(cmds.file(q=True, sn=True))
    cmds.fileInfo('filename', fn)

def _isFileSame():
    cachedName = cmds.fileInfo('filename', q=True)
    if not cachedName:
        _cacheFilename()
        return False
    cachedName = os.path.normpath(cachedName[0])
    fn = os.path.normpath(cmds.file(q=True, sn=True))
    if cachedName != fn:
        return False
    return True

def saveAsCallback(_):
    if not _isFileSame():
        pass # do work here...

Just realized that this will not work like I had hoped…
to get the new name cached into the new file, I need to call save again… otherwise the copy of the file carries the original name with it.

ok, round two.
it appears you can get access to the new name with kBeforeSave, so this seems to work:


import os
import maya.OpenMaya as om

def _cacheFilename():
    fn = cmds.file(q=True, sn=True)
    if fn:
        fn = os.path.normpath(cmds.file(q=True, sn=True))
        cmds.fileInfo('filename', fn)

def _isFileSame():
    cachedName = cmds.fileInfo('filename', q=True)
    if not cachedName:
        _cacheFilename()
        return False
    
    cachedName = os.path.normpath(cachedName[0])
    fn = os.path.normpath(cmds.file(q=True, sn=True))
    if cachedName != fn:
        _cacheFilename()
        return False
    return True

def saveAsCallback(_):
    if not _isFileSame():
        print 'Save As Operation Detected...'

om.MSceneMessage.addCallback(om.MSceneMessage.kBeforeSave, saveAsCallback)

This will trigger on Saving an Untitled File, Save As, but also the first time a filed, since the cache isn’t primed.

I supposed I could cache the file name using kAfterOpen…


def afterOpenCallback(_):
    _cacheFilename()

om.MSceneMessage.addCallback(om.MSceneMessage.kAfterOpen, afterOpenCallback)

This handles the files that already exist without the cached data.
when they are opened the name is cached. this prevents the Save As behavior the first time a file is saved to itself.