Modifying Texture Path

On 27/05/2013 at 13:27, xxxxxxxx wrote:

I have a script that copies all of my texture files to a render farm. To do this, I am iterating through the BaseContainer object obtained from a call to BaseDocument.GetAllTextures(). This works perfectly to get all of the files and copy them down. However, I am racking my brain on trying to change the paths in the document so that the farm can see the moved textures. This is necessary because my artists almost never move the texture files into their project search path on import, and they are working off of a filesystem that cannot be mapped to the farm.

I have tried modifying the entries in the BaseContainer object using BaseContainer.SetFilename(), but this makes no changes to the document, only to the BC object in RAM. How do I update these paths with the new texture locations on the farm?

On 27/05/2013 at 14:41, xxxxxxxx wrote:

C4d can do that out of the box. 'Save Project With Assets' it will stomp all textures into a
tex folder in the dir of the c4d file. It will also modify all texture paths of the materials and 
shaders in your scene.

The reason why your script is not working is pretty simple, there is no such thing
as a global texture container in c4d. GetAllTextures() is just a helper method. You
have to iterate over each materials basecontainer / shaders basecontainer manually
if you do want to do in python.

On 27/05/2013 at 20:54, xxxxxxxx wrote:


Thanks for the info. I do know about the "Save Project With Assets" functionality. The script I'm working on is meant to be a one click submit to our farm, so I'm hoping to wrap in the save with assets functionality. I will explore the materials/shaders route.

On 19/06/2013 at 11:32, xxxxxxxx wrote:

markjam33, have you found a solution for this? I'm having the same issue here, I need to somehow adjust texture paths. The thing is, even if you loop through all Materials, there are still possible sub(sub-sub-sub...) shaders that could use a texture somewhere...

it's so annoying that there is no SetAllTextures() equivalent...

On 17/07/2016 at 03:53, xxxxxxxx wrote:

Hello, I am trying to do the same thing in Python code too. being able to effectively iterate through all the texture paths in the doc and change them.


On 18/07/2016 at 01:40, xxxxxxxx wrote:


can you share some information on what you want to achieve in the end? There are no build-in tools to iterate over all elements that might use textures or other assets.

The Python API offers GetAllAssets() and SaveProject(). The later could be used to prepare scene files for team rendering etc.

best wishes,

On 18/07/2016 at 03:26, xxxxxxxx wrote:

Hi Sebastian,

Thanks for the reply, I would like to be able to essentially prepare a scene file for command line usage (third party render manager) ie. Not Team Render. One thing I would like to do is globalise all texture names, in addition to appending to the filename string to every texture or asset filename.

As such, I would prefer to not package up the scene assets with the save project function, but rather I would like to leave them referenced using absolute paths instead. We often have textures stored elsewhere on our server.

So far I have been successful in iterating all material and object shaders hierarchies, filtering by the bitmap type. Kind of the long way, but it does work.

One thing I am unsure of though is how I might access other parameters like filenames in various other formats, eg plugin caches (eg. Xparticles, tdf etc.) or GI caches etc. I will still need to change all of these filenames before submission as well.

Does GetAllAssets() allow me access to third party assets like caches or gi caches etc?

I see it returns an ID number. Can I access these assets by id number and change them after I have processed the filnames?

Hope this makes sense.


On 18/07/2016 at 08:11, xxxxxxxx wrote:


GetAllAssets() should give access to all referenced assets (if the host object correctly implements the reaction to the relevant messages, so no guarantee can be given for third party plugins). If you want a list of all textures you could take a look at BaseDocument.GetAllTextures().

GetAllAssets() does not return an ID. It returns a dictionary containing the information on the assets.

Best wishes,

On 25/07/2016 at 20:58, xxxxxxxx wrote:

Hello again,

If i use GetAllAssets(), can I then make changes directly to this dictionary? Otherwise, how do I effectively go about setting the new amended filename?


On 26/07/2016 at 09:09, xxxxxxxx wrote:


GetAllAssets() just returns a list of all used assets. It does not change anything. I'm afraid there is no efficient way to change all filepaths other than to iterate over all elements of the scene and check for filename parameters.

Best wishes,

On 30/07/2016 at 16:24, xxxxxxxx wrote:

Hi a few weeks ago I create a script for translate all C4D Bitmap to OctaneBitmap.
For dat I iterate through all material and their link (Normally you could use GetDown/GetNext... but some render engine like Octane juste "yolo" and insert shader data in the same level as the parent...) It's for that I choose to iterate through any link.

Here is my script. The only knowed limitation is the no support of layer shader (since we can't dirrectly acces it in python maybe if in R17 some improvement are done it's still not that ^^)
The only thing you have to change is to import os and the changeTexture function . I guess it would be something like

def changeTexture(id,serverPath,enfantShader) :
    if enfantShader.CheckType(ID_C4D_BITMAP) :
	filename = os.path.basename(enfantShader[c4d.BITMAPSHADER_FILENAME])
	newPath = os.join(serverPath,filename)
	enfantShader[c4d.BITMAPSHADER_FILENAME] = newPath

You could probably optimize my code since you don't really care about knowing the parent and the child shader.

I hope it helped you 🙂