/// <summary> /// Draw the state as a GUI.Window. /// </summary> public void OnGUIWindow() { // Is there a valid styles object? if (s_Styles == null) { s_Styles = new StateGUI.Styles(); } if (m_State != null) { // Is there a valid window style? if (m_WindowStyle == null || m_WindowStyleOn == null || m_State.color != m_StateColor) { SetWindowColor(m_State.color); } SetSearchColor(); var guiColor = GUI.color; // cache gui color // This is the enabled state? // Animate window alpha // if (Application.isPlaying && m_State.enabled && Event.current.type == EventType.Repaint) // GUI.color = Color.Lerp(s_Styles.activeColor, guiColor, Mathf.PingPong(Time.time, 1f)); // Draw state window rect = GUI.Window(m_Id, rect, this.StateGUIWindow, GUIContent.none, Selection.Contains(m_State) ? m_WindowStyleOn : m_WindowStyle); // Restore gui color GUI.color = guiColor; } else { this.Refresh(); // Used as a workaround the missing callback in the apply button prefab. } // Transition connections if (Event.current.type == EventType.MouseDrag && TransitionDragAndDrop.candidateForDrag != null && m_TransitionGUIs.Contains(TransitionDragAndDrop.candidateForDrag) && !rect.Contains(Event.current.mousePosition)) { TransitionDragAndDrop.StartDrag(); } }
/// <summary> /// Draw the contents of the GUI.Window. /// <param name="id">The unique id of the window.</param> /// </summary> void StateGUIWindow(int id) { // Draw the name and the icon state Rect rectName = new Rect(0, 12f, defaultWidth, c_WindowTitleHeight); GUI.Label(rectName, new GUIContent(m_State.stateName, m_Icon), s_Styles.windowTitle); // If this state is enabled then draw the enabled bar if (Application.isPlaying && m_State.enabled && Event.current.type == EventType.Repaint) { // Get the background position Rect backgroundPos = s_Styles.enabledBarBackground.margin.Remove(new Rect(0f, rectName.yMax + 5f, defaultWidth, 10f)); // Get the foreground position Rect foregroundPos = s_Styles.enabledBarBackground.padding.Remove(backgroundPos); foregroundPos.width = foregroundPos.width * Mathf.Repeat(Time.time, 1f); // Draw foreground bar s_Styles.enabledBar.Draw(foregroundPos, false, false, false, false); // Draw background s_Styles.enabledBarBackground.Draw(backgroundPos, false, false, false, false); } if (m_TransitionGUIs != null) { // Get the current event Event current = Event.current; // It's a repaint event? if (current.type == EventType.Repaint) { DrawEventName(); } // It's a mouse down event? else if (current.type == EventType.MouseDown) { // Create the rect Rect rect = new Rect(0, StateGUI.defaultHeight - 2, StateGUI.defaultWidth, TransitionGUI.defaultHeight); // Get the mouseposition Vector2 mousePos = current.mousePosition; // Logic for mouse click in event names for (int i = 0; i < m_TransitionGUIs.Count; i++) { if (rect.Contains(mousePos)) { if (Event.current.button == 1) { BehaviourWindow.activeState = m_State; BehaviourWindow.activeTransition = m_TransitionGUIs[i].transition; ShowContextMenu(m_TransitionGUIs[i].transition); Event.current.Use(); } else if (Event.current.button == 0) { BehaviourWindow.activeState = m_State; BehaviourWindow.activeTransition = m_TransitionGUIs[i].transition; TransitionDragAndDrop.PrepareStartDrag(m_TransitionGUIs[i], this); // Should always be called after BehaviourWindow.activeTransition Event.current.Use(); } } // Update rect.y pos rect.y += TransitionGUI.defaultHeight; } } } switch (Event.current.type) { // Is mouse button down? case EventType.MouseDown: if (Event.current.button == 1) { OnContextMenu(); Event.current.Use(); } // Is the left mouse button? else if (Event.current.button == 0) { // Focus in this window s_DraggedWindow = id; // Select this state? if (BehaviourWindow.activeStates.Length <= 1) { BehaviourWindow.activeState = m_State; } // Unselect transition BehaviourWindow.activeTransition = null; // Double click? if (Event.current.clickCount >= 2) { // The state is a parent state? if (m_State is ParentBehaviour) { // Selects the parent state BehaviourWindow.activeParent = m_State as ParentBehaviour; Event.current.Use(); } // The state is a MonoScript? else if (m_State is InternalMonoState) { // Selects the MonoBehaviour game object. var monoState = m_State as InternalMonoState; if (monoState.monoBehaviour != null) { Selection.activeGameObject = monoState.monoBehaviour.gameObject; Event.current.Use(); } } // Opens the state script else { var monoScript = MonoScript.FromMonoBehaviour(m_State); // Gets the script. if (monoScript != null) { AssetDatabase.OpenAsset(monoScript); // Opens script in default application. Event.current.Use(); } } } } break; // Mouse button up? case EventType.MouseUp: if (s_DraggedWindow == id) { s_DraggedWindow = -1; } break; } // GUI.DragWindow(); DragStateGUIs(); }
/// <summary> /// Draw the transition arrows. /// </summary> public override void OnGUIAfterWindows() { if (m_StatesGUI != null) { // Trying to create connections? if (TransitionDragAndDrop.dragging != null) { switch (Event.current.type) { // Mouse Up? Let's try to connect a transition destination... case EventType.MouseUp: // Mouse button left? if (Event.current.button == 0) { var mousePos = Event.current.mousePosition; // The mouse is over a StateGUI? foreach (var guiState in m_StatesGUI) { if (guiState.rect.Contains(mousePos)) { StateUtility.SetNewDestination(TransitionDragAndDrop.state, TransitionDragAndDrop.dragging, guiState.state); Refresh(); Event.current.Use(); break; } } // Ignores the Transition drag'n & drop operation TransitionDragAndDrop.AcceptDrag(); Repaint(); } break; // Cancel drag case EventType.Used: goto case EventType.Ignore; case EventType.Ignore: TransitionDragAndDrop.AcceptDrag(); Event.current.Use(); Repaint(); break; // Draws the transition destination when dragging. case EventType.Repaint: // Is dragging? if (TransitionDragAndDrop.isDragging) { // Validate dragging members var guiState = TransitionDragAndDrop.guiState; if (guiState != null && guiState.state != null) { // Gets the mouse position and creates a Rect var mousePos = Event.current.mousePosition; var destRect = new Rect(mousePos.x, mousePos.y, 0, 0); var destYOffset = 0f; // The mouse is over a StateGUI? foreach (var _guiState in m_StatesGUI) { if (_guiState.rect.Contains(mousePos)) { // Updates the destRect and destYOffset. destRect = _guiState.rect; destYOffset = StateGUI.defaultHeight * .5f; break; } } // Draws the bezier line TransitionDragAndDrop.transitionGUI.DrawArrow(guiState.rect, destRect, destYOffset); } } break; case EventType.MouseDrag: if (TransitionDragAndDrop.isDragging) { Repaint(); } break; } } } // Get the current event Event current = Event.current; var activeFsm = BehaviourWindow.activeFsm; // cached activeFsm switch (current.type) { // Show context menu? case EventType.ContextClick: OnContextMenu(); Event.current.Use(); break; case EventType.MouseDown: // If the left mouse button is down then unselect the state and start the dragging rect if (current.button == 0) { BehaviourWindow.activeState = null; EditorGUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; if (!current.alt && !current.shift) { m_SelectionStartPoint = current.mousePosition; m_SelectionRect = true; } current.Use(); } break; // Event ignored? case EventType.Ignore: // Cancel selection rect? if (m_SelectionRect) { goto case EventType.MouseUp; } break; // Cancel selection rect? case EventType.MouseUp: if (m_SelectionRect) { m_SelectionRect = false; GUIUtility.hotControl = 0; SelectNodesInRect(GetRectFromPoints(m_SelectionStartPoint, current.mousePosition)); current.Use(); } break; // Selection rect? case EventType.MouseDrag: if (m_SelectionRect) { current.Use(); } else if (current.button == 2) { m_ScrollView -= current.delta; current.Use(); } break; // Delete selected states? case EventType.ValidateCommand: // Use event to call event ExecuteCommand if (current.commandName == "Paste" && activeFsm != null && StateUtility.statesToPaste != null && StateUtility.statesToPaste.Length > 0) { current.Use(); } else if (current.commandName == "Copy" && activeFsm != null && Selection.objects.Length > 0) { current.Use(); } else if (current.commandName == "Duplicate" && activeFsm != null) { // Is there a selected state? foreach (var obj in Selection.objects) { if (obj is InternalStateBehaviour) { current.Use(); break; } } } else if ((current.commandName == "Delete" || current.commandName == "SoftDelete") && BehaviourWindow.activeState != null) { current.Use(); } break; case EventType.ExecuteCommand: if (current.commandName == "Paste") { StateUtility.PasteStates(activeFsm); } else if (current.commandName == "Copy") { StateUtility.CopySelectedStates(); } else if (current.commandName == "Duplicate") { StateUtility.CopySelectedStates(); StateUtility.PasteStates(activeFsm); } else if (current.commandName == "Delete" || current.commandName == "SoftDelete") { foreach (InternalStateBehaviour state in Selection.objects) { StateUtility.Destroy(state); } Refresh(); current.Use(); } break; // Dragging? case EventType.DragUpdated: if (DragAndDrop.objectReferences.Length > 0 && DragAndDrop.objectReferences[0] is MonoScript && BehaviourWindow.activeFsm != null) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; } break; // Drag perform? case EventType.DragPerform: if (DragAndDrop.objectReferences.Length > 0 && DragAndDrop.objectReferences[0] is MonoScript && BehaviourWindow.activeFsm != null) { var index = 0; // index of added states var mousePosition = current.mousePosition - new Vector2(StateGUI.defaultWidth, StateGUI.defaultHeight) * .5f; // Register undo #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2 Undo.RegisterSceneUndo("Add States"); #endif // Get all GetScripts var scripts = new List <MonoScript>(); foreach (var obj in DragAndDrop.objectReferences) { var script = obj as MonoScript; if (script != null) { scripts.Add(script); } } // Go trough all monoscripts foreach (MonoScript monoScript in scripts) { var type = monoScript.GetClass(); // The type is a valid InternalStateBehaviour instance? if (type != null && !type.IsAbstract) { // Add state behaviour if (type.IsSubclassOf(typeof(InternalStateBehaviour))) { var newState = StateUtility.AddState(activeFsm, type); // The state is valid? if (newState != null) { // Set the newState position newState.position = mousePosition + new Vector2(StateGUI.defaultWidth * index * .5f, 20f * index); index++; } } // Add mono state else if (type.IsSubclassOf(typeof(MonoBehaviour))) { var newMonoState = StateUtility.AddState(activeFsm, typeof(InternalMonoState)) as InternalMonoState; // Set the newMonoState position if (newMonoState != null) { // Set mono state position newMonoState.position = mousePosition + new Vector2(StateGUI.defaultWidth * index * .5f, 20f * index); index++; newMonoState.monoBehaviour = newMonoState.gameObject.AddComponent(type) as MonoBehaviour; // Register undo #if !UNITY_4_0_0 && !UNITY_4_1 && !UNITY_4_2 if (newMonoState.monoBehaviour != null) { Undo.RegisterCreatedObjectUndo(newMonoState.monoBehaviour, "Add Component"); } #endif } } } } // Sets dirty flag if (activeFsm.gameObject != null) { EditorUtility.SetDirty(activeFsm.gameObject); } // Accept drag DragAndDrop.AcceptDrag(); current.Use(); Refresh(); } break; // Draw the selection rect? case EventType.Repaint: if (m_SelectionRect) { s_Styles.selectionRect.Draw(GetRectFromPoints(m_SelectionStartPoint, current.mousePosition), false, false, false, false); } break; } GUI.EndScrollView(); // Close scroolView. GUI.EndGroup(); // Close group }