I have been programming a custom editor window to show tree diagrams of dialogue paths. It was all working fine, but now the window has stopped so much as opening, giving the following error the first time I attempt to create the window in Unity (but none of the other times after that from what I can tell):
“ArgumentException: You can only call GUI functions from inside OnGUI.
UnityEngine.GUIUtility.CheckOnGUI () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUIUtility.cs:208)
UnityEngine.GUI.get_skin () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUI.cs:55)
DialogueGUI…ctor ()
UnityEditor.EditorWindow:GetWindow(Type)
DialogueGUI:ShowWindow() (at Assets/Editor/Dialogue Backend/DialogueGUI.cs:20)”
I try double clicking the error message, and it takes me to the line containing the GetWindow function, but this has always worked previously, so I don’t understand what is wrong - has something in Unity changed? I can’t remember if I updated between the last time it worked and now, and I can’t find or think of anything new that is a GUI function running outside of OnGUI. If someone could help me understand what is wrong it would be much appreciated!
The entirety of the script controlling the window is as follows (I included all of it just in case, as I have no idea what the problem is):
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
[System.Serializable]
public class DialogueTreeBox
{
public Rect mainRect {get;set;}
}
public class DialogueGUI : EditorWindow {
[MenuItem("Window/DialogueGUI")]
public static void ShowWindow()
{
GetWindow(typeof(DialogueGUI));
Debug.Log("Window Loaded.");
}
public GUIStyle titleStyle;
//Tree Variables
public Texture backgroundTexture; //The texture of the background of the tree-editing area
public Rect windowRect = new Rect(200, 100, 160, 160);
public Rect windowRect2 = new Rect(100, 100, 160, 160);
public Vector2 nodeSize = new Vector2(160, 160); //The x and y sizes of the node windows
public string[] nodeTypeOptions = new string[] {"Monologue","Dialogue","Script"}; //The different possible types of node
public List<DialogueNode> nodes = new List<DialogueNode>();
public GUIStyle smallFontButton = new GUIStyle(GUI.skin.button);
private int scrollSizeY = 10000; //The max vertical size of the tree-editing area
private int scrollSizeX = 10000; //The max horizontal size of the tree-editing area
private Vector2 scrollPos = Vector2.zero;
//Character Dropdown Box
public string[] options = new string[3];
public int index = 0;
//Run when unity is started up?
public void OnEnable()
{
backgroundTexture = (Texture)Resources.Load("DGBT",typeof(Texture));
}
void OnGUI() {
if (smallFontButton.fontSize != 10)
{
smallFontButton = GUI.skin.button;
smallFontButton.fontSize = 10;
}
GUI.DrawTextureWithTexCoords(new Rect(-5, 50, position.width + 10, position.height - 40), backgroundTexture, new Rect(0, 0, (position.width + 10)/400, (position.height - 40)/400));
//Dropdown Box
index = EditorGUI.Popup(
new Rect(0, 10, 300, 20),
"Character:",
index,
options);
//Add Character
if (GUI.Button(new Rect(400, 10, 200, 26), "Add Character"))
AddCharacterToObjects();
//Save Tree
if (GUI.Button(new Rect(630, 10, 200, 26), "Save Tree"))
{
//Do saving stuff
}
//Add Node
if (GUI.Button(new Rect(860, 10, 200, 26),"New Node"))
{
int i = FirstEmptyIndex(nodes);
nodes.Insert(i,new DialogueNode());
nodes[i - 1].nodeRect = new Rect(100,100,160,160);
nodes[i - 1].nodeID = i - 1;
}
//Show Number Of Nodes
GUI.Box(new Rect(1090, 13, 100, 20), "Nodes: " + nodes.Count);
scrollPos = GUI.BeginScrollView(new Rect(0, 50, position.width, position.height - 50), scrollPos, new Rect(0, 0, scrollSizeX, scrollSizeY));
Handles.BeginGUI();
if (nodes.Count > 0)
{
for (int i = 0; i < nodes.Count; i++)
{
for (int j = 0; j < nodes[i].proceedingNodes.Count; j++)
{
Handles.DrawAAPolyLine(4, new Vector3[] {
new Vector3 (
nodes[i].nodeRect.center.x,
nodes[i].nodeRect.center.y,
0),
new Vector3(
nodes[nodes[i].proceedingNodes[j]].nodeRect.center.x,
nodes[nodes[i].proceedingNodes[j]].nodeRect.center.y,
0) });
}
}
}
Handles.EndGUI();
BeginWindows();
for(int i = 0; i < nodes.Count; i++)
{
nodes[i].nodeRect = GUI.Window(i, nodes[i].nodeRect, WindowFunction, nodes[i].nodeTypeString);
}
EndWindows();
for(int i = 0; i<nodes.Count; i++)
{
if (nodes[i].nodeRect.x < 0)
nodes[i].nodeRect.x = 0;
else if (nodes[i].nodeRect.x > scrollSizeX)
nodes[i].nodeRect.x = scrollSizeX - 160;
if (nodes[i].nodeRect.y < 0)
nodes[i].nodeRect.y = 0;
else if (nodes[i].nodeRect.y > scrollSizeY)
nodes[i].nodeRect.y = scrollSizeY - 160;
}
GUI.EndScrollView();
}
void WindowFunction (int windowID) {
nodes[windowID].nodeType = EditorGUI.Popup(
new Rect(5, 20, 150, 20),
nodes[windowID].nodeType,
nodeTypeOptions
);
switch (nodes[windowID].nodeType)
{
case 0:
nodes[windowID].nodeTypeString = "Monologue";
break;
case 1:
nodes[windowID].nodeTypeString = "Dialogue";
break;
case 2:
nodes[windowID].nodeTypeString = "Script";
break;
}
//Layout for node if it's a monologue node
if (nodes[windowID].nodeType == 0)
{
GUI.TextArea(new Rect(5, 45, 150, 105),"");
}
//Layout for node if it's a dialogue node
else if (nodes[windowID].nodeType == 1)
{
GUI.TextArea(new Rect(5, 45, 150, 90), "");
}
//Layout for node if it's a script node
else if (nodes[windowID].nodeType == 2)
{
//Stuff for callbacks
}
//Show Node ID
GUI.Box(new Rect(0, 0, 20, 15), "" + nodes[windowID].nodeID, smallFontButton);
//Connect To Another Node
if (GUI.Button(new Rect(20, 0, 20, 15), "/", smallFontButton))
{
//Show box to choose node to connect etc.
}
//Add New Node Proceeding This Node
if (GUI.Button(new Rect(120,0,20,15),"+", smallFontButton))
{
int i = FirstEmptyIndex(nodes);
nodes.Insert(i, new DialogueNode());
nodes[i - 1].nodeID = i - 1;
nodes[i - 1].nodeRect = new Rect(nodes[windowID].nodeRect.x, nodes[windowID].nodeRect.y + 200, 160, 160);
nodes[i - 1].preceedingNodes.Insert(nodes[i - 1].preceedingNodes.Count, windowID);
nodes[windowID].proceedingNodes.Insert(nodes[windowID].proceedingNodes.Count, i - 1);
}
//Remove Current Node
if (GUI.Button(new Rect(140,0,20,15),"x", smallFontButton))
{
for (int i = 0;i < nodes[windowID].preceedingNodes.Count; i++)
{
nodes[nodes[windowID].preceedingNodes[i]].proceedingNodes.Remove(nodes[windowID].nodeID);
}
//The Rest Of The Stuff To Remove Node
}
GUI.DragWindow(); //Must be at the end
}
void AddCharacterToObjects() {
if(!Selection.activeGameObject){
Debug.LogError("Please select at least one GameObject first");
return;
}
foreach(GameObject go in Selection.gameObjects) {
switch (index) {
case 0:
//do stuff
break;
case 1:
//more stuff
break;
case 2:
//continue this
break;
}
}
}
public int FirstEmptyIndex<T> (List<T> list)
{
int ret = 0;
for(int i = 0; i < list.Count; i++)
{
if (list[i].Equals(default(T)))
{
ret = i;
break;
}
}
if (ret == 0)
ret = list.Count;
return ret;
}
}
Thanks in advance for the help!