/// <summary> /// Make the specified selection pixel-perfect. /// </summary> static public void MakePixelPerfect(Transform t) { UIWidget w = t.GetComponent <UIWidget>(); if (w != null) { w.MakePixelPerfect(); } if (t.GetComponent <UIAnchor>() == null && t.GetComponent <UIRoot>() == null) { #if UNITY_EDITOR RegisterUndo(t, "Make Pixel-Perfect"); #endif t.localPosition = Round(t.localPosition); t.localScale = Round(t.localScale); } // Recurse into children for (int i = 0, imax = t.childCount; i < imax; ++i) { MakePixelPerfect(t.GetChild(i)); } }
/// <summary> /// Draw widget's dimensions. /// </summary> static void DrawDimensions(SerializedObject so, UIWidget w, bool isPrefab) { GUILayout.BeginHorizontal(); { bool freezeSize = so.isEditingMultipleObjects; UILabel lbl = w as UILabel; if (!freezeSize && lbl) { freezeSize = (lbl.overflowMethod == UILabel.Overflow.ResizeFreely); } if (freezeSize) { EditorGUI.BeginDisabledGroup(true); NGUIEditorTools.DrawProperty("Size", so, "mWidth", GUILayout.MinWidth(100f)); EditorGUI.EndDisabledGroup(); } else { GUI.changed = false; int val = EditorGUILayout.IntField("Size", w.width, GUILayout.MinWidth(100f)); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Dimensions Change", w); w.width = val; } } if (!freezeSize && lbl) { UILabel.Overflow ov = lbl.overflowMethod; freezeSize = (ov == UILabel.Overflow.ResizeFreely || ov == UILabel.Overflow.ResizeHeight); } NGUIEditorTools.SetLabelWidth(12f); if (freezeSize) { EditorGUI.BeginDisabledGroup(true); NGUIEditorTools.DrawProperty("x", so, "mHeight", GUILayout.MinWidth(30f)); EditorGUI.EndDisabledGroup(); } else { GUI.changed = false; int val = EditorGUILayout.IntField("x", w.height, GUILayout.MinWidth(30f)); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Dimensions Change", w); w.height = val; } } NGUIEditorTools.SetLabelWidth(80f); if (isPrefab) { GUILayout.Space(70f); } else { EditorGUI.BeginDisabledGroup(so.isEditingMultipleObjects); if (GUILayout.Button("Snap", GUILayout.Width(60f))) { foreach (GameObject go in Selection.gameObjects) { UIWidget pw = go.GetComponent <UIWidget>(); if (pw != null) { NGUIEditorTools.RegisterUndo("Snap Dimensions", pw); NGUIEditorTools.RegisterUndo("Snap Dimensions", pw.transform); pw.MakePixelPerfect(); } } } EditorGUI.EndDisabledGroup(); } } GUILayout.EndHorizontal(); }
/// <summary> /// All widgets have depth, color and make pixel-perfect options /// </summary> protected void DrawCommonProperties() { PrefabType type = PrefabUtility.GetPrefabType(mWidget.gameObject); NGUIEditorTools.DrawSeparator(); #if UNITY_3_5 // Pivot point -- old school drop-down style UIWidget.Pivot pivot = (UIWidget.Pivot)EditorGUILayout.EnumPopup("Pivot", mWidget.pivot); if (mWidget.pivot != pivot) { NGUIEditorTools.RegisterUndo("Pivot Change", mWidget); mWidget.pivot = pivot; } #else // Pivot point -- the new, more visual style GUILayout.BeginHorizontal(); GUILayout.Label("Pivot", GUILayout.Width(76f)); Toggle("\u25C4", "ButtonLeft", UIWidget.Pivot.Left, true); Toggle("\u25AC", "ButtonMid", UIWidget.Pivot.Center, true); Toggle("\u25BA", "ButtonRight", UIWidget.Pivot.Right, true); Toggle("\u25B2", "ButtonLeft", UIWidget.Pivot.Top, false); Toggle("\u258C", "ButtonMid", UIWidget.Pivot.Center, false); Toggle("\u25BC", "ButtonRight", UIWidget.Pivot.Bottom, false); GUILayout.EndHorizontal(); #endif // Depth navigation if (type != PrefabType.Prefab) { GUILayout.Space(2f); GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Depth"); int depth = mWidget.depth; if (GUILayout.Button("Back", GUILayout.Width(60f))) { --depth; } depth = EditorGUILayout.IntField(depth); if (GUILayout.Button("Forward", GUILayout.Width(60f))) { ++depth; } if (mWidget.depth != depth) { NGUIEditorTools.RegisterUndo("Depth Change", mWidget); mWidget.depth = depth; } } GUILayout.EndHorizontal(); int matchingDepths = 0; for (int i = 0; i < UIWidget.list.size; ++i) { UIWidget w = UIWidget.list[i]; if (w != null && w.depth == mWidget.depth) { ++matchingDepths; } } if (matchingDepths > 1) { EditorGUILayout.HelpBox(matchingDepths + " widgets are using the depth value of " + mWidget.depth + ". It may not be clear what should be in front of what.", MessageType.Warning); } } // Pixel-correctness if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Correction"); if (GUILayout.Button("Make Pixel-Perfect")) { NGUIEditorTools.RegisterUndo("Make Pixel-Perfect", mWidget.transform); mWidget.MakePixelPerfect(); } } GUILayout.EndHorizontal(); } EditorGUILayout.Space(); // Color tint GUILayout.BeginHorizontal(); Color color = EditorGUILayout.ColorField("Color Tint", mWidget.color); if (GUILayout.Button("Copy", GUILayout.Width(50f))) { NGUISettings.color = color; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.color = EditorGUILayout.ColorField("Clipboard", NGUISettings.color); if (GUILayout.Button("Paste", GUILayout.Width(50f))) { color = NGUISettings.color; } GUILayout.EndHorizontal(); if (mWidget.color != color) { NGUIEditorTools.RegisterUndo("Color Change", mWidget); mWidget.color = color; } }
/// <summary> /// Draw the on-screen selection, knobs, and handle all interaction logic. /// </summary> public void OnSceneGUI() { if (!UIWidget.showHandles) { return; } mWidget = target as UIWidget; Handles.color = mOutlineColor; Transform t = mWidget.cachedTransform; Event e = Event.current; int id = GUIUtility.GetControlID(s_Hash, FocusType.Passive); EventType type = e.GetTypeForControl(id); Vector3[] corners = NGUIMath.CalculateWidgetCorners(mWidget); Handles.DrawLine(corners[0], corners[1]); Handles.DrawLine(corners[1], corners[2]); Handles.DrawLine(corners[2], corners[3]); Handles.DrawLine(corners[0], corners[3]); Vector3[] worldPos = new Vector3[8]; worldPos[0] = corners[0]; worldPos[1] = corners[1]; worldPos[2] = corners[2]; worldPos[3] = corners[3]; worldPos[4] = (corners[0] + corners[1]) * 0.5f; worldPos[5] = (corners[1] + corners[2]) * 0.5f; worldPos[6] = (corners[2] + corners[3]) * 0.5f; worldPos[7] = (corners[0] + corners[3]) * 0.5f; Vector2[] screenPos = new Vector2[8]; for (int i = 0; i < 8; ++i) { screenPos[i] = HandleUtility.WorldToGUIPoint(worldPos[i]); } Bounds b = new Bounds(screenPos[0], Vector3.zero); for (int i = 1; i < 8; ++i) { b.Encapsulate(screenPos[i]); } // Time to figure out what kind of action is underneath the mouse Action actionUnderMouse = mAction; UIWidget.Pivot pivotUnderMouse = UIWidget.Pivot.Center; if (actionUnderMouse == Action.None) { int index = 0; float dist = GetScreenDistance(worldPos, e.mousePosition, out index); if (mWidget.showResizeHandles && dist < 10f) { pivotUnderMouse = mPivots[index]; actionUnderMouse = Action.Scale; } else if (e.modifiers == 0 && SceneViewDistanceToRectangle(corners, e.mousePosition) == 0f) { actionUnderMouse = Action.Move; } else if (dist < 30f) { actionUnderMouse = Action.Rotate; } } // Change the mouse cursor to a more appropriate one #if !UNITY_3_5 { Vector2 min = b.min; Vector2 max = b.max; min.x -= 30f; max.x += 30f; min.y -= 30f; max.y += 30f; Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); if (actionUnderMouse == Action.Rotate) { SetCursorRect(rect, MouseCursor.RotateArrow); } else if (actionUnderMouse == Action.Move) { SetCursorRect(rect, MouseCursor.MoveArrow); } else if (mWidget.showResizeHandles && actionUnderMouse == Action.Scale) { SetCursorRect(rect, MouseCursor.ScaleArrow); } else { SetCursorRect(rect, MouseCursor.Arrow); } } #endif switch (type) { case EventType.Repaint: { if (mWidget.showResizeHandles) { Handles.BeginGUI(); { for (int i = 0; i < 8; ++i) { DrawKnob(worldPos[i], mWidget.pivot == mPivots[i], id); } } Handles.EndGUI(); } } break; case EventType.MouseDown: { mStartMouse = e.mousePosition; mAllowSelection = true; if (e.button == 1) { if (e.modifiers == 0) { GUIUtility.hotControl = GUIUtility.keyboardControl = id; e.Use(); } } else if (e.button == 0 && actionUnderMouse != Action.None && Raycast(corners, out mStartDrag)) { mStartPos = t.position; mStartRot = t.localRotation.eulerAngles; mStartDir = mStartDrag - t.position; mStartScale = t.localScale; mDragPivot = pivotUnderMouse; mActionUnderMouse = actionUnderMouse; GUIUtility.hotControl = GUIUtility.keyboardControl = id; e.Use(); } } break; case EventType.MouseDrag: { // Prevent selection once the drag operation begins bool dragStarted = (e.mousePosition - mStartMouse).magnitude > 3f; if (dragStarted) { mAllowSelection = false; } if (GUIUtility.hotControl == id) { e.Use(); if (mAction != Action.None || mActionUnderMouse != Action.None) { Vector3 pos; if (Raycast(corners, out pos)) { if (mAction == Action.None && mActionUnderMouse != Action.None) { // Wait until the mouse moves by more than a few pixels if (dragStarted) { if (mActionUnderMouse == Action.Move) { mStartPos = t.position; NGUIEditorTools.RegisterUndo("Move widget", t); } else if (mActionUnderMouse == Action.Rotate) { mStartRot = t.localRotation.eulerAngles; mStartDir = mStartDrag - t.position; NGUIEditorTools.RegisterUndo("Rotate widget", t); } else if (mActionUnderMouse == Action.Scale) { mStartPos = t.localPosition; mStartScale = t.localScale; mDragPivot = pivotUnderMouse; NGUIEditorTools.RegisterUndo("Scale widget", t); } mAction = actionUnderMouse; } } if (mAction != Action.None) { if (mAction == Action.Move) { t.position = mStartPos + (pos - mStartDrag); pos = t.localPosition; pos.x = Mathf.RoundToInt(pos.x); pos.y = Mathf.RoundToInt(pos.y); t.localPosition = pos; } else if (mAction == Action.Rotate) { Vector3 dir = pos - t.position; float angle = Vector3.Angle(mStartDir, dir); if (angle > 0f) { float dot = Vector3.Dot(Vector3.Cross(mStartDir, dir), t.forward); if (dot < 0f) { angle = -angle; } angle = mStartRot.z + angle; if (e.modifiers != EventModifiers.Shift) { angle = Mathf.Round(angle / 15f) * 15f; } else { angle = Mathf.Round(angle); } t.localRotation = Quaternion.Euler(mStartRot.x, mStartRot.y, angle); } } else if (mAction == Action.Scale) { // World-space delta since the drag started Vector3 delta = pos - mStartDrag; // Adjust the widget's position and scale based on the delta, restricted by the pivot AdjustPosAndScale(mWidget, mStartPos, mStartScale, delta, mDragPivot); } } } } } } break; case EventType.MouseUp: { if (GUIUtility.hotControl == id) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; if (e.button < 2) { bool handled = false; if (e.button == 1) { // Right-click: Select the widget below SelectWidget(mWidget, e.mousePosition, false); handled = true; } else if (mAction == Action.None) { if (mAllowSelection) { // Left-click: Select the widget above SelectWidget(mWidget, e.mousePosition, true); handled = true; } } else { // Finished dragging something mAction = Action.None; mActionUnderMouse = Action.None; Vector3 pos = t.localPosition; Vector3 scale = t.localScale; if (mWidget.pixelPerfectAfterResize) { t.localPosition = pos; t.localScale = scale; mWidget.MakePixelPerfect(); } else { pos.x = Mathf.Round(pos.x); pos.y = Mathf.Round(pos.y); scale.x = Mathf.Round(scale.x); scale.y = Mathf.Round(scale.y); t.localPosition = pos; t.localScale = scale; } handled = true; } if (handled) { mActionUnderMouse = Action.None; mAction = Action.None; e.Use(); } } } else if (mAllowSelection) { BetterList <UIWidget> widgets = SceneViewRaycast(mWidget.panel, e.mousePosition); if (widgets.size > 0) { Selection.activeGameObject = widgets[0].gameObject; } } mAllowSelection = true; } break; case EventType.KeyDown: { if (e.keyCode == KeyCode.UpArrow) { Vector3 pos = t.localPosition; pos.y += 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.DownArrow) { Vector3 pos = t.localPosition; pos.y -= 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.LeftArrow) { Vector3 pos = t.localPosition; pos.x -= 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.RightArrow) { Vector3 pos = t.localPosition; pos.x += 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.Escape) { if (GUIUtility.hotControl == id) { if (mAction != Action.None) { if (mAction == Action.Move) { t.position = mStartPos; } else if (mAction == Action.Rotate) { t.localRotation = Quaternion.Euler(mStartRot); } else if (mAction == Action.Scale) { t.position = mStartPos; t.localScale = mStartScale; } } GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; mActionUnderMouse = Action.None; mAction = Action.None; e.Use(); } else { Selection.activeGameObject = null; } } } break; } }
/// <summary> /// All widgets have depth, color and make pixel-perfect options /// </summary> protected void DrawCommonProperties() { #if UNITY_3_4 PrefabType type = EditorUtility.GetPrefabType(mWidget.gameObject); #else PrefabType type = PrefabUtility.GetPrefabType(mWidget.gameObject); #endif NGUIEditorTools.DrawSeparator(); // Pixel-correctness if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Correction"); if (GUILayout.Button("Make Pixel-Perfect")) { NGUIEditorTools.RegisterUndo("Make Pixel-Perfect", mWidget.transform); mWidget.MakePixelPerfect(); } } GUILayout.EndHorizontal(); } // Pivot point -- old school drop-down style //UIWidget.Pivot pivot = (UIWidget.Pivot)EditorGUILayout.EnumPopup("Pivot", mWidget.pivot); //if (mWidget.pivot != pivot) //{ // NGUIEditorTools.RegisterUndo("Pivot Change", mWidget); // mWidget.pivot = pivot; //} // Pivot point -- the new, more visual style GUILayout.BeginHorizontal(); GUILayout.Label("Pivot", GUILayout.Width(76f)); Toggle("◄", "ButtonLeft", UIWidget.Pivot.Left, true); Toggle("▬", "ButtonMid", UIWidget.Pivot.Center, true); Toggle("►", "ButtonRight", UIWidget.Pivot.Right, true); Toggle("▲", "ButtonLeft", UIWidget.Pivot.Top, false); Toggle("▌", "ButtonMid", UIWidget.Pivot.Center, false); Toggle("▼", "ButtonRight", UIWidget.Pivot.Bottom, false); GUILayout.EndHorizontal(); // Depth navigation if (type != PrefabType.Prefab) { GUILayout.Space(2f); GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Depth"); int depth = mWidget.depth; if (GUILayout.Button("Back", GUILayout.Width(60f))) { --depth; } depth = EditorGUILayout.IntField(depth); if (GUILayout.Button("Forward", GUILayout.Width(60f))) { ++depth; } if (mWidget.depth != depth) { NGUIEditorTools.RegisterUndo("Depth Change", mWidget); mWidget.depth = depth; mDepthCheck = true; } } GUILayout.EndHorizontal(); UIPanel panel = mWidget.panel; if (panel != null) { int count = 0; for (int i = 0; i < panel.widgets.size; ++i) { UIWidget w = panel.widgets[i]; if (w != null && w.depth == mWidget.depth && w.material == mWidget.material) { ++count; } } if (count > 1) { EditorGUILayout.HelpBox(count + " widgets are using the depth value of " + mWidget.depth + ". It may not be clear what should be in front of what.", MessageType.Warning); } if (mDepthCheck) { if (panel.drawCalls.size > 1) { EditorGUILayout.HelpBox("The widgets underneath this panel are using more than one atlas. You may need to adjust transform position's Z value instead. When adjusting the Z, lower value means closer to the camera.", MessageType.Warning); } } } } NGUIEditorTools.DrawSeparator(); // Color tint GUILayout.BeginHorizontal(); Color color = EditorGUILayout.ColorField("Color Tint", mWidget.color); if (GUILayout.Button("Copy", GUILayout.Width(50f))) { NGUISettings.color = color; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.color = EditorGUILayout.ColorField("Clipboard", NGUISettings.color); if (GUILayout.Button("Paste", GUILayout.Width(50f))) { color = NGUISettings.color; } GUILayout.EndHorizontal(); if (mWidget.color != color) { NGUIEditorTools.RegisterUndo("Color Change", mWidget); mWidget.color = color; } }
/// <summary> /// All widgets have depth, color and make pixel-perfect options /// </summary> protected void DrawCommonProperties() { #if UNITY_3_4 PrefabType type = EditorUtility.GetPrefabType(mWidget.gameObject); #else PrefabType type = PrefabUtility.GetPrefabType(mWidget.gameObject); #endif NGUIEditorTools.DrawSeparator(); // Depth navigation if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Depth"); int depth = mWidget.depth; if (GUILayout.Button("Back")) { --depth; } depth = EditorGUILayout.IntField(depth, GUILayout.Width(40f)); if (GUILayout.Button("Forward")) { ++depth; } if (mWidget.depth != depth) { NGUIEditorTools.RegisterUndo("Depth Change", mWidget); mWidget.depth = depth; mDepthCheck = true; } } GUILayout.EndHorizontal(); UIPanel panel = mWidget.panel; if (panel != null) { int count = 0; for (int i = 0; i < panel.widgets.size; ++i) { UIWidget w = panel.widgets[i]; if (w != null && w.depth == mWidget.depth && w.material == mWidget.material) { ++count; } } if (count > 1) { EditorGUILayout.HelpBox(count + " widgets are using the depth value of " + mWidget.depth + ". It may not be clear what should be in front of what.", MessageType.Warning); } if (mDepthCheck) { if (panel.drawCalls.size > 1) { EditorGUILayout.HelpBox("The widgets underneath this panel are using more than one atlas. You may need to adjust transform position's Z value instead. When adjusting the Z, lower value means closer to the camera.", MessageType.Warning); } } } } // Pivot point UIWidget.Pivot pivot = (UIWidget.Pivot)EditorGUILayout.EnumPopup("Pivot", mWidget.pivot); if (mWidget.pivot != pivot) { NGUIEditorTools.RegisterUndo("Pivot Change", mWidget); mWidget.pivot = pivot; } // Pixel-correctness if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Correction"); if (GUILayout.Button("Make Pixel-Perfect")) { NGUIEditorTools.RegisterUndo("Make Pixel-Perfect", mWidget.transform); mWidget.MakePixelPerfect(); } } GUILayout.EndHorizontal(); } // Color tint Color color = EditorGUILayout.ColorField("Color Tint", mWidget.color); if (mWidget.color != color) { NGUIEditorTools.RegisterUndo("Color Change", mWidget); mWidget.color = color; } }
/// <summary> /// Draw the inspector widget. /// </summary> public override void OnInspectorGUI() { Transform trans = target as Transform; EditorGUIUtility.LookLikeControls(15f); serializedObject.Update(); // For clarity purposes, if there is a widget, we want to disable rotation around X and Y, and disable scaling on the Z. bool isWidget = false; bool isStatic = false; foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { UIWidget w = t.GetComponent <UIWidget>(); if (w != null) { isWidget = true; if (Application.isPlaying) { PrefabType type = PrefabUtility.GetPrefabType(w.gameObject); if (type != PrefabType.Prefab) { isStatic = (w.panel != null) && w.panel.widgetsAreStatic; } } break; } } } // Position EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mPosition); if (DrawButton("P", "Reset Position", !isStatic && (axes != Axes.None || IsResetPositionValid(trans)), 20f)) { NGUIEditorTools.RegisterUndo("Reset Position", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { t.localPosition = Vector3.zero; } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localPosition, axes, isStatic ? Axes.None : Axes.All); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Position", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localPosition; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localPosition = v; } } } } EditorGUILayout.EndHorizontal(); // Rotation EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mRotation); if (DrawButton("R", "Reset Rotation", !isStatic && (axes != Axes.None || IsResetRotationValid(trans)), 20f)) { NGUIEditorTools.RegisterUndo("Reset Rotation", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { t.localRotation = Quaternion.identity; } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localEulerAngles, axes, isStatic ? Axes.None : (isWidget ? Axes.Z : Axes.All)); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Rotation", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localEulerAngles; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localEulerAngles = v; } } } } EditorGUILayout.EndHorizontal(); // Scale EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mScale); if (DrawButton("S", "Reset Scale", !isStatic && (axes != Axes.None || IsResetScaleValid(trans)), 20f)) { NGUIEditorTools.RegisterUndo("Reset Scale", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { UIWidget w = t.GetComponent <UIWidget>(); if (w != null) { w.MakePixelPerfect(); } else { t.localScale = Vector3.one; } } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localScale, axes, isStatic ? Axes.None : (isWidget ? (Axes.X | Axes.Y) : Axes.All)); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Scale", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localScale; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localScale = v; } } } } EditorGUILayout.EndHorizontal(); if (isStatic) { EditorGUILayout.HelpBox("The panel managing this widget has the \"widgets are static\" flag set, so all transform changes will be ignored.", MessageType.Warning); } }
/// <summary> /// Draw the on-screen selection, knobs, and handle all interaction logic. /// </summary> public void OnSceneGUI () { if (!UIWidget.showHandles) return; mWidget = target as UIWidget; Handles.color = mOutlineColor; Transform t = mWidget.cachedTransform; Event e = Event.current; int id = GUIUtility.GetControlID(s_Hash, FocusType.Passive); EventType type = e.GetTypeForControl(id); Vector3[] corners = NGUIMath.CalculateWidgetCorners(mWidget); Handles.DrawLine(corners[0], corners[1]); Handles.DrawLine(corners[1], corners[2]); Handles.DrawLine(corners[2], corners[3]); Handles.DrawLine(corners[0], corners[3]); Vector3[] worldPos = new Vector3[8]; worldPos[0] = corners[0]; worldPos[1] = corners[1]; worldPos[2] = corners[2]; worldPos[3] = corners[3]; worldPos[4] = (corners[0] + corners[1]) * 0.5f; worldPos[5] = (corners[1] + corners[2]) * 0.5f; worldPos[6] = (corners[2] + corners[3]) * 0.5f; worldPos[7] = (corners[0] + corners[3]) * 0.5f; Vector2[] screenPos = new Vector2[8]; for (int i = 0; i < 8; ++i) screenPos[i] = HandleUtility.WorldToGUIPoint(worldPos[i]); Bounds b = new Bounds(screenPos[0], Vector3.zero); for (int i = 1; i < 8; ++i) b.Encapsulate(screenPos[i]); // Time to figure out what kind of action is underneath the mouse Action actionUnderMouse = mAction; UIWidget.Pivot pivotUnderMouse = UIWidget.Pivot.Center; if (actionUnderMouse == Action.None) { int index = 0; float dist = GetScreenDistance(worldPos, e.mousePosition, out index); if (mWidget.showResizeHandles && dist < 10f) { pivotUnderMouse = mPivots[index]; actionUnderMouse = Action.Scale; } else if (e.modifiers == 0 && SceneViewDistanceToRectangle(corners, e.mousePosition) == 0f) { actionUnderMouse = Action.Move; } else if (dist < 30f) { actionUnderMouse = Action.Rotate; } } // Change the mouse cursor to a more appropriate one #if !UNITY_3_5 { Vector2 min = b.min; Vector2 max = b.max; min.x -= 30f; max.x += 30f; min.y -= 30f; max.y += 30f; Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); if (actionUnderMouse == Action.Rotate) { SetCursorRect(rect, MouseCursor.RotateArrow); } else if (actionUnderMouse == Action.Move) { SetCursorRect(rect, MouseCursor.MoveArrow); } else if (mWidget.showResizeHandles && actionUnderMouse == Action.Scale) { SetCursorRect(rect, MouseCursor.ScaleArrow); } else SetCursorRect(rect, MouseCursor.Arrow); } #endif switch (type) { case EventType.Repaint: { if (mWidget.showResizeHandles) { Handles.BeginGUI(); { for (int i = 0; i < 8; ++i) { DrawKnob(worldPos[i], mWidget.pivot == mPivots[i], id); } } Handles.EndGUI(); } } break; case EventType.MouseDown: { mStartMouse = e.mousePosition; mAllowSelection = true; if (e.button == 1) { if (e.modifiers == 0) { GUIUtility.hotControl = GUIUtility.keyboardControl = id; e.Use(); } } else if (e.button == 0 && actionUnderMouse != Action.None && Raycast(corners, out mStartDrag)) { mStartPos = t.position; mStartRot = t.localRotation.eulerAngles; mStartDir = mStartDrag - t.position; mStartScale = t.localScale; mDragPivot = pivotUnderMouse; mActionUnderMouse = actionUnderMouse; GUIUtility.hotControl = GUIUtility.keyboardControl = id; e.Use(); } } break; case EventType.MouseDrag: { // Prevent selection once the drag operation begins bool dragStarted = (e.mousePosition - mStartMouse).magnitude > 3f; if (dragStarted) mAllowSelection = false; if (GUIUtility.hotControl == id) { e.Use(); if (mAction != Action.None || mActionUnderMouse != Action.None) { Vector3 pos; if (Raycast(corners, out pos)) { if (mAction == Action.None && mActionUnderMouse != Action.None) { // Wait until the mouse moves by more than a few pixels if (dragStarted) { if (mActionUnderMouse == Action.Move) { mStartPos = t.position; NGUIEditorTools.RegisterUndo("Move widget", t); } else if (mActionUnderMouse == Action.Rotate) { mStartRot = t.localRotation.eulerAngles; mStartDir = mStartDrag - t.position; NGUIEditorTools.RegisterUndo("Rotate widget", t); } else if (mActionUnderMouse == Action.Scale) { mStartPos = t.localPosition; mStartScale = t.localScale; mDragPivot = pivotUnderMouse; NGUIEditorTools.RegisterUndo("Scale widget", t); } mAction = actionUnderMouse; } } if (mAction != Action.None) { if (mAction == Action.Move) { t.position = mStartPos + (pos - mStartDrag); pos = t.localPosition; pos.x = Mathf.RoundToInt(pos.x); pos.y = Mathf.RoundToInt(pos.y); t.localPosition = pos; } else if (mAction == Action.Rotate) { Vector3 dir = pos - t.position; float angle = Vector3.Angle(mStartDir, dir); if (angle > 0f) { float dot = Vector3.Dot(Vector3.Cross(mStartDir, dir), t.forward); if (dot < 0f) angle = -angle; angle = mStartRot.z + angle; if (e.modifiers != EventModifiers.Shift) angle = Mathf.Round(angle / 15f) * 15f; else angle = Mathf.Round(angle); t.localRotation = Quaternion.Euler(mStartRot.x, mStartRot.y, angle); } } else if (mAction == Action.Scale) { // World-space delta since the drag started Vector3 delta = pos - mStartDrag; // Adjust the widget's position and scale based on the delta, restricted by the pivot AdjustPosAndScale(mWidget, mStartPos, mStartScale, delta, mDragPivot); } } } } } } break; case EventType.MouseUp: { if (GUIUtility.hotControl == id) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; if (e.button < 2) { bool handled = false; if (e.button == 1) { // Right-click: Select the widget below SelectWidget(mWidget, e.mousePosition, false); handled = true; } else if (mAction == Action.None) { if (mAllowSelection) { // Left-click: Select the widget above SelectWidget(mWidget, e.mousePosition, true); handled = true; } } else { // Finished dragging something mAction = Action.None; mActionUnderMouse = Action.None; Vector3 pos = t.localPosition; Vector3 scale = t.localScale; if (mWidget.pixelPerfectAfterResize) { t.localPosition = pos; t.localScale = scale; mWidget.MakePixelPerfect(); } else { pos.x = Mathf.Round(pos.x); pos.y = Mathf.Round(pos.y); scale.x = Mathf.Round(scale.x); scale.y = Mathf.Round(scale.y); t.localPosition = pos; t.localScale = scale; } handled = true; } if (handled) { mActionUnderMouse = Action.None; mAction = Action.None; e.Use(); } } } else if (mAllowSelection) { BetterList<UIWidget> widgets = SceneViewRaycast(mWidget.panel, e.mousePosition); if (widgets.size > 0) Selection.activeGameObject = widgets[0].gameObject; } mAllowSelection = true; } break; case EventType.KeyDown: { if (e.keyCode == KeyCode.UpArrow) { Vector3 pos = t.localPosition; pos.y += 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.DownArrow) { Vector3 pos = t.localPosition; pos.y -= 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.LeftArrow) { Vector3 pos = t.localPosition; pos.x -= 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.RightArrow) { Vector3 pos = t.localPosition; pos.x += 1f; t.localPosition = pos; e.Use(); } else if (e.keyCode == KeyCode.Escape) { if (GUIUtility.hotControl == id) { if (mAction != Action.None) { if (mAction == Action.Move) { t.position = mStartPos; } else if (mAction == Action.Rotate) { t.localRotation = Quaternion.Euler(mStartRot); } else if (mAction == Action.Scale) { t.position = mStartPos; t.localScale = mStartScale; } } GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; mActionUnderMouse = Action.None; mAction = Action.None; e.Use(); } else Selection.activeGameObject = null; } } break; } }
/// <summary> /// All widgets have depth, color and make pixel-perfect options /// </summary> protected void DrawCommonProperties() { #if UNITY_3_4 PrefabType type = EditorUtility.GetPrefabType(mWidget.gameObject); #else PrefabType type = PrefabUtility.GetPrefabType(mWidget.gameObject); #endif NGUIEditorTools.DrawSeparator(); // Depth navigation if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Depth"); int depth = mWidget.depth; if (GUILayout.Button("Back")) { --depth; } depth = EditorGUILayout.IntField(depth, GUILayout.Width(40f)); if (GUILayout.Button("Forward")) { ++depth; } if (mWidget.depth != depth) { NGUIEditorTools.RegisterUndo("Depth Change", mWidget); mWidget.depth = depth; } } GUILayout.EndHorizontal(); } Color color = EditorGUILayout.ColorField("Color Tint", mWidget.color); if (mWidget.color != color) { NGUIEditorTools.RegisterUndo("Color Change", mWidget); mWidget.color = color; } // Depth navigation if (type != PrefabType.Prefab) { GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Correction"); if (GUILayout.Button("Make Pixel-Perfect")) { NGUIEditorTools.RegisterUndo("Make Pixel-Perfect", mWidget.transform); mWidget.MakePixelPerfect(); } } GUILayout.EndHorizontal(); } UIWidget.Pivot pivot = (UIWidget.Pivot)EditorGUILayout.EnumPopup("Pivot", mWidget.pivot); if (mWidget.pivot != pivot) { NGUIEditorTools.RegisterUndo("Pivot Change", mWidget); mWidget.pivot = pivot; } if (mAllowPreview && mWidget.mainTexture != null) { GUILayout.BeginHorizontal(); { UISettings.texturePreview = EditorGUILayout.Toggle("Preview", UISettings.texturePreview, GUILayout.Width(100f)); /*if (UISettings.texturePreview) * { * if (mUseShader != EditorGUILayout.Toggle("Use Shader", mUseShader)) * { * mUseShader = !mUseShader; * * if (mUseShader) * { * // TODO: Remove this when Unity fixes the bug with DrawPreviewTexture not being affected by BeginGroup * Debug.LogWarning("There is a bug in Unity that prevents the texture from getting clipped properly.\n" + * "Until it's fixed by Unity, your texture may spill onto the rest of the Unity's GUI while using this mode."); * } * } * }*/ } GUILayout.EndHorizontal(); // Draw the texture last if (UISettings.texturePreview) { OnDrawTexture(); } } }
/// <summary> /// All widgets have depth, color and make pixel-perfect options /// </summary> protected void DrawCommonProperties() { PrefabType type = PrefabUtility.GetPrefabType(mWidget.gameObject); if (NGUIEditorTools.DrawHeader("Widget")) { NGUIEditorTools.BeginContents(); // Color tint GUILayout.BeginHorizontal(); Color color = EditorGUILayout.ColorField("Color Tint", mWidget.color); if (GUILayout.Button("Copy", GUILayout.Width(50f))) { NGUISettings.color = color; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.color = EditorGUILayout.ColorField("Clipboard", NGUISettings.color); if (GUILayout.Button("Paste", GUILayout.Width(50f))) { color = NGUISettings.color; } GUILayout.EndHorizontal(); if (mWidget.color != color) { NGUIEditorTools.RegisterUndo("Color Change", mWidget); mWidget.color = color; } GUILayout.Space(6f); #if UNITY_3_5 // Pivot point -- old school drop-down style UIWidget.Pivot pivot = (UIWidget.Pivot)EditorGUILayout.EnumPopup("Pivot", mWidget.pivot); if (mWidget.pivot != pivot) { NGUIEditorTools.RegisterUndo("Pivot Change", mWidget); mWidget.pivot = pivot; } #else // Pivot point -- the new, more visual style GUILayout.BeginHorizontal(); GUILayout.Label("Pivot", GUILayout.Width(76f)); Toggle("\u25C4", "ButtonLeft", UIWidget.Pivot.Left, true); Toggle("\u25AC", "ButtonMid", UIWidget.Pivot.Center, true); Toggle("\u25BA", "ButtonRight", UIWidget.Pivot.Right, true); Toggle("\u25B2", "ButtonLeft", UIWidget.Pivot.Top, false); Toggle("\u258C", "ButtonMid", UIWidget.Pivot.Center, false); Toggle("\u25BC", "ButtonRight", UIWidget.Pivot.Bottom, false); GUILayout.EndHorizontal(); #endif // Depth navigation if (type != PrefabType.Prefab) { GUILayout.Space(2f); GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Depth"); int depth = mWidget.depth; if (GUILayout.Button("Back", GUILayout.Width(60f))) { --depth; } depth = EditorGUILayout.IntField(depth, GUILayout.MinWidth(20f)); if (GUILayout.Button("Forward", GUILayout.Width(68f))) { ++depth; } if (mWidget.depth != depth) { NGUIEditorTools.RegisterUndo("Depth Change", mWidget); mWidget.depth = depth; } } GUILayout.EndHorizontal(); int matchingDepths = 0; for (int i = 0; i < UIWidget.list.size; ++i) { UIWidget w = UIWidget.list[i]; if (w != null && w.panel != null && mWidget.panel != null && w.panel.depth == mWidget.panel.depth && w.depth == mWidget.depth) { ++matchingDepths; } } if (matchingDepths > 1) { EditorGUILayout.HelpBox(matchingDepths + " widgets are sharing the depth value of " + mWidget.depth, MessageType.Info); } } GUI.changed = false; GUILayout.BeginHorizontal(); int width = EditorGUILayout.IntField("Dimensions", mWidget.width, GUILayout.Width(128f)); NGUIEditorTools.SetLabelWidth(12f); int height = EditorGUILayout.IntField("x", mWidget.height, GUILayout.MinWidth(30f)); NGUIEditorTools.SetLabelWidth(80f); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Widget Change", mWidget); mWidget.width = width; mWidget.height = height; } if (type != PrefabType.Prefab) { if (GUILayout.Button("Correct", GUILayout.Width(68f))) { NGUIEditorTools.RegisterUndo("Widget Change", mWidget); NGUIEditorTools.RegisterUndo("Make Pixel-Perfect", mWidget.transform); mWidget.MakePixelPerfect(); } } else { GUILayout.Space(70f); } GUILayout.EndHorizontal(); NGUIEditorTools.EndContents(); } }
/// <summary> /// Draw the inspector widget. /// </summary> public override void OnInspectorGUI() { Transform trans = target as Transform; EditorGUIUtility.LookLikeControls(15f); serializedObject.Update(); // For clarity purposes, if there is a widget, we want to disable rotation around X and Y, and disable scaling on the Z. bool isWidget = false; foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { if (t.GetComponent <UIWidget>() != null) { isWidget = true; break; } } } // Position EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mPosition); if (DrawButton("P", "Reset Position", axes != Axes.None || IsResetPositionValid(trans), 20f)) { NGUIEditorTools.RegisterUndo("Reset Position", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { t.localPosition = Vector3.zero; } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localPosition, axes, Axes.All); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Position", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localPosition; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localPosition = v; } } } } EditorGUILayout.EndHorizontal(); // Rotation EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mRotation); if (DrawButton("R", "Reset Rotation", axes != Axes.None || IsResetRotationValid(trans), 20f)) { NGUIEditorTools.RegisterUndo("Reset Rotation", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { t.localRotation = Quaternion.identity; } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localEulerAngles, axes, isWidget ? Axes.Z : Axes.All); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Rotation", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localEulerAngles; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localEulerAngles = v; } } } } EditorGUILayout.EndHorizontal(); // Scale EditorGUILayout.BeginHorizontal(); { Axes axes = GetMultipleValuesAxes(mScale); if (DrawButton("S", "Reset Scale", (axes != Axes.None || IsResetScaleValid(trans)), 20f)) { NGUIEditorTools.RegisterUndo("Reset Scale", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { UIWidget w = t.GetComponent <UIWidget>(); if (w != null) { w.MakePixelPerfect(); } else { t.localScale = Vector3.one; } } } } GUI.changed = false; VectorWrapper final = DrawVector3(trans.localScale, axes, isWidget ? (Axes.X | Axes.Y) : Axes.All); if (GUI.changed) { NGUIEditorTools.RegisterUndo("Reset Scale", serializedObject.targetObjects); foreach (Object obj in serializedObject.targetObjects) { Transform t = obj as Transform; if (t != null) { Vector3 v = t.localScale; if ((final.axes & Axes.X) != 0) { v.x = final.value.x; } if ((final.axes & Axes.Y) != 0) { v.y = final.value.y; } if ((final.axes & Axes.Z) != 0) { v.z = final.value.z; } t.localScale = v; } } } } EditorGUILayout.EndHorizontal(); }