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 29/07/2012 at 09:50, xxxxxxxx wrote:
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. I'd like to post a picture of that but I haven't figured out how to do that on this site.
-
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,
DanAlso, 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,
DanAlso, 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