Thank you for reaching out to us. Before proposing practical solutions, we should clarify the exact task, as your initial posting is there sending mixed messages at least for me. There are two options:
- Detect that a document has been closed. This approach is unable to modify the document before it is being closed (or gather data on it without reloading the document).
- Detect that a document is in the process of closing. This implies the ability to carry out 'last minute actions' on the document before it actually closes.
Option one is relatively easy to do: Just implement a message data plugin or something else like dialog that provides a timer method and periodically check the list of active documents and cache the information in that list in some form. When the list then does differ on a timer call from its cache state, you know that these documents have been closed since the previous call. This is probably what you are already doing and referring to with 'counting documents'.
Option two requires the node/plugin message system and the message
MSG_DOCUMENTINFO_TYPE_REMOVE of the message family
MSG_DOCUMENTINFO as pointed out by @fwilleke80 (thanks!). As you have already discovered yourself, you will need some form of
NodeData implementation for that, and that in C++ the obvious candidate for that is a
SceneHookData. But there are other node types you can hook into in Python. But be aware that at least
c4d.plugins.PreferenceData will not work for sure in this context (because I tried myself in the past), and I think
SceneLoaderData will work neither. The reason is that not all node/plugin messages are being broadcasted to all node types. The C++ documentation sometimes hints at that in message descriptions but is far from complete in this regard. But you will be able to use
TagData in this fashion. So, the plan would be:
- Still have Option 1 to detect new documents being opened.
- Insert a custom
MyObjectData into the document and hide the node.
- When the document is being closed,
MyObjectData.Message will be invoked.
- Carry out what you want to carry out.
- Remove the node for
MyObjectData from the document (so that installations without the plugin can still load it properly).
Which is a lot of work and is also a bit dicey in point five. As it does rely on
MyObjectData.Message always being called on the main-thread in this context (or alternatively would have to ignore main-thread restrictions).
If you are only after option one, then a message data plugin or just a timer method in your dialog is the best way, even in C++ IMHO. If you are after option two, I frankly do not see a satisfactory solution. If you are after option two, it might be interesting for our users what workaround you did find, since at least I have no idea other than the proposed one to navigate around the problem.