Get the Button GadgetID Directly Under the Mouse?
-
Hi,
I think you you mean the gadget under the mouse, do you?
-
Oh sorry for the confusion. Yes, I meant
under
the mouse. I was thinking ofhover
. -
Hi @bentraje there is no builtin way for doing it, you will have to tests each Gadget to determine which one match with the function posted in Right Click Contextual Menu on a Button?.
Final note you can retrieve the current mouse position in the message function with
if msg.GetId() == c4d.BFM_GETCURSORINFO: x = msg.GetInt32(c4d.BFM_DRAG_SCREENX) y = msg.GetInt32(c4d.BFM_DRAG_SCREENY)
Cheers,
Maxime. -
Thanks for the response. Apologies for the late response. I was trying to figure out this one:
you will have to tests each Gadget
I tried a
for loop
but theMessage
function does not seem to work with it.Is there a way around this?
You can check the illustration here:
https://www.dropbox.com/s/inizedq3rt3660f/c4d212_dynamic_rmb_context_menu.mp4?dl=0You can check the sample file here:
https://www.dropbox.com/s/hvh759wyjfiw7o7/c4d212_dynamic_rmb_context_menu.rar?dl=0 -
Its seems that GetItemDim is not properly supported by baseCustomGui ( I've to check if its a Python issue or not)
And BaseCustomGui.GetWidth seems to also not work correctly (same things I have to check if it's a Python issue).So, unfortunately, I guess in your case, the best way is to either replace the CustomGui by a GeUserArea or store the gadgetId with its coordinate + size information during the creation.
Cheers,
Maxime. -
Thanks for the response. I'm trying the later solution since I'm not that familiar with the
GeUserArea
RE: store the gadgetId with its coordinate + size information during the creation.
By this, I assume you mean moving theGeDialog.GetItemDim(id)
to theCreateLayout
function.If so, I did with this file but it has the same result as above. The dialog does not pop up and also no error.
https://www.dropbox.com/s/slyc9irbyfjj6u7/c4d212_dynamic_rmb_context_menu02.rar?dl=0 -
@bentraje said in Get the Button GadgetID Directly Under the Mouse?:
RE: store the gadgetId with its coordinate + size information during the creation.
By this, I assume you mean moving theGeDialog.GetItemDim(id)
to theCreateLayout
function.@m_adam said in Get the Button GadgetID Directly Under the Mouse?:
Its seems that GetItemDim is not properly supported by baseCustomGui ( I've to check if its a Python issue or not)
No, but since you input a size/height to draw the bitmapbutton and you store theses information in
self.width
andself.height
you can already do the checking yourself. -
I'm sorry but I'm having a hard time following.
Isn't theself.width
andself.height
a bit irrelevant since it doesn't contain the coordinates of the button relative to the whole dialog? Or are you referring to a different thing.RE:you can already do the checking yourself.
I believe this satisfies the checking
if self.IsPositionOnGadget(gadgetId=button_id, buttonData = self.button_data_list[idx], buttonx=x, y=y):
It works on a standalone but it doesn't with a
for loop
-
First of all sorry for the confusion I forget GetItemDim should be called within BFM_INTERACTSTART so that's why I didn't success previously to get it working.
Here is the method
function_to_determine_gadgetId_under_mouse_cursor
.def function_to_determine_gadgetId_under_mouse_cursor(self, x, y): for gadgetId in self.btn_id_list: if self.IsPositionOnGadget(gadgetId, x, y): return gadgetId
Now there are several issues in your code, and while I understand you may be a beginner remember we are not here to debug your code or even develop for you so please next time try to double-check your code.
@bentraje said in Get the Button GadgetID Directly Under the Mouse?:
def menu(self): self.menu = c4d.BaseContainer() for menu_item in self.menu_list: counter = 0 IDM_MENU = c4d.FIRST_POPUP_ID + counter self.menu.InsData(IDM_MENU, menu_item) counter += 1
Call this method another name than a member variable name, otherwise, Python has no way to know which one is the good one (or I would say, as soon as you do self.menu = Something you override the value).
Keep in mind in Python everything is an object (variable, function everything) and everything can be overridden (almost). So please rename this function or your variable.@bentraje said in Get the Button GadgetID Directly Under the Mouse?:
def CreateLayout(self): green_button = ColorButton() green_button.create(self, w=50,h=50,color=(0,0,255), btn_id=7000) green_button.menu_list = ['Menu8', 'Menu9'] self.btn_id_list.append(blue_button.btn_id) self.class_btn_id_dict[8000] = green_button
You passed wrong instance and an already used Id.
green_button = ColorButton() green_button.create(self, w=50, h=50, color=(0, 0, 255), btn_id=7000) green_button.menu_list = ['Menu8', 'Menu9'] self.btn_id_list.append(green_button.btn_id) self.class_btn_id_dict[8000] = green_button
@bentraje said in Get the Button GadgetID Directly Under the Mouse?:
res = c4d.gui.ShowPopupDialog(cd=self, bc=menu, x=x+l2s['x'], y=y+l2s['y'])
This should be
bc=button_class.menu
.Cheers,
Maxime. -
Hi @m_adam
Thanks for the patience. Your suggestions and reminders works are greatly appreciated.
I guess the confusion stems mainly on my part because I posted slightly two different codes. You were responding to my initial post but I was thinking with the code from the succeeding post(the one in the rar file). Totally my bad.
Anyhow, here is the working code (using the initial post) which works as I expected:
import c4d class ColorButton(object): def __init__(self): self.width = None self.height = None self.color = None self.color = None self.btn_id = None self.menu_list = None def create(self, dlg, w, h, color, btn_id): self.width = w self.height = h self.color = color self.btn_id = btn_id bmp_color = c4d.bitmaps.BaseBitmap() bmp_color.Init(w, h) for y in xrange(w): for x in xrange(h): bmp_color.SetPixel(x, y, color[0], color[1], color[2]) bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True bmp_btn = dlg.AddCustomGui(self.btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER | c4d.BFV_CENTER, w, h, bcBitmapButton) bmp_btn.SetImage(bmp_color, True) def create_menu(self): self.menu = c4d.BaseContainer() for menu_item in self.menu_list: counter = 0 IDM_MENU = c4d.FIRST_POPUP_ID + counter self.menu.InsData(IDM_MENU, menu_item) counter += 1 class MyDialog(c4d.gui.GeDialog): def __init__(self): self.btn_id_list = [] self.class_btn_id_dict = {} def CreateLayout(self): red_button = ColorButton() red_button.create(self, w=50,h=50,color=(255,0,0), btn_id=6000) red_button.menu_list = ['Menu1', 'Menu2', 'Menu3'] self.btn_id_list.append(red_button.btn_id) self.class_btn_id_dict[6000] = red_button blue_button = ColorButton() blue_button.create(self, w=50,h=50,color=(0,0,255), btn_id=7000) blue_button.menu_list = ['Menu4', 'Menu5', 'Menu6', 'Menu7'] self.btn_id_list.append(blue_button.btn_id) self.class_btn_id_dict[7000] = blue_button green_button = ColorButton() green_button.create(self, w=50,h=50,color=(0,255,0), btn_id=8000) green_button.menu_list = ['Menu8', 'Menu9'] self.btn_id_list.append(green_button.btn_id) self.class_btn_id_dict[8000] = green_button return True def IsPositionOnGadget(self, gadgetId, x, y): # Be sure that the windows is opened, # in our case since we call it in BFM_INTERACTSTART it's ok buttonData = self.GetItemDim(gadgetId) if not buttonData["x"] < x < buttonData["x"] + buttonData["w"]: return False if not buttonData["y"] < y < buttonData["y"] + buttonData["h"]: return False return True def function_to_determine_gadgetId_under_mouse_cursor(self, x, y): for gadgetId in self.btn_id_list: if self.IsPositionOnGadget(gadgetId, x, y): return gadgetId def Message(self, msg, result): if msg.GetId() == c4d.BFM_ADJUSTSIZE: self._x = msg[3] # Retrieve Y size of the GeDialog self._y = msg[4] # Retrieve Y size of the GeDialog # We are on the main thread here elif msg.GetId() == c4d.BFM_INTERACTSTART: c4d.StopAllThreads() state = c4d.BaseContainer() self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state) if state.GetInt32(c4d.BFM_INPUT_VALUE) == True: x = state.GetInt32(c4d.BFM_INPUT_X) y = state.GetInt32(c4d.BFM_INPUT_Y) g2l = self.Global2Local() x += g2l['x'] y += g2l['y'] gadgetId = self.function_to_determine_gadgetId_under_mouse_cursor(x=x,y=y) if gadgetId in self.btn_id_list: if self.IsPositionOnGadget(gadgetId=gadgetId, x=x, y=y): button_class = self.class_btn_id_dict[gadgetId] button_class.create_menu() l2s = self.Local2Screen() print str(x+l2s['x']) + " :: " + str(y+l2s['y']) self.KillEvents() res = c4d.gui.ShowPopupDialog(cd=self, bc=button_class.menu, x=x+l2s['x'], y=y+l2s['y']) return True return c4d.gui.GeDialog.Message(self, msg, result) if __name__ == "__main__": dlg = MyDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=20304050)