SOLVED Creating a 'Reload Image' button

I have a python Generator with a Texture path in its UserData.

I place a photoshop file in my texture path and I want to reload the shader image every time I make a change to the photoshop file. How can I recreate the 'Reload Image...' button (see pic) to refresh the shader? Thanks mates for any thoughts.
Screen Shot 2019-11-19 at 12.21.34 AM.png


as always, please use the Q&A system to mark your post as a question.

just to be sure: do you have a "Texture Path" parameter or a "shader" parameter in your user data?

Cinema does some image caching, so it seems that only the BitmapShader really knows how to re-load that image.

You can simply add a user data button to the Python Generator. In the generator, you can implement a message() function to check when the button was pressed (you find an related example here: Creating a material and applying to BaseObject within Python Generator😞

def message(id, data):
        buttonId = data['id']

        # check button ID 1
        if buttonId[1].id == 1:
            print("button pressed")

Now you can use CallButton() to press the "Reload Image..." button of the shader

            # assume user data parameter 4 is a shaderlink with a BitmapShader
            texID = [c4d.ID_USERDATA, 4]

            bitmapShader = op[texID]
            c4d.CallButton(bitmapShader, c4d.BITMAPSHADER_RELOADIMAGE)


best wishes,

Thank you @s_bach The button is working great. However I'm getting the following error for this line:

c4d.CallButton(bitmapShader, c4d.BITMAPSHADER_RELOADIMAGE)

RuntimeError: illegal operation, invalid cross-thread call

Yikes, sounds serious. Maybe I need to stop the threads?

To be more clear I am using a Texture path in my user data.

Alternatively, there must there must be a way to empty the cache on the Texture Path and then load the image again.


You have to ensure that you are in the main thread when invoking c4d.CallButton(). You can use c4d.threading.GeIsMainThread() for that. It seems that c4d.MSG_DESCRIPTION_COMMAND is not being sent from the main thread (to my suprise). Are you using the code provided by @s_bach ?


Ok, I was trying to call this from def main(): calling from def message(id, data):
is working! Thank you for the help!


if in doubt, one can always call c4d.StopAllThreads() before editing the active document from some user interaction in the main thread. This call will terminate other threads that may also currently use the active document (e.g. viewport rendering).

best wishes,