Best place to do version conversion for scenes and assets
-
I have a couple of MaterialData plugins that have input ports/pins that have changed in functionality. In order to make old scenes/materials work, I need to insert a ShaderData plugin inbetween the existing MaterialData port and whatever ShaderData is already connected to that port.
The documentation seems to suggest that versioning should be done at the NodeData::Read function, however this does not seem to be the right place as the gelistnode graph does not seem to be guaranteed to be fully instatiated when this function is called - which makes it a bad fit for changing the graph.
Aside from that I cannot find where I am supposed to do this type of version conversion.
-
Hey @ECHekman,
Thank you for your question. This is a tricky one. When
NodeData::Readis emitted, Cinema 4D is currently reading a file and in the process of deserializing your node; so it indeed is not yet 'fully instantiated', as that is the whole point of the method. You are here not meant to manipulate the scene graph (the node is not yet attached), but read and store data on your plugin hook. I.e., you are supposed to do something with yourMyMaterialDataand not theGeListNode/BaseMaterialwhich is being passed in as the first argument ofRead.The common workflow is to read data from the
HyperFilewhich is passed in and store it on yourNodeDatainstance. Passed in is also the important version number (which is called for some odd reasondisklevel) of yourHyperFilecontainer.As always, you are bound to the main thread for scene graph manipulations. So,
NodeData::Initis not a good candidate when wanting to poke around in the scene graph, as it can be called off main thread and on dettached dummy nodes. A good approach is to hook intoNodeData::Messageand listen for MSG_DOCUMENTINFO to catch a document just having been loaded. This is for your specific case of wanting to manipulate nodes which have been deserialized. If you want to manipulate node instantiation,MSG_MENUPREPAREis a god choice. But it is only called for nodes which have been instantiated from direct user interactions such as a menu click. So,MSG_MENUPREPAREis not being emitted for nodes loaded from a file.The drill to do what you want to do would be:
- [optional] Overwrite
NodeData::Read/Write/CopyToto read, write, and copy custom data, and possibly use/detect different disk levels to catch different versions of a node type being loaded. You would have to match this with incrementing the disk level in your RegisterMaterialPlugin call, so that there are old and new versions of your material type out there. - Hook into the document being loaded, check the scene state, and possible data left behind for you by
NodeData::Readand::Init. - Manipulate the scene graph to your liking.
Cheers,
Ferdinand - [optional] Overwrite