placing a plugin under the File Menu



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/07/2012 at 00:46, xxxxxxxx wrote:

    In order to post pictures (etc) you must go to the full editor (Full Reply Editor) when creating a message (at the top icon bar of the Message: in the Quick Reply section).

    Also note that if you Edit Post your current post you go directly to the Full Reply Editor. :)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/07/2012 at 01:20, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Is there a way to do that in C++?  If you go to tools4d, that developer created a restart functionality that shows up everytime under the file menu.

    Maybe look at GetMenuResource() and the main.cpp file in the SDK examples. Possibly it's done using this and the message C4DPL_BUILDMENU in PluginMessage()?

    Steve



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/07/2012 at 10:10, xxxxxxxx wrote:

    I'm sorry I have to say this. But the search option in this forum really sucks.
    There are times when I know the subject has been covered. Yet it doesn't get found. Even with an advanced search.
    I think there's a lot of good information that is getting wiped out from this forum.

    Anyway. With the ranting over and out of the way.
    This is some menu code that I know I got from here. Yet won't come up with a search.
    This code is how to search through the menus:

        BaseContainer *bc = GetMenuResource(String("M_EDITOR"));  //Gets the items under the M_EDITOR section  
      if (!bc) return NULL;  
      
      LONG id;  
      GeData *last = NULL, *dat;  
      BrowseContainer browse(bc);                              //A built in function for iterating containers(Can't edit containers with it)   
      while (browse.GetNext(&id,&dat))  
      {  
      if(id==MENURESOURCE_SUBMENU)                             //Gets the submenu items of M_EDITOR  
       {  
          BaseContainer *dc = dat->GetContainer();             //Gets the container for the Gedata and assign a variable to it   
          String names = dc->GetString(MENURESOURCE_SUBTITLE); //Gets the names of the submenu items  
          GePrint(names);  
          if(dc && dc->GetString(MENURESOURCE_SUBTITLE)=="IDS_EDITOR_FILE") //If the container exists and we find this menu name in it  
           {  
            GePrint("found the IDS_EDITOR_FILE submenu");  
            last = dat;  
            break;  
           }  
       }  
      }
    

    The problem is I don't know how to go one step deeper and get the individual items inside of the File menu. Then add your own item to the list.
    I can only get TO the File menu..which is a submenu of M_EDITOR.
    So this code is not complete enough to add your own file->menu item.😢

    For adding a new custom menu to the top menu bar. That's easier:

    //This code creates a new main menu at the top of the C4D UI interface when C4D starts up  
    //This method is found in the main.cpp file  
    //NOTE: you also need to uncomment EnhanceMainMenu(); found in the Bool PluginMessage(LONG id, void *data) method's switch statement  
      
    void EnhanceMainMenu(void)   
    {  
      // do this only if necessary - otherwise the user will end up with dozens of menus!  
      
      BaseContainer *bc = GetMenuResource(String("M_EDITOR"));    //Gets the items under the M_EDITOR section  
      //BaseContainer *bc = GetMenuResource(String("M_CONSOLE")); //Gets the items under the M_CONSOLE section  
      if (!bc) return;  
      
      GeData *last = SearchPluginSubMenuResource();      
      LONG value = last->GetLong();  
      GePrint(LongToString(value));  
      
      BaseContainer sc;  
      sc.InsData(MENURESOURCE_SUBTITLE,String("MyMenu"));       //Adds a new menu entry to the UI in memory only      
      if (last) bc->InsDataAfter(MENURESOURCE_STRING,sc,last);   //Adds the new menu to the UI  
      UpdateMenus(); //Updates the menu changes  
        
    }
    

    However.
    Once you have that new menu. I have no idea how to add your plugin as a child of that custom menu.
    So there's a lot of missing information on this subject that might be lost somewhere in the forum archives.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 31/07/2012 at 03:46, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    The problem is I don't know how to go one step deeper and get the individual items inside of the File menu. Then add your own item to the list.
    I can only get TO the File menu..which is a submenu of M_EDITOR.

    To go one step deeper you have to browse the submenu container (when it's a MENURESOURCE_SUBMENU) and you get the individual items that can be: MENURESOURCE_SEPERATOR, MENURESOURCE_COMMAND or MENURESOURCE_SUBMENU.
    Here is how to add new items in the "File" menu:

    if (!fileMenu) return; // This is the container you get with MENURESOURCE_SUBMENU
      
    LONG sep = 0;
      
    bc = fileMenu->GetContainer();
    BrowseContainer browseFileMenu(bc);
    while (browseFileMenu.GetNext(&id,&dat))
    {
        if(id==MENURESOURCE_SEPERATOR)
        {
            sep++; // Count number of seperator to insert our items after
            if (sep==4)
            {
                GeData item;
      
                item.SetString(String("PLUGIN_CMD_1000472")); // Set data with ActiveObject command plugin ID string
                GeData *last = bc->InsDataAfter(MENURESOURCE_COMMAND,item,dat); // Add ActiveObject command to menu
      
                item.SetLong(TRUE); // Set data to TRUE to enable separator
                bc->InsDataAfter(MENURESOURCE_SEPERATOR,item,last); // Add separator item
      
                break;
            }
        }
    }
    

    Originally posted by xxxxxxxx

    Once you have that new menu. I have no idea how to add your plugin as a child of that custom menu.

    The above example illustrates this. To add your plugin as a menu item you just need to insert a MENURESOURCE_COMMAND with a string formated "PLUGIN_CMD_YOURPLUGINID".



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 31/07/2012 at 09:10, xxxxxxxx wrote:

    Thanks for filling in the missing parts Yannick.
    But I keep getting tripped up when trying to make the jump from:

      
    if(dc && dc->GetString(MENURESOURCE_SUBTITLE)=="IDS_EDITOR_FILE")
    

    To your code.
    I never got the actual container for the File menu in my example. I only got as far as testing for it's name in the M_EDITOR list. And that's tripping me up.

    Once I get the actual container for the IDS_EDITOR_FILE. I think I can put it all together.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 31/07/2012 at 11:43, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Thanks for filling in the missing parts Yannick.
    But I keep getting tripped up when trying to make the jump from:

     
    if(dc && dc->GetString(MENURESOURCE_SUBTITLE)=="IDS_EDITOR_FILE")
    

    To your code.
    I never got the actual container for the File menu in my example. I only got as far as testing for it's name in the M_EDITOR list. And that's tripping me up.

    Once I get the actual container for the IDS_EDITOR_FILE. I think I can put it all together.

    In your code dc is actually the menu container.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 31/07/2012 at 12:32, xxxxxxxx wrote:

    Doh!
    Got it figured out now... I hope.😂

    Here's what my complete EnhanceMainMenu function looks like:

    void EnhanceMainMenu(void)  
    {  
      // do this only if necessary - otherwise the user will end up with dozens of menus!  
      
      BaseContainer *bc = GetMenuResource(String("M_EDITOR"));  //Gets the items under the M_EDITOR section  
      if (!bc) return;  
      
      LONG id;  
      GeData *last = NULL, *dat;  
      BrowseContainer browse(bc);                              //A built in function for iterating containers(Can't edit containers with it)  
      while (browse.GetNext(&id,&dat))                         //The browse function puts what it finds in the "dat" variable  
      {  
      if(id==MENURESOURCE_SUBMENU)                             //Gets the submenu items of M_EDITOR  
       {  
         BaseContainer *dc = dat->GetContainer();              //Gets the container that's inside of the dat variable  
      
         LONG sep = 0;  
       
         BrowseContainer browseFileMenu(dc);  
         while (browseFileMenu.GetNext(&id,&dat))  
         {  
           if(id==MENURESOURCE_SEPERATOR)  
           {  
              sep++;                                                            // Count number of seperators to insert our items after  
              if (sep==4)  
              {  
                GeData item;  
      
                item.SetString(String("PLUGIN_CMD_1000472"));                   // Set data with ActiveObject command plugin ID string  
                GeData *last = dc->InsDataAfter(MENURESOURCE_COMMAND,item,dat); // Add ActiveObject command to menu  
      
                item.SetLong(TRUE);                                             // Set data to TRUE to enable separator  
                dc->InsDataAfter(MENURESOURCE_SEPERATOR,item,last);             // Add separator item  
                break;  
              }  
           }  
         }        
       }  
      }     
    }
    

    Thanks for the help Yannick.
    Does this give you what you need James?

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/08/2012 at 15:23, xxxxxxxx wrote:

    Guys,
    Thank you so much for all that you've done.  Unfortunately, I am on a freelance gig until tomorrow so I won't be able to completely apply this to my code until then.  I will update then when I put your code into mine.

    You guys are an awesome help and a great resource.  Thank you!



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 01/08/2012 at 17:38, xxxxxxxx wrote:

    For the sake of completeness.
    Here's also an example of how to add your own custom menu to C4D.

    //This code creates a new menu at the top of the C4D UI interface when C4D starts up  
    //This method is found in the main.cpp file  
    //NOTE: you also need to uncomment EnhanceMainMenu(); found in the Bool PluginMessage(LONG id, void *data) method's switch statement  
      
    void EnhanceMainMenu(void)   
    {  
      // do this only if necessary - otherwise the user will end up with dozens of menus!  
      
      BaseContainer *bc = GetMenuResource(String("M_EDITOR"));    //Gets the items under the M_EDITOR section  
      //BaseContainer *bc = GetMenuResource(String("M_CONSOLE")); //Gets the items under the M_CONSOLE section if desired  
      if (!bc) return;  
      
      GeData *last = SearchPluginMenuResource();                 //The last menu item in the plugins menu  
                                                                 //This will be used later to tell the new menu where to be inserted, relative to the last plugins menu item  
      
      BaseContainer tempbc;                                      //Create an empty container to temporarily create and hold a new menu before transfering it to the container "bc"  
      tempbc.InsData(MENURESOURCE_SUBTITLE,String("MyMenu"));    //Adds a new M_EDITOR->sub menu item to the container using a string value  
      bc->InsDataAfter(MENURESOURCE_STRING,tempbc,last);         //Adds the menu item in the sc container to the original M_EDITOR conatiner(Adds a new menu)  
                                                                 //The new menu is added after the last plugins menu item (to the right of the plugins menu)      
      UpdateMenus();                                             //Updates the menu changes  
      
      LONG id;  
      GeData *dat;  
      BrowseContainer browse(bc);                              //A built in function for iterating containers(Can't edit containers with it)   
      while (browse.GetNext(&id,&dat))                         //The browse function puts what it finds in the "dat" variable  
      {    
         BaseContainer *dc = dat->GetContainer();              //Gets the container that's inside of the dat variable  
         String names = dc->GetString(MENURESOURCE_SUBTITLE);  //Gets the names of all of the menus listed under the M_EDITOR parent menu  
         //GePrint(names);  
         if(names == "MyMenu")  
         {   
           GeData item;  
           item.SetString(String("PLUGIN_CMD_1000001"));                   //Adds our plugin into the item variable using our plugin's ID# string value  
           GeData *last = dc->InsDataAfter(MENURESOURCE_COMMAND,item,dat); //Adds the plugin to the C4D menu bar...Next to the plugins menu  
           dc->InsDataAfter(MENURESOURCE_SEPERATOR,item,last);             //Adds a separator to the menu after our new plugin entry  
           break;                                                          //No Need to loop anymore ...So break out of the loop  
         }  
      }  
      
    }
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 02/08/2012 at 01:03, xxxxxxxx wrote:

    Also, here's the complete code for the EnhanceMainMenu() version adding items in the File menu (based on Scott's code, I posted part of the code above) :

    void EnhanceMainMenu(void)
    {
        BaseContainer *bc = GetMenuResource(String("M_EDITOR"));
        if (!bc) return;
      
        LONG id;
        GeData *fileMenu = NULL, *dat;
        BrowseContainer browse(bc);
        while (browse.GetNext(&id,&dat))
        {
            if(id==MENURESOURCE_SUBMENU) // Filter submenus
            {
                BaseContainer *dc = dat->GetContainer();
                String subtitle = dc->GetString(MENURESOURCE_SUBTITLE);
                if(dc && dc->GetString(MENURESOURCE_SUBTITLE)=="IDS_EDITOR_FILE") // Search for File submenu
                {
                    fileMenu = dat;
                    break;
                }
            }
        }
      
        if (!fileMenu) return;
      
        LONG sep = 0;
      
        bc = fileMenu->GetContainer();
        BrowseContainer browseFileMenu(bc);
        while (browseFileMenu.GetNext(&id,&dat))
        {
            if(id==MENURESOURCE_SEPERATOR)
            {
                sep++; // Count number of seperator to insert our items after
                if (sep==4)
                {
                    GeData item;
                    
                    item.SetString(String("PLUGIN_CMD_1000472")); // Set data with ActiveObject command plugin ID string
                    GeData *last = bc->InsDataAfter(MENURESOURCE_COMMAND,item,dat); // Add ActiveObject command to menu
      
                    item.SetLong(TRUE); // Set data to TRUE to enable separator
                    bc->InsDataAfter(MENURESOURCE_SEPERATOR,item,last); // Add separator item
      
                    break;
                }
            }
        }
    }
    

    The function adds "C++ SDK - Active Object Dialog" command and a separator to the File menu.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 07/08/2012 at 09:41, xxxxxxxx wrote:

    Ok guys, I apologize for the lateness of this reply.  I had some freelance gigs that just finished up so I have roughly a couple of days to get back to this plugin dev before I go back to another gig!

    A C4D professional's work is never done :)

    I just wanted to thank everyone for these posts!  I got it working perfectly.

    I did however have to go to the SDK examples and pull out the portion of the code for the function PluginMessage.  I've attached that code below for completeness of this thread (hopefully this one will get indexed correctly for future devs)

    THANKS AGAIN EVERYONE!

    Bool PluginMessage(LONG id, void *data) {
      switch (id)
      {
          case C4DPL_BUILDMENU:
              //react to this message to dynamically enhance the menu
              EnhanceMainMenu();
              break;
      }
     
      return FALSE;
      }



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 08/11/2012 at 14:38, xxxxxxxx wrote:

    Hi, I'm late to the party, but I was experimenting around with this and I had a couple questions.   I found the resource files with the names of the different menus, so I can put the entries in different ones.  I was wondering if there's a way to put a new entry is  this menu, in the bottom right, I think it's the context menu?  And if there's a way to put an entry in it, is there a way to know what property you had selected when the plugin is opened?

    Thanks,
    Dan

    Also,  is it better to post in old threads that are about a topic or start a new one?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 08/11/2012 at 21:10, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Hi, I'm late to the party, but I was experimenting around with this and I had a couple questions.   I found the resource files with the names of the different menus, so I can put the entries in different ones.  I was wondering if there's a way to put a new entry is  this menu, in the bottom right, I think it's the context menu?  And if there's a way to put an entry in it, is there a way to know what property you had selected when the plugin is opened?

    Thanks,
    Dan

    Also,  is it better to post in old threads that are about a topic or start a new one?

    This is really a different question so it should be a new thread (context menus are not related to the main menus).

    No.  You can modify the right-mouse-button context menus only when creating your own plugin that displays in the Attributes Manager (Object, Tag, Tool, Material, etc.) or in the TreeView or GeUserArea of a GeDialog of the plugin.  In the former case, you can only define actions on existing menu options (such as Edit Entry)

    You can't modify the r-m-b context menu of existing features of Cinema 4D, especially the Editor View context menu (unfortunately).



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/11/2012 at 16:08, xxxxxxxx wrote:

    Thanks Robert, I didn't realize that the main menus and context menu's were different, although it makes sense now.

    Dan


Log in to reply