public static ScriptableObject[] ObjectAtPosition (Vector2 position) {
            for (int i = DialogueEditorGUI.Cache.Nodes.Count - 1; i >= 0; i--) {
                BaseNode node = DialogueEditorGUI.Cache.Nodes.Get (i);

                if (node.Position.Contains (position))
                    return new ScriptableObject[] { node };

                for (int j = node.Nodules.Count - 1; j >= 0; j--)
                    if (node.Nodules.Get (j).Position.Contains (position))
                        return new ScriptableObject[] { node.Nodules.Get (j), node };

                if (node is MainNode) {
                    MainNode main = node as MainNode;

                    for (int j = main.Options.Count - 1; j >= 0; j--) {
                        OptionNode option = main.Options.Get (j);

                        if (option.Position.Contains (position))
                            return new ScriptableObject[] { option, main };

                        for (int k = option.Nodules.Count - 1; k >= 0; k--)
                            if (option.Nodules.Get (k).Position.Contains (position))
                                return new ScriptableObject[] { option.Nodules.Get (k), option, main };
                    }
                }
            }
            return new ScriptableObject[] { null };
        }
        public static OptionNode Create(string nodeTitle, string nodeTextArea, MainNode main)
        {
            OptionNode option = Instantiate(NodeTypes.GetDefaultNode("OptionNode")) as OptionNode;

            option.Construct(nodeTitle, nodeTextArea, main);
            return(option);
        }
        public static OptionNode Create(string _name, MainNode _mainNode)
        {
            OptionNode option = Instantiate(NodeTypes.GetDefaultNode("OptionNode")) as OptionNode;

            option.Construct(_name, option.textArea, _mainNode);
            return(option);
        }
        public override void OnGUI()
        {
            base.OnGUI();

            CanvasGUI.BeginGroup(Position, GUI.skin.box, actor.Tint, HasControl);

            if (Locked)
            {
                GUI.Label(new Rect(5, 5, 240, 20), name);
                GUI.Label(new Rect(5, 30, 240, 20), actor.name);
            }
            else
            {
                EditorCache cache    = DialogueEditorGUI.Cache;
                string      nodeName = name;

                if (CanvasGUI.TextField(new Rect(5, 5, 240, 20), ref nodeName))
                {
                    name = cache.Nodes.ItemNames[cache.Nodes.ItemNames.IndexOf(name)] = nodeName;
                }

                ActorDatabase actors = cache.Actors;
                actor = actors.Get(CanvasGUI.DropDownMenu(new Rect(5, 30, 240, 20),
                                                          position, actors.GetIndex(actor), actors.ItemNames.ToArray()));
            }

            if (CanvasGUI.Button(new Rect(Position.size.x - 50, 5, 20, 20), new GUIContent("L"), GUI.skin.button))
            {
                Locked = !Locked;
            }

            if (CanvasGUI.Button(new Rect(Position.size.x - 25, 5, 20, 20), new GUIContent("X"), GUI.skin.button))
            {
                Delete();
            }
            textArea = CanvasGUI.TextArea(new Rect(5, 55, 290, 115), textArea);

            if (CanvasGUI.Button(new Rect(5, 175, 290, 20), new GUIContent("Add Dialogue Option"), GUI.skin.button))
            {
                options.Add(OptionNode.Create(options.NextItemName("Option"), this));
            }

            CanvasGUI.EndGroup();

            options.OnGUI();
        }
        static void AddCallBack(object callBackObj)
        {
            EditorStates states = callBackObj as EditorStates;

            if (states == null)
            {
                throw new UnityException();
            }
            EditorState state = states.curState;

            if (states.info.Contains("Node"))
            {
                switch (states.curSpace)
                {
                case EventSpace.Node:
                    if (states.info == "OptionNode")
                    {
                        if (state.selectedObject is MainNode)
                        {
                            MainNode main = state.selectedObject as MainNode;
                            main.Options.Add(OptionNode.Create(main.Options.NextItemName("Option"), main));
                        }
                        else
                        {
                            goto default;
                        }
                    }
                    else if (states.info == "MainNode")
                    {
                        goto default;
                    }
                    else
                    {
                        Debug.LogError("Cannot recognise name of 'Node'. Add More Error here");
                        return;
                    }
                    break;

                default:
                    EditorCache cache = DialogueEditorGUI.Cache;
                    cache.Nodes.Add(DialogueNode.Create(states.info,
                                                        cache.Nodes.NextItemName(states.info),
                                                        CanvasGUI.CanvasToScreenPosition(state, states.mousePos),
                                                        cache.Actors.DefaultActor));
                    break;
                }
            }
            else if (states.info.Contains("Nodule"))
            {
                BaseNode node = (states.curSpace == EventSpace.Node) ? state.selectedObject as BaseNode :
                                (states.curSpace == EventSpace.Nodule) ? (state.selectedObject as BaseNodule).MainNode :
                                null;

                if (node)
                {
                    node.Nodules.Add(BaseNodule.Create(states.info, node.Nodules.NextItemName(states.info), node));
                }
            }
            else
            {
                throw new UnityException();
            }
        }
        public static bool CheckCompatibility(BaseNodule startNodule, BaseNodule endNodule)
        {
            if (!startNodule || !endNodule)
            {
                Debug.LogWarning((!startNodule ? "Start " : "End ") + " nodule is null.");
                return(false);
            }

            if (!startNodule.MainNode || !endNodule.MainNode)
            {
                Debug.LogWarning("");
                return(false);
            }

            if (startNodule == endNodule)
            {
                Debug.Log(startNodule.GetInstanceID() + ", " + endNodule.GetInstanceID());
                Debug.LogWarning("Start and end nodules are both the same object.");
                return(false);
            }

            if (startNodule.MainNode == endNodule.MainNode)
            {
                Debug.LogWarning("Start and end nodules have the same node.");
                return(false);
            }

            if (!GetNoduleAttritube(startNodule.GetID).CheckCompatibility(endNodule.GetID))
            {
                Debug.LogWarning("Start and end nodules are not compatible.");
                return(false);
            }

            if (startNodule.Nodules.Contains(endNodule) || endNodule.Nodules.Contains(startNodule))
            {
                Debug.LogWarning("Start and end nodules are already connected.");
                return(false);
            }

            if (startNodule.MainNode is OptionNode && !(startNodule is OutputNodule) || endNodule.MainNode is OptionNode && !(endNodule is OutputNodule))
            {
                OptionNode option = ((startNodule.MainNode is OptionNode) ? startNodule.MainNode : endNodule.MainNode) as OptionNode;

                if (option.MainNode == endNodule.MainNode)
                {
                    Debug.LogWarning("Recursive connection is a world of hurt, just dont do it.");
                    return(false);
                }
            }

            if (startNodule.MainNode is StartNode && startNodule is InputNodule)
            {
                Debug.LogError("");
                return(false);
            }
            else if (endNodule.MainNode is StartNode && endNodule is InputNodule)
            {
                Debug.LogError("");
                return(false);
            }
            return(true);
        }