Change material color in objectData plugin[SOLVED]



  • On 04/06/2015 at 06:36, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R16 
    Platform:      Mac OSX  ; 
    Language(s) :     C++  ;

    ---------
    Hi,

    I'm coding an objectData plugin which needs some new materials.
    I can find almost no information about this, so that's why I'm posting it here.
    I have a way to do it, but it isn't thread safe, so I'd like a better way.
    This is the method I use right now:
    - Inside MSG_MENUPREPARE I create the materials I need.
    - Inside the Init method I set the parameters for the colors of my materials. (These are GUI sliders, representing the color)
    - Inside GetVirtualObjects I change the color of my material depending on my GUI sliders. I know this isn't thread-safe, but I can't seem to find another way how to do this.

    I've tried inside MSG_POSTSETPARAMETER, but that just instantly crashes my C4D.

    If I have to work together with a materialData plugin to make it thread-safe, I'm happy to do so.

    Also, there are no examples about this in the SDK, so I really don't know how to improve this.
    Could somebody please help me with this? Give hints so I can search further in the right direction?

    If you need more information, just ask.
    Thanks in advance for your help and time!

    With kind regards,
    Casimir Smets



  • On 04/06/2015 at 07:22, xxxxxxxx wrote:

    Hi Casimir,

    I recommend to have a look at the threading article in the SDK documentation. There's actually an example (see "Using Core Messages"), how to transfer work from a threaded function into the main thread.



  • On 04/06/2015 at 08:09, xxxxxxxx wrote:

    Hi Andreas,

    I will definately look into this!
    Also, somebody else told me I had to do this in MSG_POSTSETPARAMETER.
    Can I assume this is wrong? Or are there multiple solutions?
    Thanks for your help and time!

    With kind regards,
    Casimir Smets



  • On 09/06/2015 at 03:17, xxxxxxxx wrote:

    Hi Andreas,

    Well, I can't get it to work. What I have now is:

      
    const Int32 UPDATE_MATERIALS = 1016549;  
      
    class MyPluginData : public ObjectData  
    {  
      INSTANCEOF(MyPluginData, ObjectData)  
      
    public:  
      ...  
      virtual Bool CoreMessage(Int32 id, const BaseContainer& msg);  
    };  
      
    Bool MyPluginData::Message(GeListNode* node, Int32 type, void* data)  
    {  
      if (type == MSG_MENUPREPARE)  
      {  
          BaseContainer* myData = ((BaseObject* )node)->GetDataInstance();  
          if (!myData) return false;  
          BaseDocument* doc = static_cast<BaseDocument*>(data);  
          if (!doc) return false;  
          BaseMaterial* myMaterial = BaseMaterial::Alloc(MMaterial);  
          if (!myMaterial) return false;  
          BaseContainer* myMaterialData = myMaterial->GetDataInstance();  
          if (!myMaterialData) return false;  
          myMaterial->SetName("My_Material");  
          myMaterial->SetParameter(MATERIAL_USE_REFLECTION, 0, DESCFLAGS_SET_0);  
          myMaterialData->SetParameter(MATERIAL_COLOR_COLOR, myData->GetData(SKINMATERIAL_DIFFUSE_COLOR));  
          doc->InsertMaterial(myMaterial);  
      }  
    ...  
    }  
      
    Bool MyPluginData::Init(GeListNode* node)  
    {  
      BaseObject* op = (BaseObject* )node;  
      if (!op) return false;  
      BaseContainer* data = op->GetDataInstance();  
      if (!data) return false;  
      ...  
      Float myTextureR = 255;  
      Float myTextureG = 190;  
      Float myTextureB = 153;  
      data->SetParameter(MYMATERIAL_DIFFUSE_COLOR, Vector(myTextureR/255, myTextureG/255, myTextureB/255));  
      return true;  
    }  
      
    BaseObject* MyPluginData::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh)  
    {  
      BaseDocument* doc = op->GetDocument();  
      if (!doc) return nullptr;  
    ...  
      BaseMaterial* myMaterial = doc->SearchMaterial("My_Material");  
      if (!myMaterial) return nullptr;  
      BaseContainer* myMaterialData = myMaterial->GetDataInstance();  
      if (!myMaterialData) return nullptr;  
      SpecialEventAdd(UPDATE_MATERIALS, 0, 0);  
      GePrint("The special event should be called!");  
    ...  
    }  
      
    Bool MyPluginData::CoreMessage(Int32 id, const BaseContainer& msg)  
    {  
      GePrint("Some CoreMessage has been called!");  
      switch (id)  
      {  
          case UPDATE_MATERIALS:  
              GePrint("The update_materials core message has been called!");  
      }  
      return true;  
    }  
    ...  
    

    As you can see I use GePrint to check whether the CoreMessage has been called or not, or if it should have been called.
    My output tells me that it should have been called multiple times, but it also says that it was never called.

    I can't seem to find the problem :s
    Does anybody see the problem here?

    Thanks in advance for your help and time!
    Greetings,
    Casimir Smets



  • On 09/06/2015 at 09:07, xxxxxxxx wrote:

    Hi Casimir,

    you can't just make up a new function and hope for it to be called. ObjectData has no CoreMessage() member to be overloaded. CoreMessages are mainly used for GUI stuff (GeDialog, GeUserArea). Think of them as messages to the application Cinema 4D and not as messages any scene related data (no NodeData derived class has CoreMessage implemented).
    So in order to make use of it, you will need to implement it in your own MessageData plugin, just like it's shown in the threading article.



  • On 09/06/2015 at 10:55, xxxxxxxx wrote:

    Hi Andreas,

    Ok, that makes sense. I don't have any experience with messages yet, so it's a bit blurry for me.
    I will look into that!

    Thanks again for your help and time!
    With kind regards,
    Casimir Smets



  • On 11/06/2015 at 01:31, xxxxxxxx wrote:

    Hi,

    Well, it seems that CoreMessage wasn't needed after all. I had to do it inside MSG_DESCRIPTION_CHECKUPDATE:

      
    else if (type == MSG_DESCRIPTION_CHECKUPDATE)  
    {  
      DescriptionCheckUpdate* dc = (DescriptionCheckUpdate* )data;  
      if (*dc->descid == MYMATERIAL_DIFFUSE_COLOR)  
      {  
          ...  
    

    And here are the steps on how to create and change materials inside an objectData plugin:
    - Create a color description element
    - Inside MSG_MENUPREPARE, create the material and set the parameters like you want
    - Inside Init, set the color parameter values (RGB)
    - Inside GVO, search the materials and assign them to the proper objects
    - Inside MSG_DESCRIPTION_CHECKUPDATE, check if your color slider has changed, and if so, change the material and update it

    This should be it, if you have questions about it, just ask.
    After all, the solution is pretty simply.

    This post can be marked as solved!
    Also, could a moderator change the name to this: "Create and change material colors in objectData plugin"? or something like that.

    Greetings,
    Casimir Smets


Log in to reply