Avoid: IsActive()



  • Hi there,

    I'm wondering, is it possible to avoid IsActive() in Message to support older C4D-Versions.

    In another thread: https://plugincafe.maxon.net/topic/11462/understanding-setcommanddragid/4 we've talked about the ability to drag BitmapButtons into the layout via SetCommandDragId.

        def CreateLayout(self):
            bc = c4d.BaseContainer()
            bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True)
            bc.SetInt32(c4d.BITMAPBUTTON_ICONID1, c4d.Ocube)
            bc.SetInt32(c4d.BITMAPBUTTON_FORCE_SIZE, 32)
            button = self.AddCustomGui(10003, c4d.CUSTOMGUI_BITMAPBUTTON, "but", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 40, 40, bc)
            button.SetCommandDragId(c4d.Ocube)
            return True
    
        def Message(self, msg, result):
            if msg.GetId() == c4d.BFM_INTERACTEND:
                if self.IsActive(10003):
                    print 'Icon clicked in the GeDialog.'
    

    Is it simply not possible to support older C4D-Versions AND have a draggable BitmapButton...?

    Thanks,
    Lasse



  • Hi @lasselauch, I will take a look, but only in few days since R18 is the minimal version working for IsActive and it's more than 3years old, while we provide support only for 2 previous release.

    But maybe there is another way to catch this kind of stuff that would work in older version so that's why I said I will take a look.

    Cheers,
    Maxime.



  • Thanks @m_adam,

    for now I've added a workaround for older versions so it's not possible to drag the buttons to the layout.

    Works for me, but would be nice to know anyway.

    Thanks,
    Lasse



  • Hi Maxime,

    I still have some problems using IsActive(). I'm having some c4d.plugins.CommandData utilizing the c4d.gui.ShowPopupDialog. Sadly sometimes the Popup will be called even after pressing the button. Happens escpially in the end of the following *.gif. (After clicking on the button, I constantly click on the Menubar, and sometimes the popup will be displayed again...)

    2020-04-07_09-36-59.gif

    My Message(self, msg, result) looks like the following:

        def Message(self, msg, result):
            if c4d.GetC4DVersion() >= 18000:
                #Handle CommandDragID
                if msg.GetId() == c4d.BFM_INTERACTEND:
                    if self.IsActive(ids.IDC_BUTTON1):
                        c4d.CallCommand(ids.PLUGIN_ID_EXPORT)
    
                    elif self.IsActive(ids.IDC_BUTTON2):
                        c4d.CallCommand(ids.PLUGIN_ID_OMCLEANER)
    
                    elif self.IsActive(ids.IDC_BUTTON3):
                        c4d.CallCommand(ids.PLUGIN_ID_PYSCRIPTS)
    
                    elif self.IsActive(ids.IDC_BUTTON4):
                        c4d.CallCommand(ids.PLUGIN_ID_RECENTFILES)
                    
                    elif self.IsActive(ids.IDC_BUTTON5):
                        c4d.CallCommand(ids.PLUGIN_ID_CHATLOG)
    
            return c4d.gui.GeDialog.Message(self, msg, result)
    

    Any ideas how to avoid or counter-act this!?

    Thanks,
    Lasse



  • May I ask in what range you enumerated your Dialog controls?
    If I recall correctly, there was this kind of behavior if the control IDs were below a certain number.



  • The ids are starting from 20001.

    IDD_DIALOG = 20001
    IDC_BUTTONFLUSHGROUP = 20002
    IDC_BUTTON1 = 20003
    IDC_BUTTON2 = 20004
    IDC_BUTTON3 = 20005
    IDC_BUTTON4 = 20006
    IDC_BUTTON5 = 20007
    

    Then of course the Commands like ids.PLUGIN_ID_EXPORT are generated PluginIDs.



  • After looking at your GIF again, it seems like the following happens:
    When checking for BFM_INTERACTEND and poking yround inyour dialog, the focus switches back to the last active Gadget. Thus your commands are fired since you are checking if the gadgets do have the focus.



  • Yeah, I guess that makes sense.
    What would be the best way to work around that behaviour?

    Shall I return return c4d.gui.GeDialog.Message(self, msg, result) after each c4d.CallCommand()?

    A simple else statement didn't work.

    Cheers,
    Lasse



  • This does not solve your initial issue since it requires the use of GetItemDim and it was introduced in R18 but here is how to avoid your second issue:

    import c4d
    
    class Dialog(c4d.gui.GeDialog):
        
        def CreateLayout(self):
            bc = c4d.BaseContainer()
            bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True)
            bc.SetInt32(c4d.BITMAPBUTTON_ICONID1, c4d.Ocube)
            bc.SetInt32(c4d.BITMAPBUTTON_FORCE_SIZE, 32)
            button = self.AddCustomGui(10003, c4d.CUSTOMGUI_BITMAPBUTTON, "but", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 40, 40, bc)
            button.SetCommandDragId(c4d.Ocube)
            self.AddStaticText(10001, 0, 0, name="test")
            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):
            # Main thread
            if msg.GetId() == c4d.BFM_INTERACTSTART:
                c4d.StopAllThreads()
    
                # Check the mouse is clicked
                state = c4d.BaseContainer()
                self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state)
    
                if state.GetInt32(c4d.BFM_INPUT_CHANNEL) != 0:
    
                    # Get coordinates
                    x = state.GetInt32(c4d.BFM_INPUT_X)
                    y = state.GetInt32(c4d.BFM_INPUT_Y)
                    g2l  = self.Global2Local() 
                    x += g2l['x']  
                    y += g2l['y']
    
                    # Checks the coordinate is within the range of the BitmapButton
                    if self.IsPositionOnGadget(10003, x, y):
                        print 'Icon clicked in the GeDialog.'
    
                        # Stop others event to be processed
                        self.KillEvents()
                        return True
                    
            return c4d.gui.GeDialog.Message(self, msg, result)
    
    # Main function
    def main():
        global dlg
        dlg = Dialog()
        dlg.Open(c4d.DLG_TYPE_ASYNC)
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    Note that there is a very similar problem Disable default Right-Click Menu that you may found interesting about how to handle popup in your dialog.

    And adding this constraint in mind, I'm afraid I don't see any solution to make it work before R18.
    Cheers,
    Maxime.



  • Thanks @m_adam for the insights!

    Works like a charm!!

    Cheers,
    Lasse