Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi,
Is there a command to get the Button Gadget ID directly under the mouse? I understand that you can get the GadgetID by clicking the button but I'm using the Message() rather than Command().
Message()
Command()
In overview, I have several buttons and when you RMB them, they have there own dedicated pop-up commands. It works when I have them typed separately but I'm having a problem with making them dynamic through a class.
You can see the illustration here: https://www.dropbox.com/s/k5d38cctk4hgtz7/c4d206_get_gadgetid_under_mouse.jpg?dl=0
You can check the WIP code here:
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 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,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 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 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 = function_to_determine_gadgetId_under_mouse_cursor() 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.menu() l2s = self.Local2Screen() print str(x+l2s['x']) + " :: " + str(y+l2s['y']) self.KillEvents() res = c4d.gui.ShowPopupDialog(cd=self, bc=menu, x=x+l2s['x'], y=y+l2s['y']) return True return c4d.gui.GeDialog.Message(self, msg, result) return True if __name__ == "__main__": dlg = MyDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=20304050)
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 of hover.
under
hover
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.
@m_adam
Thanks for the response. Apologies for the late response. I was trying to figure out this one: you will have to tests each Gadget
you will have to tests each Gadget
I tried a for loop but the Message function does not seem to work with it.
for loop
Message
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=0
You 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.
Thanks for the response. I'm trying the later solution since I'm not that familiar with the GeUserArea
GeUserArea
RE: store the gadgetId with its coordinate + size information during the creation. By this, I assume you mean moving the GeDialog.GetItemDim(id) to the CreateLayout function.
GeDialog.GetItemDim(id)
CreateLayout
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?:
@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 and self.height you can already do the checking yourself.
self.width
self.height
I'm sorry but I'm having a hard time following. Isn't the self.width and self.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):
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.
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.
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.
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
res = c4d.gui.ShowPopupDialog(cd=self, bc=menu, x=x+l2s['x'], y=y+l2s['y'])
This should be bc=button_class.menu.
bc=button_class.menu
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)