It works now. Surprisingly I just restarted the PC and I did not changed the python plugin script! I worked for three days on this menu problem and restarted the PC (Windows 64 10 bit) every morning. During that time I did not do any other changes to the OS or Cinema4D (R21 and R23) settings / plugins or Python or similar. Restarting now a couple of times did not go back to the erroneous behavior. So about the final outcome I am half happy and half unhappy.
Latest posts made by Chris Chris
-
RE: Add menu item to existing submenu in Python
-
RE: Add menu item to existing submenu in Python
Hello Manuel,
The line
customMenu = None
came accidentally in when cleaning up the code for posting. It is not in the actual code. Sorry for the confusion. My current code revision:
def GetMenuContainer(name, mainMenu=None): "searches a submenu in given menu basecontainer. Uses toplevel menu if mainMenu is None. Returns False if not found." # get top level menu if not mainMenu: mainMenu = c4d.gui.GetMenuResource("M_EDITOR") # search for submenu or entry for bcMenuId, bcMenu in mainMenu: #print("bcMenuId " + str(bcMenuId) + " bcMenu " + str(bcMenu)) if bcMenu != 1: #print(bcMenu[c4d.MENURESOURCE_SUBTITLE]) if bcMenu[c4d.MENURESOURCE_SUBTITLE] == name: return bcMenu #return mainMenu.InsData(c4d.MENURESOURCE_SUBTITLE, name) # create return None def AddMenuEntry(menu, plugin_id): "add a menu command to given menu basecontainer and returns True on success, else False." plugin_cmd = "PLUGIN_CMD_{0}".format(plugin_id) menu.InsData(c4d.MENURESOURCE_COMMAND, plugin_cmd) return c4d.gui.SearchMenuResource(menu, plugin_cmd) def EnhanceMenu(): # search our submenu and add an entry for this script ok = False menu = GetMenuContainer("MyMenu", None) if menu: menu = GetMenuContainer("MySubmenu2", menu) if menu: ok = AddMenuEntry(menu, MY_COMMAND_ID) # if that failed because user has moved the (sub)menu then add it to default plugin menu if not ok: menu = c4d.gui.SearchPluginMenuResource() if menu: ok = AddMenuEntry(menu, MY_COMMAND_ID) if not ok: print("Unable to register menu command: " + c4d.plugins.GeLoadString(IDS_XXX)) c4d.gui.UpdateMenus() def PluginMessage(id, data): if id == c4d.C4DPL_BUILDMENU: EnhanceMenu()
I read your linked forum post and had already made experiments with recreating the menu structure and will give it another try.
I encourage Maxon to simplify things for Python here.
Kind Regards,
Chris -
RE: Add menu item to existing submenu in Python
I noticed when I add a submenu it is created in the correct place. The code:
# create new menu item #customMenu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_" + str(MY_COMMAND_ID)) menu = c4d.BaseContainer() menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_" + str(MY_COMMAND_ID)) customMenu.InsData(c4d.MENURESOURCE_SUBMENU, menu)
But it is not what I want.
-
Add menu item to existing submenu in Python
Hello,
I have two C++ plugins which register lots of menu entries. These are not generated under the usual "Extensions" / custom plugin menu, but in an own top level menu and its submenus. That works and look like that:
MyMenu MySubmenu1 MyMenuItem1 MySubmenu2 MyMenuItem2
Now I want to register a
Python
script to add a menu item after MyMenuItem2, but it appears after MyMenuItem1.MyMenu MySubmenu1 MyMenuItem1 MyMenuItem3 // here it appears, created from Python MySubmenu2 MyMenuItem2a MyMenuItem2b MyMenuItem2c *MyMenuItem3* // here it should appear
I used the official example for building menus and an older forum post How to add a plugin to a toolbar menu?
My code is
def EnhanceMenu(): # getting the main menu resource container menu = c4d.gui.GetMenuResource("M_EDITOR") # find our menu customMenu = None for bcMenuId, bcMenu in menu: #print(" " + str(bcMenuId) + " " + str(bcMenu)) if bcMenu != 1: #? #print(bcMenu[c4d.MENURESOURCE_SUBTITLE]) if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "MyMenu": customMenu = bcMenu #customMenu = menu.GetContainerInstance(bcMenuId) break print(customMenu) # find our submenu customMenu = None menu = customMenu for bcMenuId, bcMenu in menu: if bcMenu != 1: #? #print(" " + str(bcMenuId) + " " + str(bcMenu)) #print(bcMenu[c4d.MENURESOURCE_SUBTITLE]) if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "MySubMenu2": customMenu = bcMenu break print(customMenu) # test debug output submenu content menu = customMenu for bcMenuId, bcMenu in menu: if bcMenu != 1: #? print(" " + str(bcMenuId) + " " + str(bcMenu)) print(bcMenu[c4d.MENURESOURCE_SUBTITLE]) print(bcMenu[c4d.MENURESOURCE_STRING]) # create new menu item customMenu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_" + str(MY_COMMAND_ID)) c4d.gui.UpdateMenus() def PluginMessage(id, data): if id == c4d.C4DPL_BUILDMENU: EnhanceMenu()
I know the code is a bit redundant and I compare the menu text instead of the id, but there was not id set in C++. Worth to mention is that the test debug out submenu content prints
4 MySubMenu2 i t 3 PLUGIN_CMD_1000001 I N 3 PLUGIN_CMD_1000002 I N 3 PLUGIN_CMD_1000003 I N
The expected strings should be MyMenuItem2a, MyMenuItem2b and MenuItem2c instead of single letters. The commands are correct. And why is MyMenuItem3 within MySubmenu1?
Has someone any idea?
Chris
-
RE: GetDocumentPath() returning wrong path?
Hi @ferdinand,
Your explanation and the given example solved all problems. I don't know why I did not found that earlier.
Thanks,
Chris -
RE: GetDocumentPath() returning wrong path?
Hello @ferdinand,
Thanks for answering. Yes, I have overseen to copy the line
BaseDocument* pDoc = node->GetDocument();
and will add it to the original posting. So the path to the currently saved document is not valid while saving, but after saving. Ok.
About the second part: I wonder where in code and why the QuestionDialog about complaining missing asset(s) while saving is triggered.
It might be in Cinema4D or in our plugin, but I can't find it for days. It appears directly after the message
MSG_GETALLASSETS
(Link) is done and before the next message comes in.Kind Regards,
Chris -
GetDocumentPath() returning wrong path?
Hello,
I like to know the path to the document when the user does a "Save With Assets" command.
class MyObject : public ObjectData { Bool MyObject::Message(GeListNode* node, Int32 type, void* data) { if (type == MSG_GETALLASSETS) { BaseDocument* pDoc = node->GetDocument(); // modified after initial post Filename fullDocPath = pDoc->GetDocumentPath() + pDoc->GetDocumentName(); } } }
Saving with assets the first time reports the correct path. Saving with assets a second time reports the previous path, which is wrong.
The doc says:
When “Save Project with Assets” is invoked, everything is moved to the new target directory. In this case all absolute paths must be converted to just filenames because the files are next to the document and the absolute paths are not needed anymore.
MSG_GETALLASSETS
andMSG_MULTI_CLEARSUGGESTEDFOLDER
AssetData *assetData = static_cast<AssetData*>(data); Filename myAsset = ... assetData->Add(myAsset.GetFile());
So I removed the path before adding assets to the assetData. But then the assets are not written to disk and Cinema4D pops up a message box complaining the assets cannot be found (
IDS_PAI_CONSOLIDATE_QUESTION_LOCATION
orIDS_TEXLACK
). Why? What is my understanding is that the handler forMSG_MULTI_CLEARSUGGESTEDFOLDER
should add the new path to my asset, not remove it because this was already done inMSG_GETALLASSETS
?I am using Cinema4D R21, but can also test on R23.
Kind Regards,
Chris -
RE: How to set Roughness texture to material?
Hello Maxime,
Thanks for fixing the category for my post. I am new to Cinema4D.
I found the correct IDs by opening the UI for the material and drag and drop the settings into the Python console.Kind Regards,
Chris -
How to set Roughness texture to material?
Hello,
I want to set in a standard material the four textures Roughness, Reflection Strength, Specular Strength and Bump Strength in C++. Already working is setting the roughness value with REFLECTION_LAYER_MAIN_VALUE_ROUGHNESS and the Layer Color Brightness texture with REFLECTION_LAYER_COLOR_TEXTURE.
But I can't find the other constants. They are defined in c4d_reflection.h. How to do this?Kind Regards,
Chris