How to detect a document switching?
-
Hi there,
I'm trying to find a way to detect in a Python plugin a document change when I'm switching between different document in C4D. The switch do not concern file open, then close, and open an other document, but really having 2 or 3 different scenes opened at the same time and switching from one to an another.
I went through the different post here, but I didn't found anything relevant, only few tracks, and also some C++ examples but they have some functions that are not existing in Python (ie
GeDialog::CheckCoreMessage()
). The best example I found is in C++ there : https://developers.maxon.net/docs/cpp/2023_2/page_manual_gedialog.html#page_manual_gedialog_interaction_global_events
But the scope ofEVMSG_CHANGE
is too wide and appears for many operations and not only windows/doc switching.I tried to trace the msg IDs inside CoreMessage(), but I didn't found the correspondance for the IDs that I traced in console.
For example I'm getting this when switching between opened documents:
Python extract for the CoreMessage call,
def CoreMessage(self, id, msg): doc = c4d.documents.GetActiveDocument() # if id == c4d.EVMSG_CHANGE: if msg.GetId() != 1298360653: print ( f"COREMSG_ID {msg.GetId()}" )
In console,
COREMSG_ID 1937337955
I'm skipping the
COREMSG_ID = 1298360653
otherwise I'm filing the console in a blink of an eye - it's maybe the redraw or evaluate scene.I tried to explore the
ge_prepass.h
file but didn't found any match. Where are located those ID Core Message definitions and their related readable values?That would helps me to found the right ID message called when switching.
Then, I thought analyse the
doc.GetDocumentName()
once I do know that I effectively switch from a document to an another.If someone have some answers, just let me know, it would be really helpful!
Thanks!
Christophe -
Hi @mocoloco, this topic was discussed not so long ago in Modifying Scene On First Open or Before Save?. But this involve SceneHook which are only possible in C++.
The best way in Python would be to create a MessageData plugin with a Timer and check if the active document changed. Relying on the Document Name is indeed a bad idea since unsaved document, are all unnamed. Find bellow a MessageData checking for the document change.
class TimerMessage(c4d.plugins.MessageData): @property def activeDoc(self): doc = getattr(self, '_activeDoc', None) if doc is None: return None # Check if we don't have a dead reference if not doc.IsAlive(): del self._activeDoc return None return doc @activeDoc.setter def activeDoc(self, value): if not isinstance(value, c4d.documents.BaseDocument): raise TypeError("value is not a c4d.documents.BaseDocument.") self._activeDoc = value def GetTimer(self): return 500 def CoreMessage(self, id, bc): if id == c4d.MSG_TIMER: activeDoc = c4d.documents.GetActiveDocument() if activeDoc is None: return if activeDoc != self.activeDoc: oldDoc = self.activeDoc self.activeDoc = activeDoc print("Document Changed") return True
Cheer,
Maxime. -
Thanks a lot @m_adam for this detailed answer. I missed that post about the SceneHook method in C++ - as our main plugin is already in C++, maybe we can incorporate this SceneHook inside it instead of having a perpetual running timer checking for a scene change in Python.
Are you aware if there some example somewhere in the SDK talking about this?
Cheer,
Christophe -
Hi there is no special documentation about SceneHook. It's like an object, but instead you register an SceneHookData with RegisterSceneHookPlugin.
For more information about MSG_DOCUMENTINFO find an example in Notification on change of active document.
Cheers,
Maxime. -
Hello @mocoloco,
without further questions or replies, we will consider this topic as solved by Monday, the 30th and flag it accordingly.
Thank you for your understanding,
Ferdinand