Hey @wickedp,
So, I spent some time on this but unfortunately there are also a few other things on my plate, so I did not have too much time to invest on it. Here are my findings for now:
- You are right,
::Command
is not the right way to go here, since you are effectively unable to distinguish there between right and left mouse button clicks, as the input event already has been consumed inside that method (you have to actually release the mouse button to trigger ::Command
).
- You then must go with the second approach I proposed, although poorly explained as I now see. You must instead move to
GeDialog::Message
and do the handling manually (that was what I meant with BFM_GETCURSORINFO
).
- I tried that, only to find out that in the context of
BFM_GETCURSORINFO
you are unable to poll the mouse inside ::Message
, when you poll for the right mouse button, it will always return 0
, although the button is pressed.
- But you are able to do it in the context of
BFM_INTERACTSTART
.
- There is still quite a bit to be fleshed out here, the restriction part to the actual tab header thingy, for example, but this will at least open a popup menu when RMB is being pressed (without doing the evaluation all the time for that). I cannot tell you exactly how much of the remaining way is possible, I would have to poke a bit myself.
Find the example code in Python below (sorry, I know that you are on C++, but I really did not have much time today). Just tell me when you want this to be explored further, I will then invest some time next week.
Cheers,
Ferdinand
The code:
"""Opens a popup menu over a GeDialog when the right mouse button is being pressed.
This can be run in the Script Manger.
"""
import c4d
class TabDialog (c4d.gui.GeDialog):
"""Provides a dialog with two tabs.
"""
ID_GRP_MAIN: int = 1000
ID_GRP_TABS: int = 2000
ID_GRP_TAB_FOO: int = 3000
ID_GRP_TAB_BAR: int = 3001
def CreateLayout(self) -> bool:
"""Adds the gadgets to the dialog.
"""
flags: int = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT
self.GroupBegin(TabDialog.ID_GRP_MAIN, flags, 1)
self.TabGroupBegin(TabDialog.ID_GRP_TABS, flags, c4d.TAB_TABS)
self.GroupBegin(TabDialog.ID_GRP_TAB_FOO, flags, 1, 0, "Foo")
self.GroupEnd() # ID_GRP_TAB_FOO
self.GroupBegin(TabDialog.ID_GRP_TAB_BAR, flags, 1, 0, "Bar")
self.GroupEnd() # ID_GRP_TAB_BAR
self.GroupEnd() # ID_GRP_TABS
self.GroupEnd() # ID_GRP_MAIN
return super().CreateLayout()
def Message(self, msg: c4d.BaseContainer, result: c4d.BaseContainer) -> int:
"""Opens the popup menu.
"""
# Bail when this not the start of a GUI interaction.
if msg.GetId() != c4d.BFM_INTERACTSTART:
return super().Message(msg, result)
# Poll for the right mouse button being pressed.
state: c4d.BaseContainer = c4d.BaseContainer()
if not c4d.gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state):
raise RuntimeError("Could not poll input state.")
# Bail when RMB is not being pressed.
if state[c4d.BFM_INPUT_VALUE] != 1:
return super().Message(msg, result)
# Open a popup menu at the cursor.
x: int = int(state[c4d.BFM_INPUT_X])
y: int = int(state[c4d.BFM_INPUT_Y])
bc: c4d.BaseContainer = c4d.BaseContainer()
bc.InsData(c4d.FIRST_POPUP_ID, f"Cube&i{c4d.Ocube}&")
bc.InsData(c4d.FIRST_POPUP_ID + 1, f"Sphere&i{c4d.Osphere}&")
res = c4d.gui.ShowPopupDialog(self, bc, x, y)
return super().Message(msg, result)
if __name__ == '__main__':
dialog: TabDialog = TabDialog()
dialog.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)