Getting a GadgetID during BFM_INTERACTSTART



  • Hello,
    I'd like to detect when an EditSlider gadget in my GeDialog is first being dragged. I am overriding the Message function and listening for c4d.BFM_INTERACTSTART so I can see which Gadget sent the Message. A strange thing occurs though: when I try to print the msg and result BaseContainers, neither return any values.

    I can check if the EditSlider is active using GeDialog.IsActive(), but it fires with every c4d.BFM_INTERACTSTART Message, which is undesired.

    Is there a way to detect the GadgetID from the c4d.BFM_INTERACTSTART Message?

    Here is code demonstrating my issue:

    import c4d
    from c4d import gui
    
    PLUGIN_ID=1972142
    GROUP_ID1=1000
    SLIDER=1001
    
    class MyDlg(gui.GeDialog):
        def CreateLayout(self):
            self.SetTitle("Interact Start Demo")
            if self.GroupBegin(GROUP_ID1, c4d.BFH_SCALEFIT, 1, 1):
                self.GroupBorderSpace(20,20,20,20)
                self.AddEditSlider(SLIDER, c4d.BFH_SCALEFIT | c4d.BFV_CENTER, initw=0, inith=0)
            self.GroupEnd()
            return True
    
        def InitValues(self):
            self.SetFloat(SLIDER, value=50, min=0, max=100, step=1)
            return True
    
        def Message(self, msg, result):
            if msg.GetId() == c4d.BFM_INTERACTSTART:
                print "*"*100
                #Can I get the Gadget ID from this Message?
                for cid,value in msg:
                    print "MSG id: %s, value: %s"%(cid,value)
                    #doesn't print
                for cid,value in result:
                    print "RESULT id: %s, value: %s"%(cid,value)
                    #doesn't print
                print "slider active: %s"%self.IsActive(SLIDER) #Can't use as is because it fires True with every interaction where the slider is active (not just dragging the slider).
            return c4d.gui.GeDialog.Message(self, msg, result)
    
    c4d.CallCommand(12305) # Console
    global dlg
    dlg = MyDlg()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=300, defaulth=100, xpos=-2, ypos=-2)
    

    Thank you!



  • Hi,

    I do not think that you can get the id. The reason that your code does not print anything, is because you treat the message id and data containers like iterables for a loop. Which in turn will not do anything when said containers are empty.

    Is there a specific reason why you do not (want to) use GeDialog.Command? It has a specific message for drag events of sliders (BFM_ACTION_INDRAG).

    Cheers,
    zipit



  • Hi,

    I do not think that you can get the id. The reason that your code does not print anything, is because you treat the message id and data containers like iterables for a loop. Which in turn will not do anything when said containers are empty.

    Is there a specific reason why you do not (want to) use GeDialog.Command? It has a specific message for drag events of sliders (BFM_ACTION_INDRAG).

    Cheers,
    zipit



  • Hi @zipit , thank you for your reply. I am treating the message & data containers as iterables because they are both BaseContainers and I don't know which IDs they contain. If the containers are empty, where is msg.GetId() getting its data? Is the ID separate from the msg BaseContainer's data?

    I have something working with BFM_ACTION_INDRAG but it is not very elegant as the drag ID is executed many times during a drag. As mentioned in the original post, I am interested in executing code only once on the initial touch of the slider.

    This is what I'm doing:

    import c4d
    from c4d import gui
    
    PLUGIN_ID=1972142
    GROUP_ID1=1000
    SLIDER=1001
    
    class MyDlg(gui.GeDialog):
        def __init__(self):
            self.firstInteraction = False
        
        def CreateLayout(self):
            self.SetTitle("Interact Start Demo")
            if self.GroupBegin(GROUP_ID1, c4d.BFH_SCALEFIT, 1, 1):
                self.GroupBorderSpace(20,20,20,20)
                self.AddEditSlider(SLIDER, c4d.BFH_SCALEFIT | c4d.BFV_CENTER, initw=0, inith=0)
            self.GroupEnd()
            return True
    
        def InitValues(self):
            self.SetFloat(SLIDER, value=50, min=0, max=100, step=1)
            return True
    
        def Command(self,id,msg):
            if id == SLIDER:
                if self.firstInteraction == False:
                    if msg[c4d.BFM_ACTION_INDRAG] == 1:
                        if self.firstInteraction == False:
                            print "first interaction"
                            # first interaction code goes here
                            self.firstInteraction = True
                if msg[c4d.BFM_ACTION_INDRAG] == None:
                    self.firstInteraction = False
            return True
    
    c4d.CallCommand(12305) # Console
    global dlg
    dlg = MyDlg()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=300, defaulth=100, xpos=-2, ypos=-2)
    

    Do you or anyone else have any thoughts on this implementation? Thank you!



  • Hi,

    @blastframe said in Getting a GadgetID during BFM_INTERACTSTART:

    If the containers are empty, where is msg.GetId() getting its data? Is the ID separate from the msg BaseContainer's data?

    yes, the id of a container is separate from its data. It is just an easy to access integer attached to the container which is used to tell the recipient something about the purpose of the container. What you are effectively doing is something like this:

    data = []
    #Will not do anything since the iterator of data will never yield anything.
    for item in data:
        print item
    

    I have something working with BFM_ACTION_INDRAG but it is not very elegant as the drag ID is executed many times during a drag [...]

    Aside from the crazy amount of branching I do not see anything inherently inelegant about your code. Do you have any specific concerns? Without that any suggestions for "improvement" would be highly subjective.

    Cheers,
    zipit



  • hi,

    I don't see what's wrong neither. Using a boolean to know if your function have been already execute once is pretty common.
    As long as you got what you need.

    Cheers,
    Manuel



  • Thank you both! @zipit & @m_magalhaes 😄


Log in to reply