Persisting and re-instantiating Python data from a Maya scene
Recently, I needed a tool/UI to be able to restore data for a particular Python class from a Maya scene. The immediately obvious solutions were to simply store all the class properties as individual attributes, or store a JSON string containing the class data on a single string attribute. For simple classes or data, this is probably the way to go. However, I had a complex object with nested classes and some Maya API objects. Using these methods would have required writing the logic to properly write out the data and ultimately read it back in while properly instantiating all the necessary classes/objects.
Thankfully, Python gives us the pickle module (https://docs.python.org/2/library/pickle.html) for serializing and de-serializing data back into the proper Python objects/classes. Ultimately, I ended up using an extension of the pickle module, dill (https://github.com/uqfoundation/dill), as it supports more complex data types. In the process, I found out that Maya API objects were not handled by either pickle or dill. Fortunately, there's a way around that! http://www.ctrl-shift-kill.com/2015/09/30/picked-points-in-python/. With this all in place, I was able to pickle the data, and save it as a base64 encoded string to a single string attribute on my node. Upon re-opening the scene, I can unpickle that data and have my proper Python object hierarchy restored. I'm curious what approaches others have taken for similar situations.
That's really cool! I've been looking into ways of pickling API mesh data and saving that to a file, but I couldn't find a way of doing that. It's a bit different from what that article shows, as I wanted to actually save the
MFnMesh
to a file and be able to load it back in.I haven't had to do any of this other than saving some simple dictionaries or lists into maya string attributes, but I can't see any other ways of doing it than what you already described. I know that the Tween Machine tool saves data as a hierarchy of transforms, but that I feel is a bit dirty. I suppose the same can be achieved by creating a network of network nodes just so it's not visible in the outliner, although it's still quite dirty.
I am curious to see other people's approaches.