Hi, so for other people as a starting point I've taken the same code than I posted in the previous topic.
With that's said, there are multiple issues in the previous code that leads to the inability to change the render path.
First, you are in a threading environment meaning, that some other stuff in the scene may occur at the same time, so you shouldn't change the scene structure since you can corrupt it. But you can still do it at least Cinema 4D let you do this, but as said do it at your own risk, as it can screw up the scene. But sometimes there is no real other solution and scene corruption are really unlikely to happen but could happen.
Secondly the on_modified is a callback. So internally, it's most likely, that python will compile this python object (the function) and simply call it when needed as an independent object (in our case when something modifies the file). But due to the nature of how BaseList2D links are handled in python, you can face that the internal object changed (it's the case for the undo system, see NodeData Management) but you still refer to the older object. And to add on top of that the python GvNode is also a BaseList2D, meaning the things that own everything also have this behavior.
And finally in some case when Python own the BaseLisr2D its even worth since you have a Python object referring to this object, Cinema 4D will not delete it, as long as Python delete it.
So long story short:
- You are in a threaded environment. See Threading Information.
- You register a callback at a given time that may reference an object that does not exist anymore.
So to handle everything correctly is really tricky, and not possible to have clean thing from a python xpresso Node.
So is it mandatory? Cause a tag plugin could work way easier and in a cleaner way.
However I've done a few changes in the file, you can have the updated version here: monitoring.c4d
- In the python node, I node retrieve the path from the Xpresso User data.
- I've also added a Checkbox displayed as a button in this Xpresso User Data in order to reset the callback (if you modify the code, press the reset button, while it will not modify the existing one, as said in case of undo, BaseList2D are moved, meaning they are still stored somewhere in the memory so the python scope for the copied Xpresso tag still exists, so the Observer as well, meaning that it's got triggered as well, and since they are all triggered in the same time but only one can render, it may happen that you don't see the actual change. In this case, save the scene restart c4d.).
- I update the render path according to the filename. As said previously while Cinema 4D lets you do this, do this at your own risk.
- And finally, I changed Message to trigger an update event (so the change we made previously in the render path from our GvNode) is computed and then render the scene. Find the updated version below:
# Make sure to have an Unique ID from https://plugincafe.maxon.net/c4dpluginid_cp
PLUGIN_ID = 1000001
def CoreMessage(self, id, msg) :
if id == PLUGIN_ID:
# Render the document if there is not actually another render running
if not c4d.CheckIsRunning(c4d.CHECKISRUNNING_EXTERNALRENDERING):
# Compute the change we have made)
# Render the current active document
if __name__ == "__main__":
c4d.plugins.RegisterMessagePlugin(PLUGIN_ID, "MyMessagePlugin", 0, MyMessagePlugin())
So I really encourage you to creates a plugin instead of using python xpresso node. Unfortunately, we are are not here to develop for you, and as you a are a pure beginner it's not an easy task, and I already spent a lot of time in your problem.
But if you need help to creates a plugin no issue at all. You can find an example in the Github Repository.
By making a plugin you will be able to create a singleton observer, this way it will be really a global variable, and constant over time. So no more issue with double registered Handler.