Making a generic modal window (Pt 3)

Checked with version: 5

-

Difficulty: Intermediate

In this session we will be making a generic modal window (Yes, No, Maybeso, Cancel) where we can push content and actions to the window from anywhere in our game and have the events work when the buttons are pressed. In this particular session, we will look at code options (if not optimizations) and other final touches. (Part 3 of 3) Tutor - Adam Buckner

Making a generic modal window (Pt 3)

Intermediate User Interface (UI)

Be aware that ModalPanel.cs is a work in progress and we adapted only a few of the functions in the scripts. The un-adapted code has been commented out. This code is still valid, and will work, but to avoid confusion, only the code used in Pt3 is uncommented.

ModalPanel

Code snippet

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Collections;

public class EventButtonDetails {
    public string buttonTitle;
    public Sprite buttonBackground;  // Not implemented
    public UnityAction action;
}

public class EventSliderDetails {

}

public class ModalPanelDetails {
    public string title; // Not implemented
    public string question;
    public Sprite iconImage;
    public Sprite panelBackgroundImage; // Not implemented
    public EventButtonDetails button1Details;
    public EventButtonDetails button2Details;
    public EventButtonDetails button3Details;
    public EventButtonDetails button4Details;
    public EventSliderDetails sliderDetails;
}


public class ModalPanel : MonoBehaviour {
    
    public Text question;
    public Image iconImage;
    public Button button1;
    public Button button2;
    public Button button3;

    public Text button1Text;
    public Text button2Text;
    public Text button3Text;
    
    public GameObject modalPanelObject;
    
    private static ModalPanel modalPanel;
    
    public static ModalPanel Instance () {
        if (!modalPanel) {
            modalPanel = FindObjectOfType(typeof (ModalPanel)) as ModalPanel;
            if (!modalPanel)
                Debug.LogError ("There needs to be one active ModalPanel script on a GameObject in your scene.");
        }
        
        return modalPanel;
    }
    
    
//  //  Announcement with Image:  A string, a Sprite and Cancel event;
//  public void Choice (string question, UnityAction cancelEvent, Sprite iconImage = null) {
//      modalPanelObject.SetActive (true);
//      
//      button3.onClick.RemoveAllListeners();
//      button3.onClick.AddListener (cancelEvent);
//      button3.onClick.AddListener (ClosePanel);
//      
//      this.question.text = question;
//      if (iconImage)
//          this.iconImage.sprite = iconImage;
//      
//      if (iconImage)
//          this.iconImage.gameObject.SetActive(true);
//      else
//          this.iconImage.gameObject.SetActive(false);
//      button1.gameObject.SetActive(false);
//      button2.gameObject.SetActive(false);
//      button3.gameObject.SetActive(true);
//  }

    public void NewChoice (ModalPanelDetails details){
        modalPanelObject.SetActive (true);

        this.iconImage.gameObject.SetActive(false);
        button1.gameObject.SetActive(false);
        button2.gameObject.SetActive(false);
        button3.gameObject.SetActive(false);

        this.question.text = details.question;

        if (details.iconImage) {
            this.iconImage.sprite = details.iconImage;
            this.iconImage.gameObject.SetActive(true);
        }

        button1.onClick.RemoveAllListeners();
        button1.onClick.AddListener (details.button1Details.action);
        button1.onClick.AddListener (ClosePanel);
        button1Text.text = details.button1Details.buttonTitle;
        button1.gameObject.SetActive(true);
        
        if (details.button2Details != null) {
            button2.onClick.RemoveAllListeners();
            button2.onClick.AddListener (details.button2Details.action);
            button2.onClick.AddListener (ClosePanel);
            button2Text.text = details.button2Details.buttonTitle;
            button2.gameObject.SetActive(true);
        }

        if (details.button3Details != null) {
            button3.onClick.RemoveAllListeners();
            button3.onClick.AddListener (details.button3Details.action);
            button3.onClick.AddListener (ClosePanel);
            button3Text.text = details.button3Details.buttonTitle;
            button3.gameObject.SetActive(true);
        }
    }
    
//  //  Yes/No: A string, a Yes event, a No event (No Cancel Button);
//  public void Choice (string question, UnityAction yesEvent, UnityAction noEvent) {
//      modalPanelObject.SetActive (true);
//
//      button1.onClick.RemoveAllListeners();
//      button1.onClick.AddListener (yesEvent);
//      button1.onClick.AddListener (ClosePanel);
//
//      button2.onClick.RemoveAllListeners();
//      button2.onClick.AddListener (noEvent);
//      button2.onClick.AddListener (ClosePanel);
//
//      this.question.text = question;
//      
//      this.iconImage.gameObject.SetActive(false);
//      button1.gameObject.SetActive(true);
//      button2.gameObject.SetActive(true);
//      button3.gameObject.SetActive(false);
//  }
//  
//  //  Yes/No/Cancel: A string, a Yes event, a No event and Cancel event;
//  public void Choice (string question, UnityAction yesEvent, UnityAction noEvent, UnityAction cancelEvent) {
//      modalPanelObject.SetActive (true);
//      
//      button1.onClick.RemoveAllListeners();
//      button1.onClick.AddListener (yesEvent);
//      button1.onClick.AddListener (ClosePanel);
//      
//      button2.onClick.RemoveAllListeners();
//      button2.onClick.AddListener (noEvent);
//      button2.onClick.AddListener (ClosePanel);
//      
//      button3.onClick.RemoveAllListeners();
//      button3.onClick.AddListener (cancelEvent);
//      button3.onClick.AddListener (ClosePanel);
//      
//      this.question.text = question;
//      
//      this.iconImage.gameObject.SetActive(false);
//      button1.gameObject.SetActive(true);
//      button2.gameObject.SetActive(true);
//      button3.gameObject.SetActive(true);
//  }
//  
//  //  Yes/No with Image: A string, a Sprite, a Yes event, a No event (No Cancel Button);
//  public void Choice (string question, Sprite iconImage, UnityAction yesEvent, UnityAction noEvent) {
//      modalPanelObject.SetActive (true);
//      
//      button1.onClick.RemoveAllListeners();
//      button1.onClick.AddListener (yesEvent);
//      button1.onClick.AddListener (ClosePanel);
//      
//      button2.onClick.RemoveAllListeners();
//      button2.onClick.AddListener (noEvent);
//      button2.onClick.AddListener (ClosePanel);
//      
//      this.question.text = question;
//      this.iconImage.sprite = iconImage;
//      
//      this.iconImage.gameObject.SetActive(true);
//      button1.gameObject.SetActive(true);
//      button2.gameObject.SetActive(true);
//      button3.gameObject.SetActive(false);
//  }
//  
//  //  Yes/No/Cancel with Image: A string, a Sprite, a Yes event, a No event and Cancel event;
//  public void Choice (string question, Sprite iconImage, UnityAction yesEvent, UnityAction noEvent, UnityAction cancelEvent) {
//      modalPanelObject.SetActive (true);
//      
//      button1.onClick.RemoveAllListeners();
//      button1.onClick.AddListener (yesEvent);
//      button1.onClick.AddListener (ClosePanel);
//      
//      button2.onClick.RemoveAllListeners();
//      button2.onClick.AddListener (noEvent);
//      button2.onClick.AddListener (ClosePanel);
//      
//      button3.onClick.RemoveAllListeners();
//      button3.onClick.AddListener (cancelEvent);
//      button3.onClick.AddListener (ClosePanel);
//      
//      this.question.text = question;
//      this.iconImage.sprite = iconImage;
//      
//      this.iconImage.gameObject.SetActive(true);
//      button1.gameObject.SetActive(true);
//      button2.gameObject.SetActive(true);
//      button3.gameObject.SetActive(true);
//  }
    
    void ClosePanel () {
        modalPanelObject.SetActive (false); 
    }
}

Be aware that TestModalPanel.cs is a work in progress and we adapted only a few of the functions in the scripts. The un-adapted code has been commented out. This code is still valid, and will work, but to avoid confusion, only the code used in Pt3 is uncommented.

TestModalPanel

Code snippet

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Collections;

public class TestModalPanel : MonoBehaviour {

    public Sprite icon;
    public Transform spawnPoint;
    public GameObject thingToSpawn;
    public DisplayManager displayManager;
    
    private ModalPanel modalPanel;

    void Awake () {
        modalPanel = ModalPanel.Instance();
    }
    
    //  Send to the Modal Panel to set up the Buttons and functions to call
    public void TestC () {
        ModalPanelDetails modalPanelDetails = new ModalPanelDetails ();
        modalPanelDetails.question = "This is an announcement!\nIf you don't like it, shove off!";
        modalPanelDetails.button1Details = new EventButtonDetails ();
        modalPanelDetails.button1Details.buttonTitle = "Gotcha!";
        modalPanelDetails.button1Details.action = TestCancelFunction;

        modalPanel.NewChoice (modalPanelDetails);
    }
    public void TestCI () {
        ModalPanelDetails modalPanelDetails = new ModalPanelDetails {question = "This is an announcement!\nIf you don't like it, shove off!", iconImage = icon};
        modalPanelDetails.button1Details = new EventButtonDetails {buttonTitle = "Gotcha!", action = TestCancelFunction};
        
        modalPanel.NewChoice (modalPanelDetails);
    }
    
//  public void TestYN () {
//      modalPanel.Choice ("Cheese on your burger?", TestYesFunction, TestNoFunction);
//  }
//  
//  public void TestYNC () {
//      modalPanel.Choice ("Would you like a poke in the eye?\nHow about with a sharp stick?", TestYesFunction, TestNoFunction, TestCancelFunction);
//  }
//  
//  public void TestYNI () {
//      modalPanel.Choice ("Do you like this icon?", icon, TestYesFunction, TestNoFunction, TestCancelFunction);
//  }
//  
//  public void TestYNCI () {
//      modalPanel.Choice ("Do you want to use this icon?", icon, TestYesFunction, TestNoFunction, TestCancelFunction);
//  }
//  
//  public void TestLambda () {
//      modalPanel.Choice ("Do you want to create this sphere?", () => { InstantiateObject(thingToSpawn); }, TestNoFunction);
//  }
//  
//  public void TestLambda2 () {
//      modalPanel.Choice ("Do you want to create two spheres?", () => { InstantiateObject(thingToSpawn, thingToSpawn); }, TestNoFunction);
//  }
    
    public void TestLambda3 () {
        ModalPanelDetails modalPanelDetails = new ModalPanelDetails {question = "Do you want to create three spheres?"};
        modalPanelDetails.button1Details = new EventButtonDetails {
            buttonTitle = "Yes Please!",
            action = () => { InstantiateObject(thingToSpawn); InstantiateObject(thingToSpawn, thingToSpawn);}
        };
        modalPanelDetails.button2Details = new EventButtonDetails {
            buttonTitle = "No thanks!",
            action = TestNoFunction
        };

        modalPanel.NewChoice (modalPanelDetails);
    }
    
    //  The function to call when the button is clicked
    void TestYesFunction () {
        displayManager.DisplayMessage ("Heck, yeah!");
    }
    
    void TestNoFunction () {
        displayManager.DisplayMessage ("No way, Jose!");
    }
    
    void TestCancelFunction () {
        displayManager.DisplayMessage ("I give up!");
    }
    
    void InstantiateObject (GameObject thingToInstantiate) {
        displayManager.DisplayMessage ("Here you go!");
        Instantiate (thingToInstantiate, spawnPoint.position, spawnPoint.rotation);
    }
    
    void InstantiateObject (GameObject thingToInstantiate, GameObject thingToInstantiate2) {
        displayManager.DisplayMessage ("Here you go!");
        Instantiate (thingToInstantiate, spawnPoint.position -  Vector3.one, spawnPoint.rotation);
        Instantiate (thingToInstantiate2, spawnPoint.position + Vector3.one, spawnPoint.rotation);
    }
}

BringToFront

Code snippet

using UnityEngine;
using System.Collections;

public class BringToFront : MonoBehaviour {

    void OnEnable () {
        transform.SetAsLastSibling ();
    }
}

DisplayManager

Code snippet

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class DisplayManager : MonoBehaviour {

    public Text displayText;
    public float displayTime;
    public float fadeTime;
    
    private IEnumerator fadeAlpha;
    
    private static DisplayManager displayManager;
    
    public static DisplayManager Instance () {
        if (!displayManager) {
            displayManager = FindObjectOfType(typeof (DisplayManager)) as DisplayManager;
            if (!displayManager)
                Debug.LogError ("There needs to be one active DisplayManager script on a GameObject in your scene.");
        }
        
        return displayManager;
    }

    public void DisplayMessage (string message) {
        displayText.text = message;
        SetAlpha ();
    }
    
    void SetAlpha () {
        if (fadeAlpha != null) {
            StopCoroutine (fadeAlpha);
        }
        fadeAlpha = FadeAlpha ();
        StartCoroutine (fadeAlpha);
    }
    
    IEnumerator FadeAlpha () {
        Color resetColor = displayText.color;
        resetColor.a = 1;
        displayText.color = resetColor;
        
        yield return new WaitForSeconds (displayTime);
        
        while (displayText.color.a > 0) {
            Color displayColor = displayText.color;
            displayColor.a -= Time.deltaTime / fadeTime;
            displayText.color = displayColor;
            yield return null;
        }
        yield return null;
    }
}

Related documentation

Community resources