How to make a Modal Dialog

I know this is been talked many times but I still don’t know how to accomplish it.

I mean, I’ve been searching and reading lots of info regarding this topic. But some doesn’t work,and some couldn’t be understood.

I know there’s no such internal function inside Unity3D so we have to make our own one. (It’s wrong saying that GUI.Window would automatically mask the GUI controls behinds it.)

All right. I just like to make a very simple "Are you sure? Yes. No."modal dialog window. But there’s many buttons on the screen as well when this window pops up. I want these buttons “not functioned” while poping up “Are you sure?”.

I know I need to make my own GUI manager. But the problem is, how to distinguish the GUI events. The
Event Type just distinguishes them from whether this is a MouseDown, or Keyboard Event, or Mouse Drag, something like this. But I really need “something that could tell me where this event comes from: whether it’s from the modal window, or the buttons all over the screen”, so that I could choose to use it or ignore it.

Thank you very much.

For anybody looking at this post now,

There is support for modal windows in 4.1.2:
GUI.ModalWindow

  1. Create a class extending EditorWindow
  2. Implement the function OnLostFocus()
  3. Call Focus() from OnLostFocus() if you do not want to loose focus.

Note: this does cause a small flicker between windows, but does force the focus to the extended EditorWindow.

Here’s some code I wrote to get a simple dialog for an error message. It’s not a pretty dialog but it’s enough to get a quick message on the screen which is sometimes enough.

using UnityEngine;
using System;

// example:
// HFTDialog.MessageBox("error", "Sorry but you're S.O.L", () => { Application.Quit() });

public class HFTDialog : MonoBehaviour {

    Rect m_windowRect;
    Action m_action;
    string m_title;
    string m_msg;

    static public void MessageBox(string title, string msg, Action action)
    {
        GameObject go = new GameObject("HFTDialog");
        HFTDialog dlg = go.AddComponent<HFTDialog>();
        dlg.Init(title, msg, action);
    }

    void Init(string title, string msg, Action action)
    {
        m_title = title;
        m_msg = msg;
        m_action = action;
    }

    void OnGUI()
    {
        const int maxWidth = 640;
        const int maxHeight = 480;

        int width = Mathf.Min(maxWidth, Screen.width - 20);
        int height = Mathf.Min(maxHeight, Screen.height - 20);
        m_windowRect = new Rect(
            (Screen.width - width) / 2,
            (Screen.height - height) / 2,
            width,
            height);

        m_windowRect = GUI.Window(0, m_windowRect, WindowFunc, m_title);
    }

    void WindowFunc(int windowID)
    {
        const int border = 10;
        const int width = 50;
        const int height = 25;
        const int spacing = 10;

        Rect l = new Rect(
            border,
            border + spacing,
            m_windowRect.width - border * 2,
            m_windowRect.height - border * 2 - height - spacing);
        GUI.Label(l, m_msg);

        Rect b = new Rect(
            m_windowRect.width - width - border,
            m_windowRect.height - height - border,
            width,
            height);

        if (GUI.Button(b, "ok"))
        {
            Destroy(this.gameObject);
            m_action();
        }

    }
}

You don’t need a complex gui manager or alike at least not for modal.
all you need is a simple handling that:

  1. knows if there is a modal dialog showing up (bool)
  2. A way so that the modal dialog knows that it is the modal one and responds to input (the starting point would be having the modal dialog just ignoring the modal bool from 1).

There is no modal dialog capability in Unity, as such you won’t find anything inbuilt that helps you.

To go into more detail what you will need to create:

  1. An UI manager that handles the whole UI. Its not needed technically but the possibility to have all gui in a single OnGUI call with the dialog classes having a “Draw” function is favorable performance wise as it makes a large difference. This gui manager then also would have a field “modalDialog” which is null if there is no modal and otherwise holds the ref to the modal dialog.
    The exception to using the Draw function and being in the manager is the modal dialog with an own OnGUI so you can use the gui.depth to have it in front and use Event.Use to “eat” events and prevent click through.

  2. Create a base Dialog Interface with a Draw() and optionally Draw(x,y) function

  3. Create your dialog classes that implement this interface

  4. In all these classes implement a check for the input handling so they check if the managers modalDialog is either null or this and otherwise the input is being ignored (you can do that through GUI.XXX() && isModalMe - where as isModalMe is a bool you set at the beginning of draw basing on above comparision)

I write this in OnGUI()

if(m_showError)
GUI.ModalWindow(0,new Rect(Screen.width/2-100,Screen.height/2-100,200,200),DoMyWindow,"Error");

and here is my DoMyWindow function

void DoMyWindow(int windowID)
{
GUI.Label(new Rect(0,100,200,100),errorStr);
if(GUI.Button(new Rect(50,150,60,30),"OK"))
{
m_showError=false;
}
}