Is it possible to run a command when saving in Maya?

Hello,

I’m wondering if there is any way to run a Python (or MEL) command every time that the user saves a scene.
I want the script to check something when saving the scene and give a heads up to the user if it’s necessary.

I know that I could add a couple of lines into the original MEL scripts in a folder like:

C:\Program Files\Autodesk\MayaXXX\scripts (XXXX being the version of Maya)

But I’d like to know if there is a another way to do that (Similar to the ‘Pre render MEL’ and ‘post render MEL’ when setting up a Render)

Thanks in advance,

Dave

You should be able to do that with ScriptJobs, yes?

there are a variety of ways to do this.

First, you can create your own function…

def mySaveScene():
    # do some stuff
    cmds.file(save=True)
    # do some more stuff

you can hotkey this to CTRL-S, however the File Menu option won’t call this, and the Status Bar icons won’t use it either.

Another way is to use Script Jobs, although you don’t have control over whether the script runs before or after the save operation. I don’t recall when Maya runs the script when a file is Saved.

Thirdly, you can copy the Save File MEL script from Autodesk’s folder and put in your local folder and edit that file, but I would discourage that approach.

Lastly, there is a concept in Maya of a “RunTimeCommand” - you can think of this as an alias to some code. It’s basically a layer that sits between Maya’s UI and the code it runs. RunTimeCommands are what you see when you go into the HotKey Editor and assign hotkeys to functions.

Maya has a default RunTimeCommand called “SaveScene”. If you could somehow edit that RunTimeCommand, you can alter Maya’s Save Scene function AND also update all Hotkeys, Shelf Buttons, Menus and Icons in one stroke.

However, default RunTimeCommands cannot be edited after they are created… so… what you can do is copy Maya’s “defaultRunTimeCommands.mel” file into your local folder and edit the “SaveScene” and “SaveSceneAs” runtime commands to perform your operations before and after and won’t have to worry up about updating the File Menu, Status Icon, Hotkeys, custom Shelf Buttons, etc.

I recently used this last approach to run a maya ascii file scrubber each time the file is saved.

You can use the api to add a variety of callbacks as well using MSceneMessage.addCallback()

Of interest in this case would be MSceneMessage.kBeforeSave and MSceneMessage.kAfterSave

Just happened to see that and while writing some save callbacks:

import maya.OpenMaya as OpenMaya

def do_stuff(*args):
print “I’m being run”

id = OpenMaya.MSceneMessage.addCallback(OpenMaya.MSceneMessage.kAfterSave, do_stuff)

I typically run some code at startup that hijacks the Save menu, icon, and CTRL-S like this:


import maya.cmds as mc
import maya.mel as mm

def install_custom_save_stuff():
    # no install if in batch mode
    if mc.about(batch=True):
        return
    # hijack save button
    mc.iconTextButton(u"saveSceneButton", edit=True, command='python("import yourstuff;yourstuff()")', sourceType="mel")
    # hijack save menu item
    mm.eval("buildFileMenu();") # new in Maya 2009, we have to explicitly create the file menu before modifying it
    mc.setParent(u"mainFileMenu", menu=True)
    mc.menuItem(u"saveItem", edit=True, label="Save Scene", command='import yourstuff;yourstuff()')
    # hijack CTRL-S named command
    mc.nameCommand(u"NameComSave_File", annotation="Your Custom Save", command='python("import yourstuff;yourstuff()")' )


We just edit a version of defaultRunTimeCommands.mel and put it in to our script path. This overrides Maya’s version with our own.

@oz there is no on save callback in mel/python, there is one in the API as in Sune’s post.

The API doesn’t have a mechanism to “cancel” the event does it? Depending on what you need to do, this does seem cleaner than the other various hijacking methods…

It does.

OpenMaya.MSceneMessage has two ways to add callbacks that can also cancel an operation:
addCheckCallback
addCheckFileCallback.

addCheckCallback works with a subset of the full list of Messages , and addCheckFileCallback works with a subset of addCheckCallback’s usable Messages.
See the API page for MSceneMessage for a full list of Messages that work with the different add*Callback methods (http://download.autodesk.com/global/docs/mayasdk2012/en_us/index.html?url=cpp_ref/class_m_scene_message.html,topicNumber=cpp_ref_class_m_scene_message_html)

The difference between those two is that addCheckFileCallback is passed an MFileObject which “is the MFileObject that will be acted on by the current file IO operation, any modifications to it will be passed back to Maya and change the file being acted on.”
In both cases the callback function is passed a refCode and clientData argument. If refCode is False when the function exits the operation is cancelled, if it is True the operation completes as normal. You should set the value of refCode using OpeneMaya.MScriptUtil.setBool(refCode, value).

import maya.OpenMaya as om

allow_save = False

def func(refCode, clientData):
    om.MScriptUtil.setBool(refCode, allow_save)
    
cb_id = om.MSceneMessage.addCheckCallback(om.MSceneMessage.kBeforeSaveCheck, func)

Thanks a lot for the replies! I will be using ‘defaultRunTimeCommands.mel’ as it seems to be a clean and reliable solution. :slight_smile: