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

    First Time calling SetAction does show the Brush tool's AM

    Cinema 4D SDK
    r20 r21 c++
    3
    16
    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.
    • C4DSC
      C4DS
      last edited by C4DS

      Hi,
      Having some trouble understanding what's going on in following scenario.

      For testing purposes I have provided following implementation of two CommandData and one DescriptionToolData derived plugins. All are just dummy plugins for demonstration purposes only.
      Both CommandData plugins do activate the DescriptionToolData from their Execute method. One does so by performing a CallCommand, the other one by means of SetAction.

      1. When you select the CommandData plugin which performs the SetAction right after launching Cinema you then get the Brush tool's attributes in the Attribute Manager.
      2. Restart Cinema and do the same with the one performing the CallCommand and you'll end up with the expected tool in the Attribute Manager.
        If you now switch to another tool and then selects the SetAction plugin you will also end up with the appropriate AM.
      3. Restart Cinema, select a different tool (default scenes start with Move tool active, so select Live Selection), then select the SetAction plugin, and again the AM shows the expected tool.

      So, why is it that when starting from a default launch (no actions performed yet) will show the Brush tool in the AM when performing a SetAction?
      Is something missing in the registration of the tool plugin, or in the resource, or implementation of the tool? An if so, why is the CallCommand not affected by this?

      I am including the description files only to show they're empty (for testing purposes).

      #include "c4d.h"
      
      #define TEST_COMMAND1_PLUGIN_ID			1000001
      #define TEST_COMMAND2_PLUGIN_ID			1000002
      #define TEST_DESCRIPTIONTOOL_PLUGIN_ID	1000003
      
      // ====================================
      // CommandDatas
      // ====================================
      
      // MyCommand1 - does perform a CallCommand to active the DescriptionTool
      
      class MyCommand1 : public CommandData
      {
      	INSTANCEOF(MyCommand1, CommandData)
      
      public:
      	virtual Bool Execute(BaseDocument* doc, GeDialog* parentManager);
      };
      
      Bool MyCommand1::Execute(BaseDocument* doc, GeDialog* parentManager)
      {
      	CallCommand(TEST_DESCRIPTIONTOOL_PLUGIN_ID);
      	return true;
      }
      
      // MyCommand2 - does perform a SetAction to active the DescriptionTool
      
      class MyCommand2 : public CommandData
      {
      	INSTANCEOF(MyCommand2, CommandData)
      
      public:
      	virtual Bool Execute(BaseDocument* doc, GeDialog* parentManager);
      };
      
      Bool MyCommand2::Execute(BaseDocument* doc, GeDialog* parentManager)
      {
      	doc->SetAction(TEST_DESCRIPTIONTOOL_PLUGIN_ID);
      	return true;
      }
      
      // ====================================
      // DescriptionTool
      // ====================================
      
      class MyDescriptionTool : public DescriptionToolData
      {
      public:
      	virtual Int32				GetToolPluginId() { return TEST_DESCRIPTIONTOOL_PLUGIN_ID; }
      	virtual const String		GetResourceSymbol() { return String("MyDescriptionTool_desc"_s); } // return the resource description filename (without extension)
      
      	virtual Bool		InitTool(BaseDocument* doc, BaseContainer& data, BaseThread* bt);
      	virtual void		FreeTool(BaseDocument* doc, BaseContainer& data);
      	virtual void		InitDefaultSettings(BaseDocument* doc, BaseContainer& data);
      	virtual Int32		GetState(BaseDocument* doc);
      	virtual Bool		GetCursorInfo(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, Float x, Float y, BaseContainer& bc);
      	virtual TOOLDRAW	Draw(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, BaseDrawHelp* bh, BaseThread* bt, TOOLDRAWFLAGS flags);
      };
      
      
      Bool MyDescriptionTool::InitTool(BaseDocument* doc, BaseContainer& data, BaseThread* bt)
      {
      	if (!DescriptionToolData::InitTool(doc, data, bt))
      		return false;
      	return true;
      }
      
      void MyDescriptionTool::FreeTool(BaseDocument* doc, BaseContainer& data)
      {
      	DescriptionToolData::FreeTool(doc, data);
      }
      
      void MyDescriptionTool::InitDefaultSettings(BaseDocument* doc, BaseContainer& data)
      {
      	DescriptionToolData::InitDefaultSettings(doc, data);
      }
      
      Int32 MyDescriptionTool::GetState(BaseDocument* doc)
      {
      	return CMD_ENABLED;
      }
      
      Bool MyDescriptionTool::GetCursorInfo(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, Float x, Float y, BaseContainer& bc)
      {
      	return true;
      }
      
      TOOLDRAW MyDescriptionTool::Draw(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, BaseDrawHelp* bh, BaseThread* bt, TOOLDRAWFLAGS flags)
      {
      	return TOOLDRAW::HANDLES | TOOLDRAW::AXIS;
      }
      
      // ====================================
      // Plugin Main 
      // ====================================
      Bool PluginStart(void)
      {
      	ApplicationOutput("Test"_s);
      
      	if (!RegisterCommandPlugin(TEST_COMMAND1_PLUGIN_ID, "CallCommand"_s, 0, AutoBitmap("Test.png"_s), "MyCommand1"_s, NewObjClear(MyCommand1)))
      		ApplicationOutput("Test - failed registering CommandData");
      	if (!RegisterCommandPlugin(TEST_COMMAND2_PLUGIN_ID, "SetAction"_s, 0, AutoBitmap("Test.png"_s), "MyCommand2"_s, NewObjClear(MyCommand2)))
      		ApplicationOutput("Test - failed registering CommandData");
      
      	if (!RegisterToolPlugin(TEST_DESCRIPTIONTOOL_PLUGIN_ID, "Test - MyDescriptionTool"_s, 0, AutoBitmap("Test.png"_s), "MyDescriptionTool"_s, NewObjClear(MyDescriptionTool)))
      		ApplicationOutput("Test - failed registering DescriptionTool");
      
      	return true;
      }
      void PluginEnd(void)
      {
      }
      Bool PluginMessage(Int32 id, void * data)
      {
      	switch (id) {
      	case C4DPL_INIT_SYS:
      		if (!g_resource.Init())
      			return false;
      		return true;
      	case C4DMSG_PRIORITY:
      		return true;
      	case C4DPL_BUILDMENU:
      		break;
      	case C4DPL_ENDACTIVITY:
      		return true;
      	}
      	return false;
      }
      

      res/description/MyDescriptionTool_desc.h

      #ifndef MYDESCRIPTIONTOOL_DESC_H__
      #define MYDESCRIPTIONTOOL_DESC_H__
      
      #endif // MYDESCRIPTIONTOOL_DESC_H__
      

      res/description/MyDescriptionTool_desc.res

      CONTAINER MyDescriptionTool_desc
      {
      	NAME MyDescriptionTool_desc;
      }
      

      res/strings_en-US/MyDescriptionTool_desc.str

      STRINGTABLE MyDescriptionTool_desc
      {
      	MyDescriptionTool_desc	 "MyDescriptionTool";
      }
      
      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by

        Hi,

        I don't have a solution for you and this all sounds really weird, but have you tried to retrieve the plugin node (i.e. your description plugin) associated with the plugin id and FindPlugin at the point SetAction bugs out? If you also retrieve the node for the brush tool thingy with FindPlugin, you will at least know, that the problem is not exclusive to SetAction.

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        C4DSC 1 Reply Last reply Reply Quote 0
        • C4DSC
          C4DS @ferdinand
          last edited by

          @zipit said in First Time calling SetAction does show the Brush tool's AM:

          ... have you tried to retrieve the plugin node (i.e. your description plugin) associated with the plugin id and FindPlugin at the point SetAction bugs out? ...

          Yes, I had done that to check if the DescriptionToolData had been registered correctly.
          The obtained BasePlugin contains the expected name and ID.

          However, the Brush tool, which I originally assumed to be the "Brush modeling tool", actually seems to be the "Brush tool for painting texture" (ID = 170134). And apparently that isn't a PLUGINTYPE::TOOL but a PLUGINTYPE::COMMAND.

          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by

            Hi,

            jeah, that is all very mysterious 😉 One possible solution could be to retrieve the BasePlugin via FindPlugin (as this seems to work) and write that node to the active object manager via ActiveObjectManager_SetObject, assuming you are just after setting an active tool without the implications CallCommand comes with.

            Cheers,
            zipit

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • C4DSC
              C4DS
              last edited by

              One thing I forgot to mention is that when performing the SetAction the active tool is indeed the expected one. Except that the AM doesn't show it's attributes.

              On the other hand when performing an ActiveObjectManager_SetObject with the BasePlugin obtained via FindPlugin I do indeed get the attributes shown in the AM of the baseplugin. However, at that point the desired baseplugin is NOT the active tool.
              And doing both (SetAction and ActiveObjectManager_SetObject) does again set the desired tool, but the AM then shows the Brush tool attributes ... weird indeed.

              It seems to be also reproducible with any tool. So, I tried with the ID_MODELING_ROTATE and obtain the same weird result ... but it reduces the amount of code needed to reproduce, as I can skip the whole DescriptionToolData and all its description resource files.

              Reduced code below:

              #include "c4d.h"
              
              #define TEST_COMMAND1_PLUGIN_ID			1000001
              #define TEST_COMMAND2_PLUGIN_ID			1000002
              
              // ====================================
              // CommandDatas
              // ====================================
              
              // MyCommand1 - does perform a CallCommand to active the DescriptionTool
              
              class MyCommand1 : public CommandData
              {
              	INSTANCEOF(MyCommand1, CommandData)
              
              public:
              	virtual Bool Execute(BaseDocument* doc);
              };
              
              Bool MyCommand1::Execute(BaseDocument* doc)
              {
              	CallCommand(ID_MODELING_ROTATE);
              	return true;
              }
              
              // MyCommand2 - does perform a SetAction to active the DescriptionTool
              
              class MyCommand2 : public CommandData
              {
              	INSTANCEOF(MyCommand2, CommandData)
              
              public:
              	virtual Bool Execute(BaseDocument* doc);
              };
              
              Bool MyCommand2::Execute(BaseDocument* doc)
              {
              	doc->SetAction(ID_MODELING_ROTATE);
              	return true;
              }
              
              // ====================================
              // Plugin Main 
              // ====================================
              Bool PluginStart(void)
              {
              	ApplicationOutput("Test"_s);
              
              	if (!RegisterCommandPlugin(TEST_COMMAND1_PLUGIN_ID, "CallCommand"_s, 0, AutoBitmap("Test.png"_s), "MyCommand1"_s, NewObjClear(MyCommand1)))
              		ApplicationOutput("Test - failed registering CommandData");
              	if (!RegisterCommandPlugin(TEST_COMMAND2_PLUGIN_ID, "SetAction"_s, 0, AutoBitmap("Test.png"_s), "MyCommand2"_s, NewObjClear(MyCommand2)))
              		ApplicationOutput("Test - failed registering CommandData");
              
              	return true;
              }
              void PluginEnd(void)
              {
              }
              Bool PluginMessage(Int32 id, void * data)
              {
              	switch (id) {
              	case C4DPL_INIT_SYS:
              		if (!g_resource.Init())
              			return false;
              		return true;
              	case C4DMSG_PRIORITY:
              		return true;
              	case C4DPL_BUILDMENU:
              		break;
              	case C4DPL_ENDACTIVITY:
              		return true;
              	}
              	return false;
              }
              
              1 Reply Last reply Reply Quote 0
              • M
                m_adam
                last edited by

                Hi I can indeed confirm your issue, However, I did remember we also faced this issue during the R22 dev cycle and it is now fixed.
                I will get in touch with the development team to know if there is any workaround applicable to your code.

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 1
                • M
                  m_adam
                  last edited by m_adam

                  Dev team confirmed this issue is resolved as a side effect of the document mode merging in R22 but they didn't remember exactly why it happened.
                  I will try to take a look, but since there is an alternative (CallCommand, I know it is not optional because it screws the undo). I will put it as low prio on my side to look at and will be back (don't expect before the end of the week/start of next week).

                  Cheers,
                  Maxime.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

                  C4DSC 1 Reply Last reply Reply Quote 0
                  • C4DSC
                    C4DS @m_adam
                    last edited by C4DS

                    @m_adam
                    Sorry to say but CallCommand is not an option, as in my specific case the DescriptionTool I want to activate is a hidden plugin, and CallCommand cannot execute hidden ones.
                    I understand the fact that CallCommand cannot call hidden plugins, and I don't assume this to be a bug. But if SetAction is an issue to use, and CallCommand doesn't execute as expected ... then what is one supposed to use?

                    1 Reply Last reply Reply Quote 1
                    • ferdinandF
                      ferdinand
                      last edited by ferdinand

                      Hm,

                      I never mentioned this, because I thought it is obvious, but since the thread has somehow come to a pass: Have you ever tried to exploit the fact that selecting two tools in row seems to solve the problem? I.e. first select some dummy tool and then the tool you actually want to select?

                      Cheers,
                      zipit

                      MAXON SDK Specialist
                      developers.maxon.net

                      C4DSC 1 Reply Last reply Reply Quote 0
                      • C4DSC
                        C4DS @ferdinand
                        last edited by C4DS

                        @zipit
                        I did try to activate a tool when initializing the plugin ... didn't make any difference.

                        But to answer your actual question, I just tried the following:

                        		doc->SetAction(ID_MODELING_ROTATE);
                        		doc->SetAction(ID_MODELING_MOVE);
                        		doc->SetAction(myPluginID);
                        

                        Sadly, no difference, the brush tool still gets shown into the AM.

                        1 Reply Last reply Reply Quote 0
                        • ferdinandF
                          ferdinand
                          last edited by ferdinand

                          Hi,

                          I am not sure if we are talking about the same thing, I meant (as extra lazy pseudo-code).

                          edit: Jeah, just like that. But you could try to give Cinema some time to catch up and invoke an EventAdd() or doc->ExecutePasses between the tool activations.

                          Cheers,
                          zipit

                          MAXON SDK Specialist
                          developers.maxon.net

                          1 Reply Last reply Reply Quote 0
                          • M
                            m_adam
                            last edited by m_adam

                            Hi @C4DS I tracked it down a bit.
                            First of all this issue appears only if you are in BodyaPaint Layout mode.

                            The main problem is that in R21 and previous versions, there is 2 tool logics (For BodyPaint and for Classic one) and more problematic, 2 different attribute manager, while in S22 there is only 1 attribute manager.

                            The issue in R21 is that if there is no Mode selected, and you are in BP mode, SetAction assume that you want to define the BodyPaint Manager and command, so if you define previously the mode to a Polygon mode it will set is to the one you expect.

                            doc->SetMode(Mpoints);
                            doc->SetAction(ID_MODELING_ROTATE);
                            SyncMessage(EVMSG_TOOLCHANGED, ID_MODELING_ROTATE);
                            

                            Defining the Mode to a modeling mode and make sure to also send EVMSG_TOOLCHANGED this way the internal state of command manager for BP will also be updated(otherwise you may see the command jump).

                            Cheers,
                            Maxime.

                            MAXON SDK Specialist

                            Development Blog, MAXON Registered Developer

                            C4DSC 1 Reply Last reply Reply Quote 1
                            • C4DSC
                              C4DS @m_adam
                              last edited by

                              @m_adam said in First Time calling SetAction does show the Brush tool's AM:

                              First of all this issue appears only if you are in BodyaPaint Layout mode.

                              Nope!
                              I am simply starting the application in its default state. The default startup layout, with the default move tool selected.

                              However, I agree that in the default state the Object Model mode is active So, if I indeed perform a mode change to set it to points (probably also edges or polygons will work) I can see the SetAction bringing the expected tool settings in the AM.
                              So, this might be a solution:

                              1. Switch mode to points/edge/polygon
                              2. SetAction
                              3. Switch to orginal mode
                              1 Reply Last reply Reply Quote 0
                              • C4DSC
                                C4DS
                                last edited by C4DS

                                This works:

                                		const Int32 currentMode = doc->GetMode();
                                // only change mode if current one is different from Mpoints, Medges, Mpolygons or Mpolyedgepoint
                                		doc->SetMode(Mpoints);
                                		doc->SetAction(MYTOOL_PLUGINID);
                                		GeSyncMessage(EVMSG_TOOLCHANGED, MYTOOL_PLUGINID);
                                		doc->SetMode(currentMode);
                                

                                Thanks for the hint.

                                EDIT:
                                FYI, note that I have only tested this solution on R20, not R21, but I assume it will behave identical.

                                1 Reply Last reply Reply Quote 0
                                • M
                                  m_adam
                                  last edited by

                                  And I did test only on R21 so be sure to check again because I wasn't able to reproduce as you said with default layout in R21.

                                  Cheers,
                                  Maxime.

                                  MAXON SDK Specialist

                                  Development Blog, MAXON Registered Developer

                                  C4DSC 1 Reply Last reply Reply Quote 0
                                  • C4DSC
                                    C4DS @m_adam
                                    last edited by

                                    @m_adam said in First Time calling SetAction does show the Brush tool's AM:

                                    And I did test only on R21 so be sure to check again because I wasn't able to reproduce as you said with default layout in R21.

                                    Cheers,
                                    Maxime.

                                    I am using R21.207 and with default layout see the brush tool in the AM (identical to what happens with R20.059). For safety, I have now tested your solution on R21 and works as expected.

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