Solved Update Render Path in an Xpresso Node

Follow up from Start render in PictureViewer at the moment when a certain file has changed

Sorry about my wording. There are two Problems for me: First i'm not that good in english, second i'm not a programmer. Thats not very ideal base to get this done, i know 🙂 . This in mind, i'm pretty happy to get some help from you guys.

Back to the issue:
If the renderer is startet by the solution of maxime (above) the renderoutput path can't be set by a node?! I recon this, cause i've read somewhere, that the renderpath can't be changed while rendering is ongoing.

So the renderoutput path should be set before the Plugin from Maxime starts the renderer. That means (when i'm right) the path should be set by the same Plugin that also starts the renderer, just before it starts it. That's the reason why i'm trying to set the Path there (in the Plugin) and not in a node.

Do i have a wrong idea with this? The Node isn't executet before the render starts, right? That's why my Path isn't changing...


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:
import c4d

# Make sure to have an Unique ID from
PLUGIN_ID = 1000001

class MyMessagePlugin(c4d.plugins.MessageData):
	def CoreMessage(self, id, msg) :
		if id == PLUGIN_ID:

			# Render the document if there is not actually another render running
                # Compute the change we have made)

                # Render the current active document
		return True

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.


Hi Maxime,

Thanks again a lot 🙂
I just needed to replace the part in the python-node where you newly written how the path is being generated by my own Path-String-generation-algorythm which is builded from the content of the file watched.
Sure, it's the risky way, as you mentioned it, but it works for this time.