Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Objects plugins with their own materials [SOLVED]

    SDK Help
    0
    4
    363
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 21/04/2016 at 13:24, xxxxxxxx wrote:

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

      ---------
      Hello, I'm working with Object Plugin that has materials associated with it and that are added to the scene with MSG_MENU_PREPARE.  I've been looking at Matthias' code from this thread https://developers.maxon.net/forum/topic/5051/4975_question and I copied the code below.

      I want to modify it so that each instance of the plugin has it's own material, instead of sharing a single material.  If I call the plugin again then the new instance of the plugin gets a new material, but if the plugin is copied and pasted within the same scene file it doesn't create another material and both objects share the same already existing material.  Where should I start looking to accomplish this?

        
          
          
          class MySky : public ObjectData  
          {  
            public:  
                virtual Bool Init(GeListNode *node);  
                virtual Bool Read(GeListNode *node, HyperFile *hf, LONG level);  
                virtual Bool Write(GeListNode *node, HyperFile *hf);  
                virtual Bool CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, LONG flags, AliasTrans *trn);  
                virtual Bool Message(GeListNode *node, LONG type, void *data);  
                virtual BaseObject *GetVirtualObjects(BaseObject *op, HierarchyHelp *hh);  
            
                static NodeData *Alloc(void) { return gNew MySky; }  
            
                //the BaseLink containing the link to the material  
                //must be handled through CopyTo, Read, Write  
                AutoAlloc<BaseLink> matlink;  
          };  
            
            
          Bool MySky::Init(GeListNode *node)  
          {  
            if (!matlink) return FALSE;  
            
            return TRUE;  
          }  
            
          Bool MySky::Read(GeListNode *node, HyperFile *hf, LONG level)  
          {  
            return matlink->Read(hf);  
          }  
            
          Bool MySky::Write(GeListNode *node, HyperFile *hf)  
          {  
            return matlink->Write(hf);  
          }  
            
          Bool MySky::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, LONG flags, AliasTrans *trn)  
          {  
            return matlink->CopyTo(((MySky* )dest)->matlink, flags, trn);  
          }  
            
          Bool MySky::Message(GeListNode *node, LONG type, void *data)  
          {  
            switch (type)  
            {  
                //create the material after the menu entry of the object has been called  
                //save the material pointer as BaseLink  
                case MSG_MENUPREPARE:  
                    {  
                        BaseDocument *doc = (BaseDocument* )data;  
            
                        Material *mat = (Material* )matlink->GetLink(doc, Mmaterial);  
            
                        if (!mat)  
                        {  
                            mat = Material::Alloc();  
                            if (!mat) return FALSE;  
                            doc->InsertMaterial(mat, NULL, NULL);  
            
                            matlink->SetLink(mat);  
                        }  
                    }  
                    break;  
            
                //must be checked because CINEMA 4D can have several documents open  
                //objects and their materials can be copied across these docuemnts  
                //the MarkMaterials structure contains the old and new material  
                case MSG_MULTI_MARKMATERIALS:  
                    {  
                        Material* mat;  
                        MarkMaterials* mm = (MarkMaterials* )data;  
                        BaseDocument* doc = GetDocument(node);  
            
                        if (mm)  
                        {  
                            mat = (Material* )matlink->GetLink(doc, Mmaterial);  
                            if (mat == mm->omat)   
                            {  
                                doc->StartUndo();  
                                doc->AddUndo(UNDO_CHANGE_SMALL, node);  
                                matlink->SetLink(mm->nmat);  
                                doc->EndUndo();  
                            }  
                        }  
                        else  
                        {  
                            mat = (Material* )matlink->GetLink(doc, Mmaterial);  
                            if (mat) mat->SetBit(BIT_MATMARK);  
                        }  
                    }  
                    break;  
            }  
            
            return TRUE;  
          }  
            
          BaseObject* MySky::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)  
          {  
            Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTY_DATA);  
            if (!dirty) return op->GetCache(hh);  
            
            BaseObject *sky = NULL;  
            TextureTag *ttag = NULL;  
              
            sky = BaseObject::Alloc(Osky);  
            if (!sky) goto Error;  
            
            //create the texture tag for the material  
            ttag = (TextureTag* )sky->MakeTag(Ttexture, NULL);  
            if (!ttag)    goto Error;  
            
            //set the material  
            ttag->SetMaterial((Material* )matlink->GetLink(hh->GetDocument(), Mmaterial));  
            
            return sky;  
            
          Error:  
            blDelete(sky);  
            blDelete(ttag);  
            return NULL;  
          }  
          
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 22/04/2016 at 02:11, xxxxxxxx wrote:

        Hello,

        I'm not aware of any way to achieve this only using the ObjectData itself. But a SceneHookData plugin receives the message MSG_DOCUMENTINFO and the sub-message MSG_DOCUMENTINFO_TYPE_PASTE. So you could check if something was pasted into the document and if the new element is an object of your type. If so you could create a new material and connect it to your object instance.

        Best wishes,
        Sebastian

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 22/04/2016 at 11:12, xxxxxxxx wrote:

          Thanks, taking a look at it now.

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 25/04/2016 at 10:45, xxxxxxxx wrote:

            This is my current code:

              
            Bool SettingsSceneHook::Message(GeListNode* node, LONG type, void* data)  
            {  
              if(type==MSG_DOCUMENTINFO)  
              {  
                  DocumentInfoData* dc = (DocumentInfoData* ) data;  
                  if(dc->type ==MSG_DOCUMENTINFO_TYPE_OBJECT_INSERT)  
                  {  
                      BaseObject* insertedObject = static_cast<BaseObject*>(dc->bl);  
                      if(insertedObject->GetType() == SearchType)  
                      {  
                            
                         ReplaceMaterial(insertedObject);  
                            
                      }  
                  }  
                    
                    
              }  
              return true;  
                
            }  
             
            

            I've got it correctly adding in my materials when an object of the specified type is inserted.  It seems like the functionality of MSG_DOCUMENTINFO_TYPE_PASTE is more limited and wouldn't cover certain cases so I went with MSG_DOCUMENTINFO_TYPE_OBJECT_INSERT instead.

            Dan

            1 Reply Last reply Reply Quote 0
            • First post
              Last post