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

    Seperator Tag Plugin

    SDK Help
    0
    20
    1.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 05/06/2016 at 11:16, xxxxxxxx wrote:

      I don't think you can use a non modal dialog that way.
      A tag's AM GUI is linked to the object the tag is on via descriptions. And if you did that with an Async GeDialog you would probably lock up C4D. Because GeDialogs run in the main thread. Thus blocking the user from doing anything. Even if it was set to Async.
      A dialog typically needs to execute some task/tasks and then finish. Not run continuously like an expression or a tag.
      You might be better off writing a GeDialog plugin that's in the plugins folder. And make it target the active object. Just don't try to make the dialog continuously execute like a tag.

      Here is an example of a tag plugin with a dialog.
      But the dialog is modal.

        
      //This is a sample plugin that opens a dialog when the tag is double clicked so you can attach GUI items to the tags using Coffee  
        
      //INSTRUCTIONS:  
      //Create a new folder named whatever you want  
      //Copy all of this code into a text file with the file extension .cof and put it in that folder  
      //Create a 32x32 .tif image named "plugintagicon.tif" and put it that folder  
      //Then put the folder in your C4D plugins folder  
        
        
      const var PLUGIN_ID = 10000009; // THIS id IS FOR TESTING PURPOSES ONLY!!!!  
        
      enum // Assigns id numbers to your GUI items so you don't have to create them on the fly later on  
      {  
        PLUGIN_DIALOG = 10000,  
        group1,  
        X_POSITION,  
        Y_POSITION,  
        Z_POSITION,  
        X_ROTATION,  
        Y_ROTATION,  
        Z_ROTATION,  
        METHOD_TYPE,  
        METHOD_ENABLE,  
            
        _DUMMY01_  
      };  
        
        
      //A custom method that moves and rotates the object this tag plugin is on  
      DoThis(obj, bc)  
      {  
        //Sets the position of the obj  
        var pos = obj->GetPosition();  
        pos.x = bc->GetFloat(X_POSITION);  
        pos.y = bc->GetFloat(Y_POSITION);  
        pos.z = bc->GetFloat(Z_POSITION);  
        obj->SetPosition(pos);  
        obj->Message(MSG_UPDATE);  
          
        var rot = obj->GetRotation();  
        rot.x = bc->GetFloat(X_ROTATION);  
        rot.y = bc->GetFloat(Y_ROTATION);  
        rot.z = bc->GetFloat(Z_ROTATION);  
        obj->SetRotation(rot);  
        obj->Message(MSG_UPDATE);  
      }  
        
      //////////////////////////////////  
      //The dialog class for the plugin  
      //////////////////////////////////  
      class PluginDialog : GeModalDialog  
      {  
        public:  
        var bc;  
        PluginDialog();  
        GetContainer();  
        SetContainer(_bc);  
        CreateLayout();  
        Init();    
        Command(id, msg);  
          
        private:    
        ContainerToDialog();  
        DialogToContainer();  
      }  
        
      PluginDialog::PluginDialog()   
      {   
        super();  
        bc = new(BaseContainer);  
      }  
        
      PluginDialog::GetContainer() { return bc->GetClone(); }  
      PluginDialog::SetContainer(_bc) { bc = _bc->GetClone(); }  
        
      PluginDialog::CreateLayout()  
      {  
        AddGroupBeginV(800, BFV_SCALEFIT, 1, "Position Group", 0);  
        AddGroupBorder(BORDER_GROUP_IN);  
        AddGroupBorderSpace(10, 10, 10, 10);   
        AddGroupSpace(4, 4);  
        
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "X slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"X Position",0);  
        AddEditSlider(X_POSITION, BFH_SCALEFIT, 100, 10); //id, flags, width,height  
          
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "Y slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"Y Position",0);  
        AddEditSlider(Y_POSITION, BFH_SCALEFIT, 100, 10); //id, flags, width,height  
          
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "Z slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"Z Position",0);  
        AddEditSlider(Z_POSITION, BFH_SCALEFIT, 100, 10); //id, flags, width,height  
        
        AddGroupEnd();    
        AddGroupEnd();  
        AddGroupEnd();  
        AddGroupEnd();  
        
        AddGroupBeginV(800, BFV_SCALEFIT, 1, "Rotation Group", 0);  
        AddGroupBorder(BORDER_GROUP_IN);  
        AddGroupBorderSpace(10, 10, 10, 10);   
        AddGroupSpace(4, 4);  
          
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "Y slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"Y Rotation",0);  
        AddEditSlider(X_ROTATION, BFH_SCALEFIT, 100, 10); //id, flags, width,height    
        
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "X slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"X Rotation",0);  
        AddEditSlider(Y_ROTATION, BFH_SCALEFIT, 100, 10); //id, flags, width,height   
          
        AddGroupBeginH(group1, BFH_SCALEFIT, 3, "Z slider", 0);  
        AddStaticText(0,BFH_LEFT,0,0,"Z Rotation",0);  
        AddEditSlider(Z_ROTATION, BFH_SCALEFIT, 100, 10); //id, flags, width,height  
        
        AddGroupEnd();    
        AddGroupEnd();  
        AddGroupEnd();  
        AddGroupEnd();  
        
        AddDlgGroup(DR_DLGGROUP_OK);  
        AddDlgGroup(DR_DLGGROUP_CANCEL);  
      }  
        
        
      PluginDialog::Init()  
      {   
        ContainerToDialog();  
      }  
        
      PluginDialog::ContainerToDialog()  
      {  
        //Transfer data from the container to the dialog  
        SetMeter(X_POSITION, bc->GetFloat(X_POSITION), -1000, 1000, .1); // id, value, min, max, step  
        SetMeter(Y_POSITION, bc->GetFloat(Y_POSITION), -1000, 1000, .1); // id, value, min, max, step  
        SetMeter(Z_POSITION, bc->GetFloat(Z_POSITION), -1000, 1000, .1); // id, value, min, max, step  
          
        SetRadians(X_ROTATION, bc->GetFloat(X_ROTATION), -6.28319, 6.28319, .0174533); // id, value, min, max, step  
        SetRadians(Y_ROTATION, bc->GetFloat(Y_ROTATION), -6.28319, 6.28319, .0174533); // id, value, min, max, step    
        SetRadians(Z_ROTATION, bc->GetFloat(Z_ROTATION), -6.28319, 6.28319, .0174533); // id, value, min, max, step  
          
        Enable(METHOD_TYPE, bc->GetInt(METHOD_ENABLE, FALSE));  
      }  
        
      PluginDialog::DialogToContainer()  
      {  
        //Transfer data from the dialog to the container  
        bc->SetData(X_POSITION, GetMeter(X_POSITION));  
        bc->SetData(Y_POSITION, GetMeter(Y_POSITION));  
        bc->SetData(Z_POSITION, GetMeter(Z_POSITION));  
          
        bc->SetData(X_ROTATION, GetRadians(X_ROTATION));  
        bc->SetData(Y_ROTATION, GetRadians(Y_ROTATION));  
        bc->SetData(Z_ROTATION, GetRadians(Z_ROTATION));    
        bc->SetData(METHOD_TYPE, GetItem(METHOD_TYPE));  
      }  
        
      PluginDialog::Command(id, msg)  
      {  
        DialogToContainer(); //Get the current state      
      }  
        
        
      //////////////////////  
      //The Tag's class  
      //////////////////////  
      var tagIcon;  
        
      class MyExpressionTag : ExpressionPluginTag  
      {  
        public:  
        MyExpressionTag();    
        GetID();    
        GetIcon();  
        MultipleAllowed();  
        DisplayAllowed();  
        GetHelpText();  
        Edit();  
        Execute(doc, op);    
        UseMenu();  
        GetName();  
      }  
        
      MyExpressionTag::MyExpressionTag() { super(); }  
      MyExpressionTag::GetID()               { return PLUGIN_ID; }  
      MyExpressionTag::GetIcon()             { return tagIcon; }  
      MyExpressionTag::MultipleAllowed()     { return TRUE; } //Don't allow multiple tags  
      MyExpressionTag::DisplayAllowed()      { return TRUE; }  
      MyExpressionTag::GetHelpText()         { return "My GUI Coffee Tag Plugin"; }  
      MyExpressionTag::UseMenu() { return TRUE; }  
      MyExpressionTag::GetName() { return "My GUI Tag"; }  
        
      MyExpressionTag::Edit()  
      {  
        //This function executes only when the open tag dialog is closed using the Enter action  
          
        var bc = GetContainer();  
        bc->SetData(METHOD_ENABLE, FALSE);  
        
        var dialog = new(PluginDialog);  
        dialog->SetContainer(bc);  
        dialog->Open(-1,-1);  
        
        if (dialog->GetResult())  
            SetContainer(dialog->GetContainer());  
        else return FALSE;  
        
        return TRUE;  
      }  
        
      MyExpressionTag::Execute(doc, op)  
      {      
        //This function executes when the timeline is running. Or something is changed in the scene  
        //If you need to monitor an object's current state. This is where to put the code.    
        
        DoThis(op, GetContainer());   
                  
        return TRUE;  
      }  
        
      /////////////////////////////////////////////  
      //This section registers the plugin with C4D   
      /////////////////////////////////////////////  
      main()  
      {   
        // Get the icon  
        var fn = GeGetRootFilename();  
        fn->RemoveLast();  
        fn->AddLast("plugintagicon.tif"); //<----Change this to your own image file  
        tagIcon = new(BaseBitmap,1,1);  
        tagIcon->Load(fn);  
        
        Register(MyExpressionTag);    
      }
      

      -ScottA

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

        On 06/06/2016 at 12:12, xxxxxxxx wrote:

        Originally posted by xxxxxxxx

        I don't think you can use a non modal dialog that way.
        A tag's AM GUI is linked to the object the tag is on via descriptions. And if you did that with an Async GeDialog you would probably lock up C4D. Because GeDialogs run in the main thread. Thus blocking the user from doing anything. Even if it was set to Async.
        A dialog typically needs to execute some task/tasks and then finish. Not run continuously like an expression or a tag.
        You might be better off writing a GeDialog plugin that's in the plugins folder. And make it target the active object. Just don't try to make the dialog continuously execute like a tag.

        Here is an example of a tag plugin with a dialog.

        -ScottA

        Wow, that is very, very kind of you, thank you so much. I'm very sure this will help me immensely.

        Thank you

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

          On 07/06/2016 at 04:26, xxxxxxxx wrote:

          Not 100% sure if Scott was saying the same thing: You can make the dialog exchange data with the tag,
          and the tag does its work as an expression. You can make a button in the Tag's description (ie. in the
          attribute manager) to open the dialog that edits the tag (similar to the Expression Editor for COFFEE and
          Python Tags/Python Generators).

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

            On 07/06/2016 at 07:09, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            You can make a button in the Tag's description (ie. in the
            attribute manager) to open the dialog that edits the tag).

            According to my notes. We can't do that with COFFEE. It's not supported.
            I think this question was as asked on CGTalk a long time ago. And that's where I got the "Not Supported" answer from.

            -ScottA

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

              On 07/06/2016 at 07:55, xxxxxxxx wrote:

              My bad for not recognizing it's about COFFEE. 😊 You're example that implements PluginTag::Edit()
              is probably the best available option then. 🙂

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

                On 10/06/2016 at 05:10, xxxxxxxx wrote:

                Scott & NiklasR, thank you very much for your replies and sorry for only replying now.

                It only occurred to me last night that there's a free COFFEE plugin which has a dialog setup exactly like what I want to make with mine. The dialog of Fabian's MirrorPointPosition plugin has a non-modal dialog when you double-click on the plugin. However, even though he kindly supplies the COFFEE code with his plugin, his scripting skills are so many light years beyond mine that I can't seem to figure out how he does it.

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

                  On 10/06/2016 at 08:02, xxxxxxxx wrote:

                  I took a quick look at that plugin's code. And he's doing what I said earlier about using a GeDialog to target the active object. Only he goes one step farther, and targets a custom tag on the active object.

                  The tag in his plugin is only there to hold some data.
                  C4D creates these kinds of vertex tags automatically when you make a new object. But they are hidden by default.
                  But you can also make your own tag to hold the data like he did.

                  The key components are:
                  1- GeDialog class: The non modal dialog with all the gizmos in it
                  2- Command class: Launches the GeDialog from the C4D plugins menu (hosts the GeDialog when it's closed)
                  3- ExpressionPluginTag class: The tag plugin

                  Depending on what you want to do. You might not need the tag plugin part. It's only there to hold some specific data.
                  But in any case. If you want to write plugins in any language. You will need to get a good grip on writing classes and class methods.
                  Scripts don't use classes very often. But that's what plugins are all about. Classes and methods.
                  There's a ton of tutorials about that on the internet. But it will probably take you a bit of head banging before it finally clicks. It's a necessary thing to learn to make plugins.

                  -ScottA

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

                    On 10/06/2016 at 16:23, xxxxxxxx wrote:

                    Originally posted by xxxxxxxx

                    I took a quick look at that plugin's code. And he's doing what I said earlier about using a GeDialog to target the active object. Only he goes one step farther, and targets a custom tag on the active object.

                    The tag in his plugin is only there to hold some data.
                    C4D creates these kinds of vertex tags automatically when you make a new object. But they are hidden by default.
                    But you can also make your own tag to hold the data like he did.

                    The key components are:
                    1- GeDialog class: The non modal dialog with all the gizmos in it
                    2- Command class: Launches the GeDialog from the C4D plugins menu (hosts the GeDialog when it's closed)
                    3- ExpressionPluginTag class: The tag plugin

                    Depending on what you want to do. You might not need the tag plugin part. It's only there to hold some specific data.
                    But in any case. If you want to write plugins in any language. You will need to get a good grip on writing classes and class methods.
                    Scripts don't use classes very often. But that's what plugins are all about. Classes and methods.
                    There's a ton of tutorials about that on the internet. But it will probably take you a bit of head banging before it finally clicks. It's a necessary thing to learn to make plugins.

                    -ScottA

                    Hi Scott

                    Thank you very much for having a look at the code and giving your insights.

                    I suspected that a full fledged plugin would be much more complex than the scripts I've been delving into. It appears I'll have to start looking into C++ as that will also help me overcome some of the limitations associated with COFFEE. However, just the thought of it, makes my hair stand on end. I think I'll have to follow your course on Youtube to begin with and work from there but that will have to wait untill I've got more time on my hands. Untill then I'll see if I can grasp the classes and stuff as that really makes my head spin.

                    Thanks again.

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

                      On 10/06/2016 at 17:21, xxxxxxxx wrote:

                      Many of COFFEEs limitations can be circumvented with Python already. While it's still limiting in some areas, it's certainly powerful in most others.

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

                        On 10/06/2016 at 18:00, xxxxxxxx wrote:

                        And the slight learning curve for Python and the C4D Python API is well worth the power gained over COFFEE.

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

                          On 10/06/2016 at 18:18, xxxxxxxx wrote:

                          He's stuck with R12 which doesn't support Python.
                          So Python is not an option for him guys.

                          -ScottA

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

                            On 10/06/2016 at 18:24, xxxxxxxx wrote:

                            There was Py4D but it wasn't integrated into C4D yet and probably not totally compatible with the integrated API, I agree.

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

                              On 13/06/2016 at 08:51, xxxxxxxx wrote:

                              Hey guys,

                              nice discussion you have going on here.

                              Not sure the SDK team can contribute much more here.
                              In general we recommend to use the latest version of C4D (which seems to be no option here) and from our point of view Python would be the road to go. Also we can support only the latest version of C4D. While we usually try to stretch this rule as far as possible, I'm afraid R12 or even R10.5 are completely out of our scope. Sorry.

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

                                On 13/06/2016 at 23:08, xxxxxxxx wrote:

                                Thank you to everyone who responded. I really appreciate the help & insights tremendously.

                                Originally posted by xxxxxxxx

                                Hey guys,

                                nice discussion you have going on here.

                                Not sure the SDK team can contribute much more here.
                                In general we recommend to use the latest version of C4D (which seems to be no option here) and from our point of view Python would be the road to go. Also we can support only the latest version of C4D. While we usually try to stretch this rule as far as possible, I'm afraid R12 or even R10.5 are completely out of our scope. Sorry.

                                Hi Andreas

                                I didn't intend to upset the forum guidelines so could you please clarify: Should I rather not pose questions about COFFEE scripting here? Should I rather post on a 3rd party forum like CGTalk? I don't think my question was version specific and I only mentioned my version situation so that it would be clear that I was specifically seeking COFFEE help.

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

                                  On 14/06/2016 at 00:37, xxxxxxxx wrote:

                                  Hi Uncle-Ox,

                                  I'm sorry, that wasn't my intention.
                                  You didn't upset any forum guidelines. Everything's alright. It's fine to post COFFEE questions in here. I just wanted to say, that we have no better ideas, than already discussed.
                                  And of course you are also free to discuss older versions (only partly the case here, I know), even if the SDK team might not be able to help in such cases.

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