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

    Allowing plugins to talk to eachother?

    SDK Help
    0
    26
    17.5k
    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 14/01/2013 at 09:20, xxxxxxxx wrote:

      Thanks for the code Niklas.

      I'm having a hard time with this: Bool result = GeDialog::Message(msgType, msg);
      It's giving me errors because the Message() method that we override in these plugins is a LONG type. Not a Bool.

      So I have to figure out another way to write that line of code.

      -ScottA

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

        On 14/01/2013 at 10:08, xxxxxxxx wrote:

        Hi Scott,

        I'm very sorry, that is a typo. I was originally overriding Message() but then noticed that I need
        to use CoreMessage(), changed the type only and forgot to change the parent-call. It should of
        course be like the following:

        Bool result = GeDialog::CoreMessage(msgType, msgData);

        I hope everything else is clear to you (and I didn't mess any other things up :P)

        Best wishes,
        Niklas

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

          On 14/01/2013 at 13:11, xxxxxxxx wrote:

          No worries. Happens to me all the time.
          I've got most of your code in place. But I'm afraid it's not working for me.
          The Bitmap button is always blank.

          The only code I couldn't use at all was this:

          Bool PluginStart() {  
            Bool success;  
            success = MyDialog::InitStatic();  
            if (!success) {  
                MessageDialog("MyDialog class could not initialize internals.");  
                return FALSE;  
            }  
            
            // Register Command and Tag and stuff you need..  
          }
          

          I'm guessing you want me to put that in the main.cpp file?
          I couldn't make it work. But it looks like that just handles a no image found scenario. And shouldn't stop the plugin from working if there's an image in the tag.

          You also used an Auto type C++ 11 feature that didn't work for me. I don't think the SDK supports this new C++ feature yet.
          So I wrote it this way instead:

            
            switch (type)  
            {  
                // Handle our custom message here !  
                case PMSG_GETSAMPLEIMAGE:  
                    {  
                    // C++11 Feature!  
                    //auto data = (PMSG_GetSampleImageData* ) data;  //<--Not supported by the SDK?  
                    PMSG_GetSampleImageData *data = gNew PMSG_GetSampleImageData;  
                    data->supported = TRUE;  
                    data->bmp = image;  
                    gDelete(data);  
                    }    
                    break;  
            }
          

          I'm not sure if it's correct. But is doesn't crash.

          I see what you're trying to do. But it's not working for me.
          I'm still a learner with this C++ stuff so I might be doing something wrong.

          Thanks anyway for trying to help,
          -ScottA

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

            On 14/01/2013 at 14:44, xxxxxxxx wrote:

            Hi Scott!

            The PluginStart() function from above should just give you a hint that I intended
            MyDialog::InitStatic() to be called so that MyDialog::defaultImage will be initialized (and
            that it will be handled when this method returned FALSE). It should not cover your complete
            PluginStart() implementation (didn't even take a close look at yours).

            The auto keyword is a C++11 feature supported by VC2010 and newer. It is just a shortcut
            so you don't have to write the type identifier twice. Therefore, the correct non-C++11 version
            of that line is as follows:

            PMSG_GetSampleImageData* data = (PMSG_GetSampleImageData* ) msgData;

            while msgData is the second parameter from the MyTag::Message() method (being a void*
            pointer that needs to be casted into the expected data-type). In your version of the code,
            you do not pass the requested data to the informant (sender of the message), but instead,
            you create a new data object temporarily and freeing it afterwards. This is why we pass the
            address of our data object to the message so the tag can fill in the data and we can retrieve it.

            I'll try to set up some working and compiling code as soon as I have the time for it!

            Best,
            Niklas

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

              On 14/01/2013 at 15:28, xxxxxxxx wrote:

              Ok. Thanks Niklas.

              There's so many parts to these C++ plugins it's really hard to cover something like this with code snippets. It's not like sharing python code. There's too many places it can go wrong.
              I had hoped that by providing a complete example it would lesson the burden of people trying to help me. And they could just edit my code without having to build it all from scratch.

              I appreciate the help,
              -ScottA

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

                On 15/01/2013 at 04:40, xxxxxxxx wrote:

                Hi Scott,

                I've spent my last three hours working on a complete plugin. You definately owe
                me a beer, okay? Windows x86 build is included. To build it on your own, you
                must add threee new include paths to your VC project (I build from the command
                line that is why the VC project is not included). These are ./ ./include and
                ../../resource/modules/xtensions/res/description/ (to include
                drendersettings.h from PComUtils.h).

                When you open the dialog, you will see an image showing a red exclamation mark
                with the text "not supported". This image is shown in the BitmapButton when
                no Tag is selected or the Tag does not respond positive to the
                MSG_PCOM_CANSETBITMAP message. When you create a PComTag on an object and
                select it, the image shown in the dialog will turn into a green one with the
                word "Render". This happens due to the fact that the PComTag responds positive
                to the MSG_PCOM_CANSETBITMAP message and additionally does not have an
                internal bitmap assigned yet. When you click on that "Render" image, it will
                turn into an image of the current scene (just like in your example). The
                MSG_PCOM_SETBITMAP message is sent and the PComTag will store the rendered
                image internally. When selecting another Tag, you will again see the red
                exclamation mark. Selecting the PComTag again will display the stored image.
                The image is retrieved from a Tag by sending the MSG_PCOM_RETRIEVEBITMAP
                message. Clicking on the button when the stored image is displayed will
                remove the image from the tag by sending MSG_PCOM_SETBITMAP with a NULL pointer
                instead of a valid address to a bitmap (which by definition of the message
                type states, that the internal image should be removed).

                https://docs.google.com/file/d/0B8i9BbP98pJRWC0tV3Rkb1BtRGc/edit

                Best wishes,
                Niklas

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

                  On 15/01/2013 at 09:07, xxxxxxxx wrote:

                  Wow.That's really great.
                  Thanks a lot Niklas. 🍺

                  Sorry it took up so much of your time.

                  -ScottA

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

                    On 25/01/2013 at 08:58, xxxxxxxx wrote:

                    Has anyone ever used friend classes within these C4D plugins?
                    In some cases it would be much less complicated if the two plugins simply had access to each others class members. Rather than using a third party interface to make them communicate.

                    I've Googled about friend classes trying to learn how to write them.
                    But when I try to use them inside of these plugins. I can't get it to work.
                    I can set up the basic framework so it will compile without errors. But when I try to access the member variables from the other class. I get undefined type errors.

                    Example:

                      
                    //Forward declare the tag so the Dialog can access it  
                    class MyTag;  
                      
                    class MyDialog : public GeDialog  
                    {  
                      public:   
                          virtual blah, blah, blah;  
                          virtual blah, blah, blah;  
                        
                          LONG dialogMemberVariable;  //A class member that the tag can also access  
                      
                          friend MyTag;  
                      
                    };  
                    ...  
                      
                    //How do I access use the tagMemberVariable without getting undefined class errors?  
                      
                      
                    class MyTag : public TagData  
                    {  
                      public:  
                          virtual blah, blah, blah;  
                          virtual blah, blah, blah;  
                        
                          LONG tagMemberVariable; //A class member that the dialog can also access  
                      
                          friend MyDialog;   
                    };  
                      
                      //How do I access use the dialogMemberVariable without getting undefined class errors?  
                      
                    ...
                    

                    -ScottA

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

                      On 27/01/2013 at 11:59, xxxxxxxx wrote:

                      Hi Scott,

                      The friend keyword allows the specified class to access protected and private attributes and
                      methods. Both of your classes have public members only, the friend keyword does not have any
                      effect.

                      Best,
                      Nik

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

                        On 27/01/2013 at 13:42, xxxxxxxx wrote:

                        Hiya Nik,

                        I learned a bit more about how to use friend yesterday.
                        I've a good raw C++ example now that I'm using as a learning tool:

                        //This is an example of using a custom method to access two different class's members  
                        //By making the method a friend of both of the classes  
                          
                        #include <iostream>  
                        #include <string>  
                        using namespace std;  
                          
                        class Class2;     //Forward declare Class2 so Class1 knows what's inside of it   
                          
                        class Class1  
                        {  
                          public:  
                            int a, b;  
                            Class1() : a(1), b(2) { }    //Constructor sets the class variable values  
                            friend void change(Class1 c1, Class2 c2);  
                        };  
                          
                        class Class2  
                        {  
                          public:  
                            int j;  
                            Class2() : j(3) { }        //Constructor sets the class variable value  
                            friend void change(Class1 c1, Class2 c2);   
                        };  
                          
                        void change(Class1 &x1, Class2 &x2)  
                        {  
                          x1.a = 10;          //Changes the Class1 variable from 1 to 10  
                          x2.j = 45;        //Changes the Class2 variable from 3 to 45  
                          
                              //Compare the members from the two different classes  
                          if(x1.a < x2.j) cout << "Class1 member a is less than Class2 member j" <<endl;  
                        }  
                          
                        int main()  
                        {  
                          Class1 c1;  
                          Class2 c2;  
                          change(c1,c2);  
                          
                          cout<< "Class1 member a= "<< c1.a <<endl;  
                          cout<< "Class2 member j= "<< c2.j <<endl;  
                          
                          system("pause");   //Keeps the console open until the Enter key is pressed  
                          return 0;  
                        }
                        

                        The problem I'm having with this in C4D plugins is that we don't use main() quite the same way as in raw C++.
                        I think I need to place a prototype of the function that's the friend of the classes in the main.cpp file of C4D plugins. But I'm having a problem with the parameters part.

                        I can make a void type prototyped method without any parameters work fine in the C4D main.cpp file.
                        But when the method has params. in it ( In this cases the two classes). I'm having a hard time getting that to work in the main.cpp file.

                        -ScottA

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

                          On 27/01/2013 at 14:04, xxxxxxxx wrote:

                          Hi Scott,

                          I'm a little-bit confused. You never call the method check() of either class. The methods are defined,
                          but not implemented, nor ever referenced. What should this example actually demonstrate?

                          class A {
                              friend B;
                              private:
                          
                                  void DoPrivateStuff();
                          
                              public:
                          
                                  void DoPublicStuff();
                          };
                          
                          class B {
                              private:
                          
                                  void DoPrivateStuff();
                          
                              public:
                          
                                  void DoPublicStuff();
                          };
                          

                          While class A has access to B::DoPublicStuff() only, class B has access to A::DoPublicStuff()
                          and A::DoPrivateStuff().

                          -Nik

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

                            On 27/01/2013 at 14:16, xxxxxxxx wrote:

                            Oops. Sorry about that.
                            "check" should be "changed".
                            I changed it.

                            The problem I'm having is calling the changed() type function when doing it in a C4D plugin.
                            main() is written slightly differently in these C4D plugins.  And I'm having a problem with those differences.
                            Specifically. I'm having a hard time prototyping functions that have params. in them in the C4D main.cpp file.

                            -ScottA

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