How to change the tex path in a existing material



  • On 09/06/2016 at 09:00, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R17 
    Platform:      
    Language(s) :     C++  ;

    ---------
    I figured it should be easy but unfortunatly it didn't

    I have created some materials and they are ok, also I can retrive them by name so thats ok too.
    _ BaseMaterial *searchmat = doc->SearchMaterial(name.c_str());_
    _ if (!searchmat)_
    _ return NULL;_
    _
    _
    My first try was
    _ _ BaseShader* bitmapShader = NULL;
    _ searchmat->GetParameter(DescLevel(MATERIAL_COLOR_SHADER), bitmapShader , DESCFLAGS_GET_0);_

    But obviously it didn't work, I tried others like
    _ _ GeData data;
    _ searchmat->GetParameter(DescLevel(MATERIAL_COLOR_SHADER), data, DESCFLAGS_GET_0);_
    _ BaseShader* bitmapShader = (BaseShader* )&data;_

    But no luck neither
    My intention is to find the current loaded texture and if it meets a condition (same file but other path) change it.

    Thank you in advance.



  • On 09/06/2016 at 13:30, xxxxxxxx wrote:

    You can't simply cast the GeData.  You have to use this:

    BaseShader* bitmapShader = static_cast<BastShader*>(data.GetLink(doc));
    

    where doc is a BaseDocument* to the document that contains the BaseMaterial.



  • On 13/06/2016 at 02:22, xxxxxxxx wrote:

    Hello,

    using GetParameter() one can access the value stored for a given parameter ID. This value is given in form of a GeData object. This GeData object can store any kind of data. To get the specific data one has to access it using a specific function.

    A ShaderLink parameter does not "own" or "store" a shader but it links to an existing shader. So you have to access the BaseLink that represents that link from the GeData object. Using that BaseLink you can then access the linked BaseShader.

    Best wishes,
    Sebastian



  • On 24/06/2016 at 06:22, xxxxxxxx wrote:

    Hello Motiva,

    was you question answered?

    Best wishes,
    Sebastian



  • On 02/09/2016 at 10:40, xxxxxxxx wrote:

    After a long time I come back since I never managed this properly I found an example here https://developers.maxon.net/docs/Cinema4DCPPSDK/html/page_manual_texturetag.html but it didn't work for me as expected

    	 _GeData data;_
    

    _ searchmat->GetParameter(DescID(MATERIAL_COLOR_SHADER), data, DESCFLAGS_GET_0); BaseShader* bitmapShader = static_cast<BaseShader*>(data.GetBaseLink()->GetLink(doc, Xbitmap));_

    I never managed to get bitmapShader.

    Any idea?



  • On 02/09/2016 at 15:12, xxxxxxxx wrote:

    There are two ways to change the image in a material's Xbitmap type shader
    -Using the BaseContanier
    -Using the Get() & Set() parameter functions
    Both work equally well. But Maxon prefers us to use the later whenever possible.

    BaseContainer method

        //The target material  
      BaseMaterial *mat = doc->GetActiveMaterial();  
      if (!mat) return FALSE;  
      
      //The file path to the new image  
      //Change this as desired  
      Filename file = Filename("C:\\Users\\user\\Desktop\\myimage.jpg");  
      
      //Target the color channel and get it's BaseContainer  
      BaseChannel *ch = mat->GetChannel(CHANNEL_COLOR);  
      BaseContainer bc = ch->GetData();  
      
      //Change the container to point to the new image file path  
      bc.SetString(BASECHANNEL_TEXTURE, file.GetString());   
      
      //Update the container so it uses the changes  
      ch->SetData(bc);  
      
      mat->Update(TRUE, TRUE);      //Updates the thumbnail image  
      mat->Message(MSG_UPDATE);     //Updates the material  
      
      EventAdd();
    

    Get() & Set() parameter method

        //The target material  
      BaseMaterial *mat = doc->GetActiveMaterial();  
      if (!mat) return FALSE;  
      
      //The file path to the new image  
      //Change this as desired  
      Filename file = Filename("C:\\Users\\user\\Desktop\\myimage.jpg");  
        
      //First test if there is already an Xbitmap shader holding an image in the color channel  
      //Bail out if it doesn't exit  
      GeData data;  
      mat->GetParameter(DescID(MATERIAL_COLOR_SHADER), data, DESCFLAGS_GET_0);  
      BaseShader *shader = static_cast<BaseShader*>(data.GetLink(doc, Xbitmap));  
      if (!shader || !shader->IsInstanceOf(Xbitmap)) return false;  
        
      //Get the image that is currently in the shader and print it to the console  
      //This code can be skipped if desired  
      shader->GetParameter(DescID(BITMAPSHADER_FILENAME), data, DESCFLAGS_GET_0);  
      GePrint(data.GetFilename().GetString());  
      
      //Change the file path by setting it in the data variable (similar to changing a BaseContainer value)  
      data.SetFilename(file);  
      
      //Target the file option in the shader and appy the data variable. Which now holds the new file path  
      //The ID for the file option is: BITMAPSHADER_FILENAME  
      shader->SetParameter(DescLevel(BITMAPSHADER_FILENAME), data, DESCFLAGS_SET_0);  
            
      mat->Update(TRUE, TRUE);      //Updates the thumbnail image  
      mat->Message(MSG_UPDATE);     //Updates the material  
        
      EventAdd();
    

    -ScottA



  • On 05/09/2016 at 02:55, xxxxxxxx wrote:

    It could be related to the time it happens I followed your second method without luck neither.

    I'm testing it at open scene time and it always fails on

     if (!shader || !shader->IsInstanceOf(Xbitmap)) return false;
    

    but I'm sure there is one probably the material has not loaded properly yet.



  • On 05/09/2016 at 05:10, xxxxxxxx wrote:

    Hello,

    could you explain what exactly you mean with "open scene time"?

    best wishes,
    Sebastian



  • On 05/09/2016 at 08:19, xxxxxxxx wrote:

    I mean in during opening the document
    Message(GeListNode* node, Int32 type, void* data)

    type==MSG_MULTI_DOCUMENTIMPORTED



  • On 06/09/2016 at 00:33, xxxxxxxx wrote:

    Hello,

    I have no problem to access the shader when the host material is loaded (implemented in the "Message" function of the material plugin) :

      
    case (MSG_MULTI_DOCUMENTIMPORTED) :  
    {  
      // access shader link  
      GeData data;  
      if (node->GetParameter(2001, data, DESCFLAGS_GET_0))  
      {  
      BaseDocument* doc  = node->GetDocument();  
      BaseLink*     link = data.GetBaseLink();  
      
      if (link && doc)  
      {  
        // access shader  
        BaseList2D* shader = link->GetLink(doc);  
        if (shader && shader->IsInstanceOf(Xbitmap))  
        {  
          // get filename  
          shader->GetParameter(BITMAPSHADER_FILENAME, data, DESCFLAGS_GET_0);  
          GePrint("Used Bitmap: " + data.GetFilename().GetString());  
        }  
      }  
      }  
      break;  
    }  
    

    best wishes,
    Sebastian



  • On 06/09/2016 at 01:26, xxxxxxxx wrote:

    Sorry my object is not a material but a dummy object I'm getting the material by name, but I can retrieve it properly, maybe just in the c4d order the materials are created but no filled.


Log in to reply