THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 29/12/2007 at 13:10, xxxxxxxx wrote:
There isn't a direct SDK method to do this (SaveDocument() doesn't consider this). CallCommand(12255) might work. You can get the ID of commands by opening the Command Manager (Windows:Layout:Command Manager) and selecting the command.
What I do to make textures relative is first copy them relative to the document (it MUST have been saved first to have a valid path reference to it!), then you need to do the following:
> // CMD: Copy Image Maps to Scene Folder
> //*---------------------------------------------------------------------------*
> BOOL CopyImageMaps(BaseDocument* activeDocument, AtomArray* atomArray, Filename projectPath, BOOL clearSelection)
> //*---------------------------------------------------------------------------*
> {
> if (!atomArray) return FALSE;
>
> LONG cnt = GetSelectedWithTextures(activeDocument, atomArray);
> // if nothing selected, consider entire document
> if (!cnt)
> {
> AppendPolygonObjects(activeDocument, atomArray, activeDocument->GetFirstObject());
> cnt = atomArray->GetCount();
> if (!cnt) return TRUE;
> }
>
> String* stringArray = bNew String[1024L];
> LONG index = 0L;
> Filename texpath;
> texpath = activeDocument->GetDocumentPath();
> // Get C4D Document folder or Project texture folder
> if (texpath.Content()) texpath += Filename("Tex");
> else texpath = projectPath.GetDirectory()+Filename("Tex");
> if (!GeFExist(texpath)) GeFCreateDir(texpath);
>
> BaseObject* obj;
> BaseTag* tag;
> TextureTag* ttag;
> GeData data;
> Material* mat;
> //for (LONG i = 0; i < cnt; i++)
> for (LONG i = cnt; i--; )
> {
> obj = static_cast<BaseObject*>(atomArray->GetIndex(i));
> if (!obj->IsInstanceOf(Opolygon)) continue;
> // - Copy maps for selected Object
> for (tag = obj->GetFirstTag(); tag; tag = tag->GetNext())
> {
> if (!tag->IsInstanceOf(Ttexture)) continue;
> ttag = (TextureTag* )tag;
> ttag->GetParameter(DescID(TEXTURETAG_MATERIAL), data, NULL);
> mat = static_cast<Material*>(data.GetLink(activeDocument, Mbase));
> if (!mat) continue;
> // Color
> CopyAndSetTexture(mat->GetChannel(CHANNEL_COLOR), texpath, stringArray, &index;);
> // Specular Color
> CopyAndSetTexture(mat->GetChannel(CHANNEL_SPECULARCOLOR), texpath, stringArray, &index;);
> // Bump
> CopyAndSetTexture(mat->GetChannel(CHANNEL_BUMP), texpath, stringArray, &index;);
> // Environment
> CopyAndSetTexture(mat->GetChannel(CHANNEL_ENVIRONMENT), texpath, stringArray, &index;);
> // Alpha
> CopyAndSetTexture(mat->GetChannel(CHANNEL_ALPHA), texpath, stringArray, &index;);
> // Luminance
> CopyAndSetTexture(mat->GetChannel(CHANNEL_LUMINANCE), texpath, stringArray, &index;);
> #ifdef C4D_R9
> // Displacement
> CopyAndSetTexture(mat->GetChannel(CHANNEL_DISPLACEMENT), texpath, stringArray, &index;);
> #endif
> mat->Update(TRUE, TRUE);
> mat->Message(MSG_CHANGE);
> }
> }
> if (clearSelection) DeselectObjects(atomArray);
> if (stringArray)
> {
> CopyImageMapsInfoDialog cimiDialog;
> cimiDialog.Init(stringArray, index, texpath.GetString());
> String title = GeLoadString(IPPS_COPYMAPS_DONE)+" ""+texpath.GetString()+""";
> cimiDialog.Open(-1L,-1L, SizeChr(title.GetLength())*7L, 320L);
> bDelete(stringArray);
> }
> else MessageDialog(GeLoadString(IPPS_COPYMAPS_DONE)+"\n""+texpath.GetString()+""");
> if (index) SaveDocument(activeDocument, activeDocument->GetDocumentPath()+activeDocument->GetDocumentName(), TRUE, FORMAT_C4DEXPORT);
> return TRUE;
> }
> // Copy Material image and set Texture image name
> //*---------------------------------------------------------------------------*
> void CopyAndSetTexture(BaseChannel* bchan, Filename texpath, String* stringArray, LONG* index)
> //*---------------------------------------------------------------------------*
> {
> if (!bchan) return;
> // Extract full image file path
> Filename map = bchan->GetData().GetFilename(BASECHANNEL_SUGGESTEDFOLDER)+Filename(bchan->GetData().GetString(BASECHANNEL_TEXTURE));
> /// Copy file locally
> if (!GeFExist(map)) return;
> texpath += map.GetFile();
> if (!GeFExist(texpath))
> {
> GeFCopyFile(map, texpath, TRUE);
> if (stringArray) stringArray[*index] = texpath.GetFileString();
> ++(*index);
> }
> // clear suggested folder
> BaseContainer bdata;
> bdata.SetFilename(BASECHANNEL_SUGGESTEDFOLDER, Filename());
> bchan->SetData(bdata);
> // Update Material's texture image
> bdata.SetString(BASECHANNEL_TEXTURE, map.GetFileString());
> bchan->SetData(bdata);
> }
A caveat here is that this routine does not consider texture map files referenced deeper (such as in Fusion shaders). Thus, using "Save Project" is a better approach as it will rectify all texture map path references to be relative.
HTH!