Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    How to communicate with iCustomGui?

    SDK Help
    0
    28
    16.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 25/03/2014 at 04:24, xxxxxxxx wrote:

      Hi Niklas

      virtual Bool SetData(const TriState<GeData> &tristate)
      {
      		const GeData &value = tristate.GetValue();
      		if(value.GetContainer())
      		{
      			BaseContainer* bc = value.GetContainer();
      			Real fooReal = bc->GetReal(12345);
      			LONG fooLong = bc->GetLong(6789);
      			Bool fooBool = bc->GetBool(654321);
      		}
      }
      
      virtual Bool GetData(const TriState<GeData> &tristate)
      {
      		BaseContainer bc;
      		bc.SetReal(12345, 3.14);
      		bc.SetLong(6789, 2014);
      		bc.SetBool(654321, TRUE);
      		GeData geContainer(bc);
      		return TriState<GeData>(geContainer);
      }
      

      By passing a BaseContainer between the tag and the custom GUI, I can send a bunch of data in one operation.
      When reading this code, you have to take into consideration that it is simplified, I have removed all the normal validity and safety checks.
      In the tag, I can just use SetParameter() and use a BaseContainer that I create on the fly, fill it up with data, and use it as the second parameter. The first parameter is the ID of the Custom GUI.
      For the record, I had to concentrate on other tasks the last couple of weeks, so this topic is out of my head at the moment, but I will come back.

      I am really looking forward to a working example. Please use the BaseTag plugin type, and no Dialog or Command plugin. I do understand the iCustomDatatype if the user needs to add CustomData to the tag. But I do not understand the purpose of it when communicating between the tag and the GUI.

      And - keep the example simple, if possible 🙂

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

        On 25/03/2014 at 16:07, xxxxxxxx wrote:

        Hi ingvar,

        I see, thanks for the info. 🙂 Didn't think of containers for that use case, neat workaround.

        By the way, it just appeared to me that the SDK example in source/datatype/datatype.cpp actually
        does what you want, exposing the parameters to XPresso. It lacks the comments completely,
        though. I'll still be making an example.

        Best,
        -Niklas

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

          On 25/03/2014 at 16:46, xxxxxxxx wrote:

          Hi Niklas,
          I found the datatype.cpp example some weeks ago. And I have turned the datatype.cpp inside out, upside down, das ganze auf den Kopf gestellt - I still do not see how that can help me communicate with the custom GUI.
          For the User data - I can understand its purpose, but not for the communication between a BaseTag and a CustomGui.

          Please note this: We might be talking about different things.
          It is not about the User Data, like the image you posted above. It is about making a Custom Gui for my tag. I want to make a custom gui, like the SplineData GUI, just as an example.
          My concern is the communication between the BaseTag and the CustomGui. Which I somehow have solved, using the BaseContainer.

          But let us look at the SplineData Custom Gui.
          If I had Maxon's soure code for this, I might understand how it works. Have you seen all the code you need to write in order to programmatically add knots to the SplineData Custom GUI?  
          I know how to write the code in C++ for doing this, add knots and set the tangents. Because I found the source code for doing this here in this forum, or elsewhere on the Internet.
          But I have absolutely no clue whatsoever why it has to be done this way.

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

            On 01/04/2014 at 11:33, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            Hi Niklas,
            I found the datatype.cpp example some weeks ago. And I have turned the datatype.cpp inside out, upside down, das ganze auf den Kopf gestellt - I still do not see how that can help me communicate with the custom GUI.
            For the User data - I can understand its purpose, but not for the communication between a BaseTag and a CustomGui.

            Please note this: We might be talking about different things.
            It is not about the User Data, like the image you posted above. It is about making a Custom Gui for my tag. I want to make a custom gui, like the SplineData GUI, just as an example.
            My concern is the communication between the BaseTag and the CustomGui. Which I somehow have solved, using the BaseContainer.

            But let us look at the SplineData Custom Gui.
            If I had Maxon's soure code for this, I might understand how it works. Have you seen all the code you need to write in order to programmatically add knots to the SplineData Custom GUI?  
            I know how to write the code in C++ for doing this, add knots and set the tangents. Because I found the source code for doing this here in this forum, or elsewhere on the Internet.
            But I have absolutely no clue whatsoever why it has to be done this way.

            Hi ingvar, I am working on an example for you. Your BaseContainer approach is not bad at all
            actually, less work than implementing your own CustomDataType.

            The only way to communicate between your tag and your CustomGUI is by passing the appropriate
            data from the tag to your CustomGUI. You solved it with a BaseContainer, the SplineGUI has its
            own CustomDataType.

            The BitmapButtonCustomGui is a very good example for this. Its custom datatype has a pointer
            to the BaseList2D (in your case the tag) that uses the custom GUI. The Custom GUI uses this
            pointer to invoke the MSG_DESCRIPTION_GETBITMAP message on it.

            Originally posted by xxxxxxxx

            Have you seen all the code you need to write in order to programmatically add knots to the SplineData Custom GUI?

            I don't think I do understand what you mean. I don't see where there is much code to write
            to add knots to a SplineData. Would you mind pointing that out for me?

            Best,
            -Niklas

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

              On 01/04/2014 at 12:51, xxxxxxxx wrote:

              Hi Niklas,
              where can I find the source code for the BitmapButtonCustomGui?

              Originally posted by xxxxxxxx

              I don't think I do understand what you mean. I don't see where there is much code to write
              to add knots to a SplineData.

                  GeData gdSplineData(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE);                             //Stores the data gotten from SplineData
                  SplineData *spd = (SplineData* )gdSplineData.GetCustomDataType(CUSTOMDATATYPE_SPLINE); //Creates an instance of the SplineData class
                  if (!spd) 
                    return;
              //    spd->SetUserCallback(FooGetUserCallback(3, NULL), NULL);  
                  
                  CustomSplineKnot *knot1;   //The first spline knot
                  CustomSplineKnot *knot2;   //The second spline knot
                
                  spd->MakeLinearSplineBezier(2);
                  
                  //Real xmin, Real xmax, Real xsteps, Real ymin, Real ymax, Real ysteps
                  spd->SetRange(0.0, 1.0, 0.01, 0.0, 1.0, 0.01);
                
                  //Set The first spline knot's position to 0,0,0
                  knot1 = spd->GetKnot(0);
                  knot1->vPos = Vector(0, 0, 0);
                  knot1->lFlagsSettings |= FLAG_KNOT_LOCK_X|ADD_KNOT_ADAPT_TANGENTS;
                  knot1->vTangentRight = Vector(0.2, 0.1, 0);
                
                  //Set The second spline knot's position to 100,100,0
                  knot2 = spd->GetKnot(1);
                  knot2->vPos = Vector(1, 1, 0);
                  knot2->lFlagsSettings |= FLAG_KNOT_LOCK_X|ADD_KNOT_ADAPT_TANGENTS;
                  knot2->vTangentLeft = Vector(-0.3, 0.3, 0);
                
                  Bool success = node->SetParameter(FOO_SPLINE, gdSplineData,
              	 DESCFLAGS_SET_0);
              

              Maybe it is the naming convention in C4D that collides with my way of thinking. But I still do not understand how to write my own Custom Data type, and use it the way it is being used for SplineData. I spent many (too many) hours trying to do it myself, but it will always crash at some stage, and not do what SplineData does.

              A working example would be just great! Keep it simple! Do not introduce new things that are not strictly necessary to explain things. What also is needed (in my opinion) is an overall description of what the various classes / structures do, what their purposes are, what roles they play and so on. I have read the SDK docs, regarding this. But I did not get much wiser than I was when I started.

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

                On 07/04/2014 at 08:33, xxxxxxxx wrote:

                Hi Ingvar,

                Ok, I see it's quite a few lines of code. But since you say, you do not understand why it is so much
                to write, how would you expect such an interface to look like?

                I tried to keep it as simple as possible, but the example involves 4 classes, 3 of them Cinema 4D 
                Plugin API subclasses. Custom datatypes and GUIs are one of the most (if not the most) complex
                topic regarding plugin implementation in Cinema 4D.

                You can find the current state of your example on our new GitHub repository for the Cinema4D SDK.
                This repository will be filled slowly with better and more understandable examples, examples
                for beginners, advanced programmers and experts. The new SDK aims to replace the old one with
                greatly improved content in the future. Until then, the two SDKs will co-exist and the current main
                one will still be shipped with the Cinema 4D installation.

                Currently, the example from the repository is still missing that XPresso can read the sub channels
                from the custom datatype. I am waiting for a reply from a developer on this.

                The new SDK project is at its very beginning and there are not even Visual Studio or XCode project
                files. The example code is for the Cinema4D R15 API.

                https://github.com/PluginCafe/cpp-cinema4dsdk/tree/datatype/floatlist/src/datatype

                Source:
                https://github.com/PluginCafe/cpp-cinema4dsdk/blob/datatype/floatlist/src/datatype/floatlist.cpp

                Readme:
                https://github.com/PluginCafe/cpp-cinema4dsdk/blob/datatype/floatlist/src/datatype/floatlist.md

                Best,
                -Niklas

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

                  On 07/04/2014 at 13:43, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  Hi Ingvar,
                  Ok, I see it's quite a few lines of code. But since you say, you do not understand why it is so much
                  to write, how would you expect such an interface to look like?

                  Hallo Niklas!
                  It is not so much the code itself that I have in mind. The code is fine.
                  I have done object oriented programming for many years. I do accept that in C++ there are no properties, only methods. But I still would expect that the Custom GUI controls would be accessible, so that I could just grab it ans set the knots, just like that.

                  It is this:

                    GeData gdSplineData(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE);                             //Stores the data gotten from SplineData
                      SplineData *spd = (SplineData* )gdSplineData.GetCustomDataType(CUSTOMDATATYPE_SPLINE); //Creates an instance of the SplineData class
                      if (!spd) 
                        return;
                  

                  And this:

                  Bool success = node->SetParameter(FOO_SPLINE, gdSplineData,
                  	 DESCFLAGS_SET_0);
                  

                  which I 
                  a) Don't really understand why has to be like this
                  b) Cannot emulate myself, using my own Custom Data Type classes.
                  Where b) is my main frustration.

                  All in all:
                  When programming my C4D plugins, I use one day, where I would have used one hour in, what I would call, normal object oriented SDK. I use one week, instead of one day. etc. etc.

                  It is interesting that a new SDK is on its way!
                  Having a vibrant and flourishing 3rd party business will strengthen Maxon and Cinema 4D very much.

                  I thank you for the new code, I will look at it as soon as I get the time, and come back with comments! Give me a few days.

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

                    On 07/04/2014 at 16:59, xxxxxxxx wrote:

                    Originally posted by xxxxxxxx

                    Hallo Niklas!
                    It is not so much the code itself that I have in mind. The code is fine.
                    I have done object oriented programming for many years. I do accept that in C++ there are no properties, only methods. But I still would expect that the Custom GUI controls would be accessible, so that I could just grab it ans set the knots, just like that.

                    It is this:

                      GeData gdSplineData(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE);                             //Stores the data gotten from SplineData
                        SplineData *spd = (SplineData* )gdSplineData.GetCustomDataType(CUSTOMDATATYPE_SPLINE); //Creates an instance of the SplineData class
                        if (!spd) 
                          return;
                    

                    And this:

                    Bool success = node->SetParameter(FOO_SPLINE, gdSplineData,
                    	 DESCFLAGS_SET_0);
                    

                    which I 
                    a) Don't really understand why has to be like this
                    b) Cannot emulate myself, using my own Custom Data Type classes.
                    Where b) is my main frustration.

                    All in all:
                    When programming my C4D plugins, I use one day, where I would have used one hour in, what I would call, normal object oriented SDK. I use one week, instead of one day. etc. etc.

                    I think I understand your point now. Well, the thing is that Cinema 4D does not ship a static
                    library that plugins can be linked against. That would bring a bunch of limitations and insecurities.
                    Cinema 4D provides a runtime interface constructed on startup that the Plugin API accesses. Have
                    you ever taken a look into the resource/_api source files?

                    // c4d_basedraw.cpp
                    void BaseView::GetSafeFrame(Int32* cl, Int32* ct, Int32* cr, Int32* cb)
                    {
                    	C4DOS.Bv->GetSafeFrame(this, cl, ct, cr, cb);
                    }
                    

                    C4DOS.Bv->GetSafeFrame is a function pointer in a structure that is filled by Cinema 4D on startup.
                    Implementing classes this way is even a little more complicated. The SplineData class is a class
                    for which the actual implementation is actually hidden in the Cinema 4D application.

                    Another point is that the GeData class does not implement any special value referencing or
                    counting and is therefore passed by value , not by reference. Copying one GeData to another
                    will also copy the internal data! This is why you have to get, modify and set the value. Since
                    you do not hold the real reference of the SplineData that the object uses, you must set the
                    value back to the parameters.

                    On another note, the comments are not quire right.

                    // Create the SplineData object. The GeData communicates with Cinema 4D
                    // to find the CustomDataTypeClass implementation for the CUSTOMDATATYPE_SPLINE
                    // plugin and allocate the data ( CustomDataTypeClass::AllocData() ).
                    GeData gdSplineData(CUSTOMDATATYPE_SPLINE, DEFAULTVALUE); 
                      
                    // Get the internal SplineData from the GeData object. Here, the Plugin ID is required
                    // to verify, it is for your safety! It'll return NULL when the Plugin ID of the data-type
                    // you want doesn't match the data-type of the actual value in the GeData.
                    SplineData* spd = (SplineData* ) gdSplineData.GetCustomDataType(CUSTOMDATATYPE_SPLINE);
                    

                    There is also another way to create a SplineData, but it comes with an overhead when setting
                    the data to the node since the SplineData is 1) copied when calling SetDParameter() to the
                    GeData and 2) copied to the node when the GeData is actually set in the nodes parameters.

                    SplineData* spd = SplineData::Alloc();
                    if (spd == nullptr) ... ;
                      
                    // ...
                      
                    node->SetDParameter(SOMESPLINE, GeData(CUSTOMDATATYPE_SPLINE, spd), DESCFLAGS_SET_0);
                    

                    Originally posted by xxxxxxxx

                    It is interesting that a new SDK is on its way!
                    Having a vibrant and flourishing 3rd party business will strengthen Maxon and Cinema 4D very much.

                    I thank you for the new code, I will look at it as soon as I get the time, and come back with comments! Give me a few days.

                    Yeah, I'm confident that it'll grow very quickly! Don't hesitate to contribute if you have anything
                    that you want to contribute. 🙂 We'll just make sure that it applies our new standards for the 
                    SDK (coding style, file headers [description, experience level, tags], etc.). The guidelines will be
                    added soon.

                    Sure, tell me when there is something you need to understand. That can only help to improve
                    the example!

                    Best,
                    -Niklas

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