Exemplo n.º 1
0
        void OnGUI()
        {
            foreach (var obj in Selection.objects)
            {
                if (obj is StateMachineDefinition)
                {
                    def = (StateMachineDefinition)obj;
                    break;
                }
            }

            if (!Application.isPlaying)
            {
                ShowSidebar();
            }

            Rect viewportRect = new Rect(0, 0, position.width - sideWidth, position.height);

            EditorGUI.DrawRect(viewportRect, bgColor);

            GUI.EndGroup();

            Rect clippedArea = new Rect(0, 0, position.width - sideWidth, position.height);

            clippedArea.size /= zoom;
            clippedArea.y    += editorWindowTabHeight / zoom;
            GUI.BeginGroup(clippedArea);

            bool repaint = false;

            if (def != null)
            {
                Event cur = Event.current;

                Matrix4x4 gm = GUI.matrix;
                GUI.matrix = Matrix4x4.Scale(new Vector3(zoom, zoom, 1));

                UpdateView(ref repaint);

                if (!Application.isPlaying)
                {
                    if (op != null)
                    {
                        if (def != op.definition)
                        {
                            op.Cancel();
                            op = null;
                        }
                        else
                        {
                            op.Update();

                            if (op.done)
                            {
                                op      = null;
                                repaint = true;
                                EditorUtility.SetDirty(def);
                                dirty = true;
                            }
                        }
                    }
                    else
                    {
                        var selected   = def.SelectState(ToWorld(cur.mousePosition));
                        var selectedTr = def.SelectTransition(ToWorld(cur.mousePosition));

                        if (selectedTr.t1 == null)
                        {
                            if (selected != lastSelectedState)
                            {
                                repaint           = true;
                                lastSelectedState = selected;
                            }

                            if (lastSelectedTr != null)
                            {
                                lastSelectedTr = null;
                                repaint        = true;
                            }
                        }
                        else
                        {
                            if (selectedTr.t2 != lastSelectedTr)
                            {
                                repaint        = true;
                                lastSelectedTr = selectedTr.t2;
                            }

                            if (lastSelectedState != null)
                            {
                                lastSelectedState = null;
                                repaint           = true;
                            }
                        }

                        if (cur.type == EventType.MouseDown)
                        {
                            if (cur.button == 0)
                            {
                                if (selectedTr.t1 != null)
                                {
                                    editingTransition = selectedTr;
                                    editingState      = null;
                                    repaint           = true;
                                }
                                else if (selected != null)
                                {
                                    editingState         = selected;
                                    editingTransition.t1 = null;
                                    editingTransition.t2 = null;
                                    repaint = true;

                                    if (cur.clickCount == 1)
                                    {
                                        op = new MoveStateOperation(def, this, selected);
                                    }
                                    else if (cur.clickCount == 2)
                                    {
                                        op = new RenameStateOperation(def, this, selected);
                                    }
                                }
                                else
                                {
                                    editingState         = null;
                                    editingTransition.t1 = null;
                                    editingTransition.t2 = null;
                                    repaint = true;
                                }
                            }
                            else if (cur.button == 1)
                            {
                                if (selected == null && lastSelectedTr == null)
                                {
                                    GenericMenu menu = new GenericMenu();

                                    menu.AddItem(new GUIContent("Create State"), false, () => {
                                        var s      = def.AddState();
                                        s.position = ToWorld((cur.mousePosition - Vector2.up * editorWindowTabHeight) / zoom);
                                        MoveStateOperation.Snap(ref s.position);
                                        op = new RenameStateOperation(def, this, s);
                                        EditorUtility.SetDirty(def);
                                        dirty = true;
                                    });

                                    GUI.EndGroup();
                                    menu.ShowAsContext();
                                    GUI.BeginGroup(clippedArea);
                                }
                                else if (selectedTr.t1 != null)
                                {
                                    GenericMenu menu = new GenericMenu();

                                    menu.AddItem(new GUIContent("Remove Transition"), false, () => {
                                        selectedTr.t1.RemoveTransition(selectedTr.t2);
                                        EditorUtility.SetDirty(def);
                                        dirty   = true;
                                        repaint = true;
                                    });

                                    GUI.EndGroup();
                                    menu.ShowAsContext();
                                    GUI.BeginGroup(clippedArea);
                                }
                                else if (selected != null)
                                {
                                    GenericMenu menu = new GenericMenu();

                                    menu.AddItem(new GUIContent("Delete State"), false, () => {
                                        def.RemoveState(selected);
                                        EditorUtility.SetDirty(def);
                                        dirty   = true;
                                        repaint = true;
                                    });

                                    menu.AddItem(new GUIContent("Rename State"), false, () => {
                                        op = new RenameStateOperation(def, this, selected);
                                    });

                                    menu.AddItem(new GUIContent("Add Transition"), false, () => {
                                        op = new MakeTransitionOperation(def, this, selected);
                                    });

                                    StateMachineDefinition.State parent = def.GetState(selected.parent);

                                    if (parent == null)
                                    {
                                        if (selected.name != def.defaultState)
                                        {
                                            menu.AddItem(new GUIContent("Make Default State"), false, () => {
                                                def.defaultState = selected.name;
                                                dirty            = true;
                                                repaint          = true;
                                            });
                                        }
                                    }
                                    else
                                    {
                                        if (selected.name != parent.localDefault)
                                        {
                                            menu.AddItem(new GUIContent("Make Local Default"), false, () => {
                                                parent.localDefault = selected.name;
                                                dirty   = true;
                                                repaint = true;
                                            });
                                        }
                                    }

                                    if (selected.hasChildren)
                                    {
                                        menu.AddItem(new GUIContent("Remove Sub-Machine"), false, () => {
                                            def.RemoveSub(selected, MoveStateOperation.snap * 2);
                                        });

                                        menu.AddItem(new GUIContent("Create Child State"), false, () => {
                                            var s      = def.AddState();
                                            s.position = ToWorld((cur.mousePosition - Vector2.up * editorWindowTabHeight) / zoom);
                                            def.SetStateParent(s, selected, MoveStateOperation.snap);
                                            MoveStateOperation.Snap(ref s.position);
                                            op = new RenameStateOperation(def, this, s);
                                            EditorUtility.SetDirty(def);
                                            dirty = true;
                                        });
                                    }
                                    else
                                    {
                                        menu.AddItem(new GUIContent("Make Sub-Machine"), false, () => {
                                            def.CreateSub(selected, MoveStateOperation.snap * 2);
                                        });
                                    }

                                    GUI.EndGroup();
                                    menu.ShowAsContext();
                                    GUI.BeginGroup(clippedArea);
                                }
                            }
                        }
                    }
                }

                if (Event.current.type != EventType.Repaint && (repaint || (op != null && op.repaint)))
                {
                    Repaint();
                }

                Handles.BeginGUI();

                Handles.color = lineColor;
                Vector2 sz = scroll / zoom;

                for (float x = -sz.x % MoveStateOperation.snap; x < clippedArea.width; x += MoveStateOperation.snap)
                {
                    Handles.DrawLine(new Vector3(x, 0), new Vector3(x, clippedArea.height));
                }

                for (float y = -sz.y % MoveStateOperation.snap; y < clippedArea.height; y += MoveStateOperation.snap)
                {
                    Handles.DrawLine(new Vector3(0, y), new Vector3(clippedArea.width, y));
                }

                if (Application.isPlaying)
                {
                    if (observing == null || observing.gameObject != Selection.activeGameObject)
                    {
                        if (Selection.activeGameObject)
                        {
                            observing = Selection.activeGameObject.GetComponent <StateMachine>();
                        }

                        if (observing == null)
                        {
                            observing = (StateMachine)FindObjectOfType(typeof(StateMachine).Assembly.GetType(def.name));
                        }
                    }
                }
                else if (!Application.isPlaying)
                {
                    observing = null;
                }
                Color oldColor = GUI.color;

                if (def.states != null)
                {
                    foreach (var state in def.states)
                    {
                        if (op == null || op.state != state || op.showBaseGUI)
                        {
                            string s      = state.name;
                            var    parent = def.GetState(state.parent);
                            if (parent == null && def.defaultState == s)
                            {
                                s += "\n<default state>";
                            }
                            else if (parent != null && parent.localDefault == s)
                            {
                                s += "\n<local default>";
                            }

                            Rect rect = state.rect;
                            rect.position = ToScreen(rect.position);

                            GUI.SetNextControlName("StateButton");

                            if (observing && cur.type == EventType.Repaint)
                            {
                                if (observing.IsStateActive(state.name))
                                {
                                    GUI.color = new Color(0.5f, 0.7f, 1.0f);
                                }
                                else if (observing.IsStateRemembered(state.name))
                                {
                                    GUI.color = new Color(0.9f, 0.8f, 1.0f);
                                }
                                else
                                {
                                    GUI.color = oldColor;
                                }
                            }

                            if (!state.hasChildren)
                            {
                                if (state != editingState)
                                {
                                    GUI.Button(rect, s);
                                }
                                else
                                {
                                    GUI.Button(rect, "");

                                    var style = new GUIStyle(GUI.skin.label);
                                    style.alignment        = TextAnchor.MiddleCenter;
                                    style.normal.textColor = Color.blue;
                                    style.fontStyle        = FontStyle.Bold;

                                    GUI.Label(rect, s, style);
                                }
                            }
                            else
                            {
                                GUI.Button(rect, "");

                                var style = new GUIStyle(GUI.skin.label);
                                style.alignment = TextAnchor.UpperCenter;

                                if (state == editingState)
                                {
                                    style.normal.textColor = Color.blue;
                                    style.fontStyle        = FontStyle.Bold;
                                }

                                GUI.Label(rect, s, style);

                                Rect innerRect = rect;

                                innerRect.xMin += 4;
                                innerRect.xMax -= 4;

                                innerRect.yMin += 32;
                                innerRect.yMax -= 4;

                                GUI.color = oldColor;
                                EditorGUI.DrawRect(innerRect, bgColor);

                                Handles.color = lineColor;
                                for (float x = rect.xMin + MoveStateOperation.snap; x < rect.xMax; x += MoveStateOperation.snap)
                                {
                                    Handles.DrawLine(new Vector3(x, innerRect.yMin), new Vector3(x, innerRect.yMax));
                                }

                                for (float y = rect.yMin + MoveStateOperation.snap * 2; y < rect.yMax; y += MoveStateOperation.snap)
                                {
                                    Handles.DrawLine(new Vector3(innerRect.xMin, y), new Vector3(innerRect.xMax, y));
                                }
                            }
                        }

                        if (op != null && op.state == state)
                        {
                            op.OnGUI();
                        }
                    }

                    foreach (var from in def.states)
                    {
                        if (from.transitions != null)
                        {
                            foreach (var tr in from.transitions)
                            {
                                if (Application.isPlaying)
                                {
                                    Handles.color = Color.black;
                                    if (observing)
                                    {
                                        float t = Time.unscaledTime - observing.TransitionLastTime(from.name, tr.to);
                                        if (t < 0.5f)
                                        {
                                            Handles.color = Color.Lerp(Color.black, Color.green, 1.0f - t * 2);
                                        }
                                    }
                                }
                                else
                                {
                                    if (tr != lastSelectedTr && tr != editingTransition.t2)
                                    {
                                        Handles.color = Color.black;
                                    }
                                    else
                                    {
                                        Handles.color = Color.blue;
                                    }
                                }

                                if (def.GetState(tr.to) != null)
                                {
                                    var     line = def.GetTransitionPoints(from, tr);
                                    Vector2 src  = ToScreen(line.t1);
                                    Vector2 dest = ToScreen(line.t2);

                                    Vector2 v     = (dest - src).normalized;
                                    Vector2 ortho = new Vector2(v.y, -v.x);

                                    Vector2 arrow = ortho - v;
                                    Vector2 mid   = (src + dest) / 2;

                                    Handles.DrawAAPolyLine(3, src, dest);
                                    Handles.DrawAAPolyLine(3, mid + v * 5, mid + arrow * 6);
                                }
                            }
                        }
                    }
                }

                Handles.EndGUI();

                GUI.matrix = gm;
            }
            else if (op != null)
            {
                op.Cancel();
                op = null;
            }
        }