• Hi Guest!

    We are extremely excited to announce the release of our first Beta1.1 and the first release of our Public AddonKit!
    To participate in the Beta, a subscription to the Entertainer or Creator Tier is required. For access to the Public AddonKit you must be a Creator tier member. Once subscribed, download instructions can be found here.

    Click here for information and guides regarding the VaM2 beta. Join our Discord server for more announcements and community discussion about VaM2.
  • Hi Guest!

    VaM2 Resource Categories have now been added to the Hub! For information on posting VaM2 resources and details about VaM2 related changes to our Community Forums, please see our official announcement here.

Getting gui control from callback function

fabio

Well-known member
Joined
Jan 30, 2021
Messages
78
Reactions
286
Hi. I'm finishing some plugin but I need help with an issue. I have an indeterminate number of people on a scene (any scene) and I need to setup an UIDynamicPopup for each one. So from the code below, is there any way to get 'i' inside the callback functions? I can resolve this by creating a separate callback function for each posible person, but it must be a way to get from which popup the call is coming from.

Code:
    for(int i = 0; i < NUMBER_OF_PLEOPLE; i++)
    {
        JSONStorableStringChooser[] person[i] = new JSONStorableStringChooser("person" + i.ToString(), null, "", "", SyncAtom);
        RegisterStringChooser(person[i]);
        UIDynamicPopup dp = CreateFilterablePopup(person[i]);
        dp.popupPanelHeight = 1000f;
        dp.label = "Person #" + i.ToString();
        dp.popup.onOpenPopupHandlers += SyncAtomChocies;
    }

Code:
    // before opening the popup
    private void SyncAtomChoices()
    {
        // populate with person[i] string posibilities         (HOW DO I GET i INSIDE HERE)
    }

Code:
    // after choosing a string from the popup
    private void SyncAtom(string atomUID)
    {
        // set person[i] = atomUID                (HOW DO I GET i INSIDE HERE)
    }
 
I was hoping for some command for this but I couldn't find it. I solved it by putting the callbacks inside a helper class and passing on the index (i) on the class constructor.

Code:
        for(int i = 1; i <= NUMBER_OF_PLAYERS; i++)
        {
            DynPopupCallBack pop = new DynPopupCallBack(i);
            person[i] = new JSONStorableStringChooser("person" + i.ToString(), null, "", "", pop.SyncAtom);
            RegisterStringChooser(person[i] );
            UIDynamicPopup dp = CreateFilterablePopup(person[i]);
            dp.popupPanelHeight = 1000f;
            dp.label = "Person #" + i.ToString();
            dp.popup.onOpenPopupHandlers += pop.SyncAtomChoices;
        }

    public class DynPopupCallBack
    {
        public int i;
        
        public DynPopupCallBack(int _i)
        {
            i = _i;
        }
        
        // before opening the popup
        public void SyncAtomChoices()
        {
            // populate with person[i] string posibilities
            SuperController.LogMessage( "Before popup: " + i.ToString("#.00") );
        }
        
        // after choosing a string from the popup
        public void SyncAtom(string atomUID)
        {
            // set person[i] = atomUID
            SuperController.LogMessage( "String selected for: " + i.ToString("#.00") );
        }
    }
 
What you had been looking for is called Lambda functions.

If you define such a Lambda inside your for loop and use i, it would be automatically captured at the time the loop executes. Internally the following essentially creates that wrapper class for you and wraps the regular function call into a the lambda, so the function signature matches the callback.
C#:
    for(int i = 0; i < NUMBER_OF_PLEOPLE; i++)
    {
        JSONStorableStringChooser[] person[i] = new JSONStorableStringChooser(
                "person" + i.ToString(), null, "", "", (string atomUID) => SyncAtom(atomUID, i));
        RegisterStringChooser(person[i]);
        UIDynamicPopup dp = CreateFilterablePopup(person[i]);
        dp.popupPanelHeight = 1000f;
        dp.label = "Person #" + i.ToString();
        dp.popup.onOpenPopupHandlers += () => SyncAtomChocies(i);
    }



    // before opening the popup
    private void SyncAtomChoices(int i)
    {
        // populate with person[i] string posibilities
    }

    // after choosing a string from the popup
    private void SyncAtom(string atomUID, int i)
    {
        // set person[i] = atomUID           
    }
 
I knew it! I knew I was missing something, it was knowledge :LOL:

Thanks for the link but thank you very much for the code that makes it very easy to understand the concept. I see tons of uses for this.
 
Back
Top Bottom