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

    Set Material Default Projection [SOLVED]

    SDK Help
    0
    15
    1.6k
    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 13/09/2014 at 14:02, xxxxxxxx wrote:

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

      ---------
      Hi,
      How do we set the default projection option in a MaterialData plugin?

      When we create a standard C4D material and drop it on an object. The projection option for the texture tag is set to UVW by default.
      But when I create my own material with a MaterialData plugin and drop it on an object. The default projection is set to Spherical in the texture tag.

      How can I make it default to UVW like the built-in C4D materials?

      -ScottA

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

        On 14/09/2014 at 14:31, xxxxxxxx wrote:

        TextureTag *pTexTag = (TextureTag* )pPolyonObject>GetTag(Ttexture);
        Material *pMat = Material::Alloc();

        pDoc->InsertMaterial(pMat);
        pTexTag->SetMaterial(pMat);

        BaseContainer tagData = pTexTag->GetData();
        tagData.SetInt32(TEXTURETAG_PROJECTION, TEXTURETAG_PROJECTION_UVW);
        pTexTag->SetData(tagData);

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

          On 14/09/2014 at 16:40, xxxxxxxx wrote:

          Hi Kbar.
          I know how to grab the texture tag and then change it to UVW mode.
          This the way I do that:

            
          tag->SetParameter(DescLevel(TEXTURETAG_PROJECTION), GeData(TEXTURETAG_PROJECTION_UVW), 0);
          

          What I'm trying to do is set the generated texture tag to UVW automatically when I drop my custom material on an object.
          When we drag & drop a standard material onto an object. C4D creates a texture tag on the object with it's projection option set to UWV.
          What is telling the tag to switch to UVW mode like that?

          Do I maybe need to send some kind of CoreMessage to C4D from my material telling it to change the generated texture tag's mode?
          How would I do that?

          -ScottA

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

            On 14/09/2014 at 20:48, xxxxxxxx wrote:

            Well.
            I don't know how Maxon does it. But this is what I've dreamed up. And it seems to work so far.
            I'm using a small MessageData plugin in my MaterialData plugin that catches a SEA message sent from the MaterialData plugin when the material is dropped onto an object.
            Then the MessageData plugin changes the texture tag's projection to UVW.

            Maybe this will help someone else out if they ever run up against the same problem.

            //Be sure to use unique ID#s obtained from www.plugincafe.com  
            #define ID_SIMPLEMAT 10000004  
            #define ID_MESSAGE   10000005  
              
            /////////////////////////////////////////////////  
            /////////// MessageData plugin/////////////////  
              
            class MyMessage: public MessageData  
            {  
              virtual Bool CoreMessage(LONG id, const BaseContainer &bc);  
            };  
                
            Bool MyMessage::CoreMessage(LONG id, const BaseContainer &bc)  
            {  
              if(id==ID_SIMPLEMAT)  
              {  
                  //GePrint("Recieved sea message");  
                  BaseDocument *doc = GetActiveDocument();  
                  BaseTag *tag = doc->GetActiveTag();  
                  if(tag)   
                  {  
                      GeData d;              
                      tag->GetParameter(DescID(TEXTURETAG_MATERIAL), d, DESCFLAGS_GET_0);  
                      String name = d.GetLink(doc, NULL)->GetName();  
                      if(name == "My Material") tag->SetParameter(DescLevel(TEXTURETAG_PROJECTION), GeData(TEXTURETAG_PROJECTION_UVW), DESCFLAGS_SET_0);              
                  }          
              }  
              
              return TRUE;  
            }    
                
            Bool RegisterMyMessage(void)  
            {  
              return RegisterMessagePlugin(ID_MESSAGE, "My Message", 0, gNew MyMessage);  
            }  
              
              
              
            /////////////////////////////////////////////////  
            /////////// MaterialData plugin/////////////////  
              
            //...MaterialData class and various overridden methods here...  
              
            //The part of the Message() method that sends out a SEA message  
            Bool MyMaterial::Message(GeListNode* node, LONG type, void* data)  
            {  
              //Send out a SEA message when this material is dropped on an object  
              if(type == MSG_MATERIALDRAGANDDROP) SpecialEventAdd(ID_SIMPLEMAT);  
              
              //...the rest of your MaterialData code stuff here...  
              
              return TRUE;  
            }  
              
            //...The rest of the overridden MaterialData methods here...  
            

            -ScottA

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

              On 14/09/2014 at 23:25, xxxxxxxx wrote:

              Why use a MessageData plugin and SpecialEventAdd? You use the right message already. Look
              at its documentation, here[URL-REMOVED]. You can create your own tag and fill it into the "result" member of the
              passed MaterialDragAndDrop structure to prevent the creation of a default tag.

              -Niklas


              [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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

                On 15/09/2014 at 07:37, xxxxxxxx wrote:

                Yeah I saw that in the docs Niklas.
                But it doesn't tell me anything at all about how to actually use it. So I had to invent my own method.

                If that struct is capable of changing the material's texture tag options. I'd like to know how?

                -ScottA

                Edit- I also hate using the material's name as the thing it looks for. Because the user can change it.
                So I'm still looking for a better way to find the material that a ttag belongs to.

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

                  On 15/09/2014 at 08:47, xxxxxxxx wrote:

                  I guess getting the name of the material from the tag "link field" should be doable

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

                    On 15/09/2014 at 10:07, xxxxxxxx wrote:

                    There has to be a better way than using the name property.
                    I wouldn't even need it if Maxon documented the MaterialDragAndDrop struct properly.

                        if(type == MSG_MATERIALDRAGANDDROP)   
                      {  
                         MaterialDragAndDrop mdd;  
                         mdd.doc = GetActiveDocument();  
                         mdd.op = mdd.doc->GetActiveObject();  
                         mdd.result = mdd.op->GetTag(Ttexture);  
                      
                         GePrint(mdd.result->GetName());  //<---Crash!!!  
                      }
                    

                    Obviously I'm doing it wrong. And it's crashing because the tag doesn't exist yet.
                    But how the heck are we supposed to use this struct code to get the tag the material generates?
                    The docs don't tell us squat how to use it. Less than squat.
                    Squat looks at the docs and says "Man, that ain't squat". 😠

                    -ScottA

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

                      On 15/09/2014 at 10:51, xxxxxxxx wrote:

                      you need to do checks about GetActiveObject() and GetTag() , I see if no object it will crash, but not sure also if the whole process is correct

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

                        On 15/09/2014 at 11:10, xxxxxxxx wrote:

                        Well. That was just a quick and dirty example.
                        I can add error checking to resolve the crash. But I still can't access the texture tag and change it using the struct as the docs seem to hint at. But never exaplin how to actually do it.

                          
                          if(type == MSG_MATERIALDRAGANDDROP)  
                          {  
                             MaterialDragAndDrop mdd;  
                             mdd.doc = GetActiveDocument();  
                             if(!mdd.doc) return FALSE;  
                             mdd.op = mdd.doc->GetActiveObject();  
                             if(!mdd.op) return FALSE;  
                          
                             //Nope..doesn't work   
                             //It doesn't crash...but it doesn't change the tag's projection option either. Because the tag does not exist yet!!!  
                             mdd.result = mdd.op->GetTag(Ttexture);  
                             if(mdd.result) mdd.result->SetParameter(DescLevel(TEXTURETAG_PROJECTION), GeData(TEXTURETAG_PROJECTION_UVW), DESCFLAGS_SET_0);  
                          }
                        

                        I'm sure I'm using it wrong.

                        -ScottA

                        *Edit:
                        Thanks for your input guys.
                        I'm feeling very angry and grumpy at Maxon right now for their crappy docs. So please excuse me if I come off as rude or snappy in this thread.

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

                          On 15/09/2014 at 11:31, xxxxxxxx wrote:

                          I'm not sure if this may work or not, but I think MaterialDragAndDrop should be a pointer, constructed inside the texture tag constructor, and when you encounter the message MSG_MATERIALDRAGANDDROP your problem will vanish because the tag is there

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

                            On 15/09/2014 at 11:56, xxxxxxxx wrote:

                            Sorry Scott, but the documentation is as clear as it can get.

                            MSG_MATERIALDRAGANDDROP
                            Received by a material upon dropping an instance of the material onto an object. The material can choose to create a tag of its own, or trigger other actions, instead of letting CINEMA 4D create a normal material assignment. The corresponding data is MaterialDragAndDrop.

                            For example Sketch and Toon creates its own type of tag and returns it in result. CINEMA 4D creates the undo for it and activates it. Inserting the tag is done by the material.

                            And in the description of MaterialDragAndDrop:

                            BaseTag* result
                            If you choose to create a tag of your own, point this pointer to it. CINEMA 4D will create the undo and activate the tag. (You still have to insert the tag manually onto the object.)

                              
                            // note: nullptr checks omitted
                            Bool MyMaterial::Message(GeListNode* node, Int32 type, void* pData)
                            {
                              if(type == MSG_MATERIALDRAGANDDROP)
                              {
                                BaseMaterial* mat = static_cast<BaseMaterial*>(node);
                                MaterialDragAndDrop* mdd = static_cast<MaterialDragAndDrop*>(pData);
                                mdd->result = mdd->op->MakeTag(Ttexture);
                                mdd->result->SetParameter(TEXTURETAG_MATERIAL, mat, DESCFLAGS_SET_0);
                                mdd->result->SetParameter(TEXTURETAG_PROJECTION, TEXTURETAG_PROJECTION_UVW, DESCFLAGS_SET_0);
                                return true;
                              }
                              return MaterialData::Message(node, type, pData);
                            }
                            
                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 15/09/2014 at 12:25, xxxxxxxx wrote:

                              Thanks Niklas. That works. 👍

                              But I disagree about the docs. The docs are not even remotely saying what you've written there.
                              What on earth made you think of using this code based on the docs saying use your own pointer?:
                              MaterialDragAndDrop *mdd = static_cast<MaterialDragAndDrop*>(pData);

                              Since when does use your own pointer = void *pData?
                              I don't see the connection at all. That's as clear as mud to me.

                              -ScottA

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

                                On 15/09/2014 at 23:00, xxxxxxxx wrote:

                                Originally posted by xxxxxxxx

                                Thanks Niklas. That works. 👍

                                But I disagree about the docs. The docs are not even remotely saying what you've written there.
                                What on earth made you think of using this code based on the docs saying use your own pointer?:
                                MaterialDragAndDrop *mdd = static_cast<MaterialDragAndDrop*>(pData);

                                Since when does use your own pointer = void *pData?
                                I don't see the connection at all. That's as clear as mud to me.

                                -ScottA

                                It's Cinema's message system. I've seen you using it correctly before already, too. The documentation
                                tells you:

                                1. MSG_MATERIALDRAGANDDROP is a message type that is sent to NodeData plugins.
                                2. The data that is passed to the NodeData::Message() call is MaterialDragAndDrop
                                3. The MaterialDragAndDrop::result member can be set to a custom tag, preventing the
                                  caller (in this case Cinema 4D itself) to create the default tag.
                                4. If you create a custom tag, it does everything else that is required (undo step, selection, ...)

                                And as you should know, there is void* parameter for the NodeData::Message() method that
                                points to the data of the message. Depending on the message type, you can cast it to a different
                                pointer type in order to access the underlying data.

                                To show a different example:

                                if (type == MSG_GETCUSTOMICON)
                                {
                                  /* The void* parameter for the Message() function is the
                                   * address of a GetCustomIconData structure which the message
                                   * sender expects us to fill with the required information. */
                                  GetCustomIconData* data = static_cast<GetCustomIconData*>(pData);
                                  IconData* icon = data->dat;
                                  if (icon->bmp)
                                  {
                                    m_customIcon->CopyTo(icon->bmp);
                                  }
                                  else
                                  {
                                    icon->bmp = m_customIcon->GetClone();
                                  }
                                  icon->x = 0;
                                  icon->y = 0;
                                  icon->w = icon->bmp->GetBw();
                                  icon->h = icon->bmp->GetBh();
                                  data->filled = true;
                                  return true;
                                }
                                

                                Best,
                                -Niklas

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

                                  On 16/09/2014 at 10:27, xxxxxxxx wrote:

                                  OK. Thanks for explaining what when through your head.
                                  It helps me to know what other people are thinking when they use the docs. So I can learn how to decrypt them better.

                                  As I keep saying to you. You're cheating.!Wink[URL-REMOVED]
                                  You're not reading the docs. You are taking what you've learned from other people. Then using that information to "decrypt" what's not actually physically written in the page.

                                  I know you don't share the same opinion. And you think it's fun to figure out these little puzzles.
                                  But IMO the C4D docs require far too much of this. And it's really annoying when you're just trying to get something simple done. And don't want to play the "Solve the docs" puzzle game.
                                  IMO. Any time the reader has to rely on this much previously learned knowledge. The docs are not clear enough and they fail.

                                  -ScottA


                                  [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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