internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion rotation, Vector3 position, RotationHandleParam param) { var evt = Event.current; var camForward = Handles.inverseMatrix.MultiplyVector(Camera.current != null ? Camera.current.transform.forward : Vector3.forward); var size = HandleUtility.GetHandleSize(position); var temp = color; bool isDisabled = !GUI.enabled; var isHot = ids.Has(GUIUtility.hotControl); VertexSnapping.HandleMouseMove(ids.xyz); // Draw free rotation first to give it the lowest priority if (!isDisabled && param.ShouldShow(RotationHandleParam.Handle.XYZ) && (ids.xyz == GUIUtility.hotControl || !isHot)) { color = new Color(0, 0, 0, 0.3f); rotation = UnityEditorInternal.FreeRotate.Do(ids.xyz, rotation, position, size * param.xyzSize, param.displayXYZCircle); } for (var i = 0; i < 3; ++i) { if (!param.ShouldShow(i)) { continue; } var axisColor = GetColorByAxis(i); color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; color = ToActiveColorSpace(color); var axisDir = GetAxisVector(i); var radius = size * param.axisSize[i]; rotation = UnityEditorInternal.Disc.Do(ids[i], rotation, position, rotation * axisDir, radius, true, EditorSnapSettings.rotate, param.enableRayDrag, true, k_RotationPieColor); } // while dragging any rotation handles, draw a gray disc outline if (isHot && evt.type == EventType.Repaint) { color = ToActiveColorSpace(s_DisabledHandleColor); Handles.DrawWireDisc(position, camForward, size * param.axisSize[0], Handles.lineThickness); } if (!isDisabled && param.ShouldShow(RotationHandleParam.Handle.CameraAxis) && (ids.cameraAxis == GUIUtility.hotControl || !isHot)) { color = ToActiveColorSpace(centerColor); rotation = UnityEditorInternal.Disc.Do(ids.cameraAxis, rotation, position, camForward, size * param.cameraAxisSize, false, 0, param.enableRayDrag, true, k_RotationPieColor); } color = temp; return(rotation); }
static Vector3 DoPositionHandle_Internal(PositionHandleIds ids, Vector3 position, Quaternion rotation, PositionHandleParam param) { Color temp = color; bool isDisabled = !GUI.enabled; // Calculate the camera view vector in Handle draw space // this handle the case where the matrix is skewed var handlePosition = matrix.MultiplyPoint3x4(position); var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one); var invDrawToWorldMatrix = drawToWorldMatrix.inverse; var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix); var size = HandleUtility.GetHandleSize(position); // Calculate per axis camera lerp for (var i = 0; i < 3; ++i) { s_DoPositionHandle_Internal_CameraViewLerp[i] = ids[i] == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, GetAxisVector(i)); } // Calculate per plane camera lerp (xy, yz, xz) for (var i = 0; i < 3; ++i) { s_DoPositionHandle_Internal_CameraViewLerp[3 + i] = Mathf.Max(s_DoPositionHandle_Internal_CameraViewLerp[i], s_DoPositionHandle_Internal_CameraViewLerp[(i + 1) % 3]); } var isHot = ids.Has(GUIUtility.hotControl); var axisOffset = param.axisOffset; var planeOffset = param.planeOffset; if (isHot) { axisOffset = Vector3.zero; planeOffset = Vector3.zero; } // Draw plane handles (xy, yz, xz) var planeSize = isHot ? param.planeSize + param.planeOffset : param.planeSize; for (var i = 0; i < 3; ++i) { if (!param.ShouldShow(3 + i) || isHot && ids[3 + i] != GUIUtility.hotControl) { continue; } var cameraLerp = isHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[3 + i]; if (cameraLerp <= kCameraViewThreshold) { var offset = planeOffset * size; offset[s_DoPositionHandle_Internal_PrevIndex[i]] = 0; var planarSize = Mathf.Max(planeSize[i], planeSize[s_DoPositionHandle_Internal_NextIndex[i]]); position = DoPlanarHandle(ids[3 + i], i, position, offset, rotation, size * planarSize, cameraLerp, viewVectorDrawSpace, param.planeOrientation); } } // Draw axis sliders // Draw last to have priority over the planes for (var i = 0; i < 3; ++i) { if (!param.ShouldShow(i)) { continue; } if (!currentlyDragging) { switch (param.axesOrientation) { case PositionHandleParam.Orientation.Camera: s_DoPositionHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1; break; case PositionHandleParam.Orientation.Signed: s_DoPositionHandle_AxisHandlesOctant[i] = 1; break; } } var isThisAxisHot = isHot && ids[i] == GUIUtility.hotControl; var axisColor = GetColorByAxis(i); color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; GUI.SetNextControlName(s_DoPositionHandle_Internal_AxisNames[i]); // if we are hot here, the hot handle must be opaque var cameraLerp = isThisAxisHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[i]; if (cameraLerp <= kCameraViewThreshold) { color = Color.Lerp(color, Color.clear, cameraLerp); var axisVector = GetAxisVector(i); var dir = rotation * axisVector; var offset = dir * axisOffset[i] * size; dir *= s_DoPositionHandle_AxisHandlesOctant[i]; offset *= s_DoPositionHandle_AxisHandlesOctant[i]; if (isHot && !isThisAxisHot) { color = s_DisabledHandleColor; } // A plane with this axis is hot if (isHot && (ids[s_DoPositionHandle_Internal_PrevPlaneIndex[i]] == GUIUtility.hotControl || ids[i + 3] == GUIUtility.hotControl)) { color = selectedColor; } color = ToActiveColorSpace(color); s_DoPositionHandle_ArrowCapConeOffset = isHot ? rotation * Vector3.Scale(Vector3.Scale(axisVector, param.axisOffset), s_DoPositionHandle_AxisHandlesOctant) : Vector3.zero; position = Slider(ids[i], position, offset, dir, size * param.axisSize[i], DoPositionHandle_ArrowCap, GridSnapping.active ? 0f : EditorSnapSettings.move[i]); } } VertexSnapping.HandleMouseMove(ids.xyz); if (param.ShouldShow(PositionHandleParam.Handle.XYZ) && (isHot && ids.xyz == GUIUtility.hotControl || !isHot)) { color = ToActiveColorSpace(centerColor); GUI.SetNextControlName("FreeMoveAxis"); position = FreeMoveHandle(ids.xyz, position, rotation, size * kFreeMoveHandleSizeFactor, GridSnapping.active ? Vector3.zero : EditorSnapSettings.move, RectangleHandleCap); } if (GridSnapping.active) { position = GridSnapping.Snap(position); } color = temp; return(position); }
static Vector3 MoveHandlesGUI(Rect rect, Vector3 pivot, Quaternion rotation) { int id = GUIUtility.GetControlID(s_MoveHandleHash, FocusType.Passive); Vector3 newPos = pivot; float discSize = HandleUtility.GetHandleSize(pivot) * 0.2f; float discOpacity = (1 - GUI.color.a); Vector3[] corners = new Vector3[4]; corners[0] = rotation * new Vector2(rect.x, rect.y) + pivot; corners[1] = rotation * new Vector2(rect.xMax, rect.y) + pivot; corners[2] = rotation * new Vector2(rect.xMax, rect.yMax) + pivot; corners[3] = rotation * new Vector2(rect.x, rect.yMax) + pivot; VertexSnapping.HandleMouseMove(id); bool supportsRectSnapping = Selection.transforms.Length == 1 && UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(Selection.activeTransform) && Selection.activeTransform.parent.rotation == rotation; Event evt = Event.current; EventType eventType = evt.GetTypeForControl(id); Plane guiPlane = new Plane(corners[0], corners[1], corners[2]); switch (eventType) { case EventType.MouseDown: { bool acceptClick = false; if (Tools.vertexDragging) { acceptClick = true; } else { acceptClick = evt.button == 0 && evt.modifiers == 0 && RectHandles.RaycastGUIPointToWorldHit(evt.mousePosition, guiPlane, out s_StartMouseWorldPos) && ( SceneViewDistanceToRectangle(corners, evt.mousePosition) == 0f || (discOpacity > 0 && SceneViewDistanceToDisc(pivot, rotation * Vector3.forward, discSize, evt.mousePosition) == 0f) ); } if (acceptClick) { s_StartPosition = pivot; s_StartMousePos = s_CurrentMousePos = evt.mousePosition; s_Moving = false; s_LockAxis = -1; GUIUtility.hotControl = GUIUtility.keyboardControl = id; EditorGUIUtility.SetWantsMouseJumping(1); HandleUtility.ignoreRaySnapObjects = null; evt.Use(); // Calculate snapping values if applicable if (supportsRectSnapping) { Transform transform = Selection.activeTransform; RectTransform rectTransform = transform.GetComponent <RectTransform>(); Transform transformParent = transform.parent; RectTransform rectTransformParent = transformParent.GetComponent <RectTransform>(); s_StartRectPosition = rectTransform.anchoredPosition; RectTransformSnapping.CalculatePositionSnapValues(transformParent, transform, rectTransformParent, rectTransform); } } break; } case EventType.MouseDrag: { if (GUIUtility.hotControl == id) { s_CurrentMousePos += evt.delta; if (!s_Moving && (s_CurrentMousePos - s_StartMousePos).magnitude > 3f) { s_Moving = true; // Re-raycast to get start mouse pos when effective dragging starts. // This prevents a sudden unsnap when the dragging is enabled. RectHandles.RaycastGUIPointToWorldHit(s_CurrentMousePos, guiPlane, out s_StartMouseWorldPos); } if (s_Moving) { if (Tools.vertexDragging) { if (HandleUtility.ignoreRaySnapObjects == null) { Handles.SetupIgnoreRaySnapObjects(); } Vector3 near; if (HandleUtility.FindNearestVertex(s_CurrentMousePos, null, out near)) { // Snap position based on found near vertex newPos = near; GUI.changed = true; } ManipulationToolUtility.minDragDifference = Vector2.zero; } else { ManipulationToolUtility.SetMinDragDifferenceForPos(pivot); Vector3 pos; if (RectHandles.RaycastGUIPointToWorldHit(s_CurrentMousePos, guiPlane, out pos)) { Vector3 offset = pos - s_StartMouseWorldPos; // Snap to axis if (evt.shift) { // Get offset in rect handles space offset = Quaternion.Inverse(rotation) * offset; // Determine lock axis if not already set if (s_LockAxis == -1) { s_LockAxis = Mathf.Abs(offset.x) > Mathf.Abs(offset.y) ? 0 : 1; } // Cancel mocement on other axis offset[1 - s_LockAxis] = 0; // Put offset back in world space offset = rotation * offset; } else { s_LockAxis = -1; } if (supportsRectSnapping) { Transform transformParent = Selection.activeTransform.parent; Vector3 rectPosition = s_StartRectPosition + transformParent.InverseTransformVector(offset); rectPosition.z = 0; Quaternion inverseRotation = Quaternion.Inverse(rotation); Vector2 snapSize = Vector2.one * HandleUtility.GetHandleSize(newPos) * RectTransformSnapping.kSnapThreshold; snapSize.x /= (inverseRotation * transformParent.TransformVector(Vector3.right)).x; snapSize.y /= (inverseRotation * transformParent.TransformVector(Vector3.up)).y; Vector3 newRectPosition = RectTransformSnapping.SnapToGuides(rectPosition, snapSize); ManipulationToolUtility.DisableMinDragDifferenceBasedOnSnapping(rectPosition, newRectPosition); offset = transformParent.TransformVector(newRectPosition - s_StartRectPosition); } newPos = s_StartPosition + offset; GUI.changed = true; } } } evt.Use(); } break; } case EventType.MouseUp: { if (GUIUtility.hotControl == id) { if (!s_Moving) { Selection.activeGameObject = SceneViewPicking.PickGameObject(evt.mousePosition); } GUIUtility.hotControl = 0; EditorGUIUtility.SetWantsMouseJumping(0); HandleUtility.ignoreRaySnapObjects = null; evt.Use(); } break; } case EventType.Repaint: { if (Tools.vertexDragging) { RectHandles.RectScalingHandleCap(id, pivot, rotation, 1, EventType.Repaint); } else { Handles.color = Handles.secondaryColor * new Color(1, 1, 1, 1.5f * discOpacity); Handles.CircleHandleCap(id, pivot, rotation, discSize, EventType.Repaint); Handles.color = Handles.secondaryColor * new Color(1, 1, 1, 0.3f * discOpacity); Handles.DrawSolidDisc(pivot, rotation * Vector3.forward, discSize); } break; } } ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingPosX, eventType); ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingLeft, eventType); ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingRight, eventType); ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingPosY, eventType); ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingTop, eventType); ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingBottom, eventType); return(newPos); }
internal static Vector3 DoScaleHandle(ScaleHandleIds ids, Vector3 scale, Vector3 position, Quaternion rotation, float handleSize, ScaleHandleParam param, bool isProportionalScale = false) { // Calculate the camera view vector in Handle draw space // this handle the case where the matrix is skewed var handlePosition = matrix.MultiplyPoint3x4(position); var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one); var invDrawToWorldMatrix = drawToWorldMatrix.inverse; var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix); var isDisabled = !GUI.enabled; var isHot = ids.Has(GUIUtility.hotControl); var axisOffset = param.axisOffset; var axisLineScale = param.axisLineScale; // When an axis is hot, draw the line from the center to the handle // So ignore the offset if (isHot) { axisLineScale += axisOffset; axisOffset = Vector3.zero; } var isCenterIsHot = ids.xyz == GUIUtility.hotControl; VertexSnapping.HandleMouseMove(ids.xyz); switch (Event.current.type) { case EventType.MouseDown: s_InitialScale = scale == Vector3.zero ? Vector3.one : scale; s_CurrentMultiplier = 1.0f; break; case EventType.MouseDrag: if (isProportionalScale) { proportionalScale = true; } break; case EventType.MouseUp: proportionalScale = false; break; } CalcDrawOrder(viewVectorDrawSpace, s_DoScaleHandle_AxisDrawOrder); for (var ii = 0; ii < 3; ++ii) { int i = s_DoScaleHandle_AxisDrawOrder[ii]; int axisIndex = i; if (!param.ShouldShow(i)) { continue; } if (!currentlyDragging) { switch (param.orientation) { case ScaleHandleParam.Orientation.Signed: s_DoScaleHandle_AxisHandlesOctant[i] = 1; break; case ScaleHandleParam.Orientation.Camera: s_DoScaleHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1; break; } } var id = ids[i]; var isThisAxisHot = isHot && id == GUIUtility.hotControl; var axisDir = GetAxisVector(i); var axisColor = isProportionalScale ? constrainProportionsScaleHandleColor : GetColorByAxis(i); var offset = axisOffset[i]; var cameraLerp = id == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, axisDir); // If we are here and is hot, then this axis is hot and must be opaque cameraLerp = isHot ? 0 : cameraLerp; color = isDisabled ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; axisDir *= s_DoScaleHandle_AxisHandlesOctant[i]; if (cameraLerp <= kCameraViewThreshold) { color = GetFadedAxisColor(color, cameraLerp, id); if (isHot && !isThisAxisHot) { color = isProportionalScale ? selectedColor : s_DisabledHandleColor; } if (isCenterIsHot) { color = selectedColor; } color = ToActiveColorSpace(color); if (isProportionalScale) { axisIndex = 0; } scale = UnityEditorInternal.SliderScale.DoAxis( id, scale, axisIndex, position, rotation * axisDir, rotation, handleSize * param.axisSize[axisIndex], EditorSnapSettings.scale, offset, axisLineScale[axisIndex], s_InitialScale, isProportionalScale); } } if (param.ShouldShow(ScaleHandleParam.Handle.XYZ) && (ids.xyz == GUIUtility.hotControl || !isHot)) { color = isProportionalScale ? constrainProportionsScaleHandleColor : ToActiveColorSpace(centerColor); proportionalScale = false; EditorGUI.BeginChangeCheck(); s_CurrentMultiplier = ScaleValueHandle(ids.xyz, s_CurrentMultiplier, position, rotation, handleSize * param.xyzSize, CubeHandleCap, EditorSnapSettings.scale); if (EditorGUI.EndChangeCheck()) { scale = s_InitialScale * s_CurrentMultiplier; } } return(scale); }