Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Get the Button GadgetID Directly Under the Mouse?

    Cinema 4D SDK
    r21 python
    3
    11
    1.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      s_bach
      last edited by

      Hi,

      I think you you mean the gadget under the mouse, do you?

      MAXON SDK Specialist

      Development Blog, MAXON Registered Developer

      1 Reply Last reply Reply Quote 0
      • B
        bentraje
        last edited by

        Oh sorry for the confusion. Yes, I meant under the mouse. I was thinking of hover.

        1 Reply Last reply Reply Quote 0
        • M
          m_adam
          last edited by

          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.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          1 Reply Last reply Reply Quote 1
          • B
            bentraje
            last edited by

            @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

            I tried a for loop but the Message 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=0

            You can check the sample file here:
            https://www.dropbox.com/s/hvh759wyjfiw7o7/c4d212_dynamic_rmb_context_menu.rar?dl=0

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by

              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.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              1 Reply Last reply Reply Quote 0
              • B
                bentraje
                last edited by

                @m_adam

                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 the GeDialog.GetItemDim(id) to the CreateLayout 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

                M 1 Reply Last reply Reply Quote 0
                • M
                  m_adam @bentraje
                  last edited by m_adam

                  @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 the GeDialog.GetItemDim(id) to the CreateLayout 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 and self.height you can already do the checking yourself.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

                  1 Reply Last reply Reply Quote 1
                  • B
                    bentraje
                    last edited by

                    @m_adam

                    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):

                    It works on a standalone but it doesn't with a for loop

                    1 Reply Last reply Reply Quote 0
                    • M
                      m_adam
                      last edited by m_adam

                      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.

                      MAXON SDK Specialist

                      Development Blog, MAXON Registered Developer

                      1 Reply Last reply Reply Quote 1
                      • B
                        bentraje
                        last edited by bentraje

                        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)
                        
                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post