/// <summary> /// Creates GUI elements for fields specific to the capsule collider. /// </summary> protected void BuildGUI(CapsuleCollider collider) { centerField.OnChanged += x => { collider.Center = x; MarkAsModified(); }; centerField.OnFocusLost += ConfirmModify; centerField.OnConfirmed += ConfirmModify; orientationField.OnChanged += x => { orientation = x; Quaternion rotation = Quaternion.FromEuler(x); collider.Normal = rotation.Rotate(Vector3.YAxis); MarkAsModified(); }; orientationField.OnFocusLost += ConfirmModify; orientationField.OnConfirmed += ConfirmModify; radiusField.OnChanged += x => { collider.Radius = x; MarkAsModified(); }; radiusField.OnFocusLost += ConfirmModify; radiusField.OnConfirmed += ConfirmModify; halfHeightField.OnChanged += x => { collider.HalfHeight = x; MarkAsModified(); }; halfHeightField.OnFocusLost += ConfirmModify; halfHeightField.OnConfirmed += ConfirmModify; Layout.AddElement(centerField); Layout.AddElement(orientationField); Layout.AddElement(radiusField); Layout.AddElement(halfHeightField); orientation = Quaternion.FromToRotation(Vector3.YAxis, collider.Normal).ToEuler(); base.BuildGUI(collider); }
/// <summary> /// Creates a new rectangle. /// </summary> /// <param name="center">Origin of the rectangle. </param> /// <param name="axes">Two axes that define orientation of the rectangle. Axes extend from the origin. Axes should /// be normalized.</param> /// <param name="extents">Two extents that define the size of the rectangle. Extends should be half the width/height /// as they are applied in both directions.</param> public Rect3(Vector3 center, Vector3[] axes, float[] extents) { this._center = center; _axisHorz = axes[0]; _axisVert = axes[1]; _extentHorz = extents[0]; _extentVert = extents[1]; }
/// <summary> /// Creates GUI elements for fields specific to the plane collider. /// </summary> protected void BuildGUI(PlaneCollider collider) { normalField.OnChanged += x => { normal = x; collider.Normal = x; MarkAsModified(); }; normalField.OnFocusLost += ConfirmModify; normalField.OnConfirmed += ConfirmModify; distanceField.OnChanged += x => { collider.Distance = x; MarkAsModified(); }; distanceField.OnFocusLost += ConfirmModify; distanceField.OnConfirmed += ConfirmModify; Layout.AddElement(normalField); Layout.AddElement(distanceField); normal = collider.Normal; base.BuildGUI(collider); }
private void OnUpdate() { bool isOrtographic = camera.ProjectionType == ProjectionType.Orthographic; if (inputEnabled) { bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn); bool goingBack = VirtualInput.IsButtonHeld(moveBackwardBtn); bool goingLeft = VirtualInput.IsButtonHeld(moveLeftBtn); bool goingRight = VirtualInput.IsButtonHeld(moveRightBtn); bool goingUp = VirtualInput.IsButtonHeld(moveUpBtn); bool goingDown = VirtualInput.IsButtonHeld(moveDownBtn); bool fastMove = VirtualInput.IsButtonHeld(fastMoveBtn); bool camActive = VirtualInput.IsButtonHeld(activeBtn); bool isPanning = VirtualInput.IsButtonHeld(panBtn); bool hideCursor = camActive || isPanning; if (hideCursor != lastButtonState) { if (hideCursor) { Cursor.Hide(); Rect2I clipRect; clipRect.x = Input.PointerPosition.x - 2; clipRect.y = Input.PointerPosition.y - 2; clipRect.width = 4; clipRect.height = 4; Cursor.ClipToRect(clipRect); } else { Cursor.Show(); Cursor.ClipDisable(); } lastButtonState = hideCursor; } float frameDelta = Time.FrameDelta; if (camActive) { float horzValue = VirtualInput.GetAxisValue(horizontalAxis); float vertValue = VirtualInput.GetAxisValue(verticalAxis); float rotationAmount = RotationalSpeed * EditorSettings.MouseSensitivity * frameDelta; yaw += new Degree(horzValue * rotationAmount); pitch += new Degree(vertValue * rotationAmount); yaw = MathEx.WrapAngle(yaw); pitch = MathEx.WrapAngle(pitch); Quaternion yRot = Quaternion.FromAxisAngle(Vector3.YAxis, yaw); Quaternion xRot = Quaternion.FromAxisAngle(Vector3.XAxis, pitch); Quaternion camRot = yRot*xRot; camRot.Normalize(); SceneObject.Rotation = camRot; // Handle movement using movement keys Vector3 direction = Vector3.Zero; if (goingForward) direction += SceneObject.Forward; if (goingBack) direction -= SceneObject.Forward; if (goingRight) direction += SceneObject.Right; if (goingLeft) direction -= SceneObject.Right; if (goingUp) direction += SceneObject.Up; if (goingDown) direction -= SceneObject.Up; if (direction.SqrdLength != 0) { direction.Normalize(); float multiplier = 1.0f; if (fastMove) multiplier = FastModeMultiplier; currentSpeed = MathEx.Clamp(currentSpeed + Acceleration*frameDelta, StartSpeed, TopSpeed); currentSpeed *= multiplier; } else { currentSpeed = 0.0f; } const float tooSmall = 0.0001f; if (currentSpeed > tooSmall) { Vector3 velocity = direction*currentSpeed; SceneObject.Move(velocity*frameDelta); } } // Pan if (isPanning) { float horzValue = VirtualInput.GetAxisValue(horizontalAxis); float vertValue = VirtualInput.GetAxisValue(verticalAxis); Vector3 direction = new Vector3(horzValue, -vertValue, 0.0f); direction = camera.SceneObject.Rotation.Rotate(direction); SceneObject.Move(direction*PanSpeed*frameDelta); } } else { Cursor.Show(); Cursor.ClipDisable(); } SceneWindow sceneWindow = EditorWindow.GetWindow<SceneWindow>(); if (sceneWindow.Active) { Rect2I bounds = sceneWindow.Bounds; // Move using scroll wheel if (bounds.Contains(Input.PointerPosition)) { float scrollAmount = VirtualInput.GetAxisValue(scrollAxis); if (!isOrtographic) { SceneObject.Move(SceneObject.Forward*scrollAmount*ScrollSpeed); } else { float orthoHeight = MathEx.Max(1.0f, camera.OrthoHeight - scrollAmount); camera.OrthoHeight = orthoHeight; } } } UpdateAnim(); }
/// <summary> /// Orients the camera so it looks along the provided axis. /// </summary> public void LookAlong(Vector3 axis) { Vector3 up = Vector3.YAxis; if (MathEx.Abs(Vector3.Dot(axis, up)) > 0.9f) up = Vector3.ZAxis; CameraState state = new CameraState(); state.Position = camera.SceneObject.Position; state.Rotation = Quaternion.LookRotation(axis, up); state.Ortographic = camera.ProjectionType == ProjectionType.Orthographic; state.FrustumWidth = frustumWidth; SetState(state); }
/// <summary> /// Recreates all the GUI elements used by this inspector. /// </summary> private void BuildGUI() { CharacterController controller = InspectedObject as CharacterController; if (controller == null) return; radiusField.OnChanged += x => { controller.Radius = x; MarkAsModified(); }; radiusField.OnConfirmed += ConfirmModify; radiusField.OnFocusLost += ConfirmModify; heightField.OnChanged += x => { controller.Height = x; MarkAsModified(); }; heightField.OnConfirmed += ConfirmModify; heightField.OnFocusLost += ConfirmModify; orientationField.OnChanged += x => { orientation = x; Quaternion rotation = Quaternion.FromEuler(x); controller.Up = rotation.Rotate(Vector3.YAxis); MarkAsModified(); }; orientationField.OnConfirmed += ConfirmModify; orientationField.OnFocusLost += ConfirmModify; contactOffsetField.OnChanged += x => { controller.ContactOffset = x; MarkAsModified(); }; contactOffsetField.OnConfirmed += ConfirmModify; contactOffsetField.OnFocusLost += ConfirmModify; minMoveDistanceField.OnChanged += x => { controller.MinMoveDistance = x; MarkAsModified(); }; minMoveDistanceField.OnConfirmed += ConfirmModify; minMoveDistanceField.OnFocusLost += ConfirmModify; climbingModeField.OnSelectionChanged += x => { controller.ClimbingMode = (CharacterClimbingMode)x; MarkAsModified(); ConfirmModify(); }; stepOffsetField.OnChanged += x => { controller.StepOffset = x; MarkAsModified(); }; stepOffsetField.OnConfirmed += ConfirmModify; stepOffsetField.OnFocusLost += ConfirmModify; nonWalkableModeField.OnSelectionChanged += x => { controller.NonWalkableMode = (CharacterNonWalkableMode)x; MarkAsModified(); ConfirmModify(); }; slopeLimitField.OnChanged += x => { controller.SlopeLimit = new Degree(x); MarkAsModified(); }; slopeLimitField.OnFocusLost += ConfirmModify; layerField.OnSelectionChanged += x => { ulong layer = 0; bool[] states = layerField.States; for (int i = 0; i < states.Length; i++) layer |= states[i] ? Layers.Values[i] : 0; layersValue = layer; controller.Layer = layer; MarkAsModified(); ConfirmModify(); }; Layout.AddElement(radiusField); Layout.AddElement(heightField); Layout.AddElement(orientationField); Layout.AddElement(contactOffsetField); Layout.AddElement(minMoveDistanceField); Layout.AddElement(climbingModeField); Layout.AddElement(stepOffsetField); Layout.AddElement(nonWalkableModeField); Layout.AddElement(slopeLimitField); Layout.AddElement(layerField); orientation = Quaternion.FromToRotation(Vector3.YAxis, controller.Up).ToEuler(); }
/// <inheritdoc/> protected internal override void PostInput() { delta = Vector3.Zero; if (Handles.MoveHandleSnapActive) { delta += Handles.SnapValue(xAxis.Delta, Handles.MoveSnapAmount) * GetXDir(); delta += Handles.SnapValue(yAxis.Delta, Handles.MoveSnapAmount) * GetYDir(); delta += Handles.SnapValue(zAxis.Delta, Handles.MoveSnapAmount) * GetZDir(); delta += Handles.SnapValue(xyPlane.Delta.x, Handles.MoveSnapAmount) * GetXDir(); delta += Handles.SnapValue(xyPlane.Delta.y, Handles.MoveSnapAmount) * GetYDir(); delta += Handles.SnapValue(yzPlane.Delta.x, Handles.MoveSnapAmount) * GetYDir(); delta += Handles.SnapValue(yzPlane.Delta.y, Handles.MoveSnapAmount) * GetZDir(); delta += Handles.SnapValue(zxPlane.Delta.x, Handles.MoveSnapAmount) * GetZDir(); delta += Handles.SnapValue(zxPlane.Delta.y, Handles.MoveSnapAmount) * GetXDir(); } else { delta += xAxis.Delta * GetXDir(); delta += yAxis.Delta * GetYDir(); delta += zAxis.Delta * GetZDir(); delta += xyPlane.Delta.x * GetXDir(); delta += xyPlane.Delta.y * GetYDir(); delta += yzPlane.Delta.x * GetYDir(); delta += yzPlane.Delta.y * GetZDir(); delta += zxPlane.Delta.x * GetZDir(); delta += zxPlane.Delta.y * GetXDir(); } }
/// <summary> /// Creates a new line segment. /// </summary> /// <param name="start">Line segment start position.</param> /// <param name="end">Line segment end position.</param> public LineSegment(Vector3 start, Vector3 end) { this.start = start; this.end = end; }
/// <inheritdoc/> protected internal override void PostInput() { delta = Vector3.Zero; delta += xAxis.Delta * GetXDir() * 0.1f; delta += yAxis.Delta * GetYDir() * 0.1f; delta += zAxis.Delta * GetZDir() * 0.1f; delta += (freeAxis.Delta.x + freeAxis.Delta.y) * Vector3.One * 0.1f; }
/// <inheritdoc/> protected internal override void Draw() { HandleDrawing.Layer = 1; HandleDrawing.Transform = Matrix4.TRS(Position, Rotation, Vector3.One); float handleSize = Handles.GetHandleSize(EditorApplication.SceneViewCamera, position); // Draw 1D sliders Vector3 smallCubeExtents = new Vector3(SMALL_CUBE_SIZE*0.5f, SMALL_CUBE_SIZE*0.5f, SMALL_CUBE_SIZE*0.5f); if (xAxis.State == HandleSlider.StateType.Active) HandleDrawing.Color = Color.White; else if (xAxis.State == HandleSlider.StateType.Hover) HandleDrawing.Color = Color.BansheeOrange; else HandleDrawing.Color = Color.Red; Vector3 xCubeOffset = Vector3.XAxis * SMALL_CUBE_SIZE * 0.5f; Vector3 xCubeStart = Vector3.XAxis - xCubeOffset; HandleDrawing.DrawLine(Vector3.Zero, xCubeStart, handleSize); HandleDrawing.DrawCube(xCubeStart + xCubeOffset, smallCubeExtents, handleSize); if (yAxis.State == HandleSlider.StateType.Active) HandleDrawing.Color = Color.White; else if (yAxis.State == HandleSlider.StateType.Hover) HandleDrawing.Color = Color.BansheeOrange; else HandleDrawing.Color = Color.Green; Vector3 yCubeOffset = Vector3.YAxis * SMALL_CUBE_SIZE * 0.5f; Vector3 yCubeStart = Vector3.YAxis - yCubeOffset; HandleDrawing.DrawLine(Vector3.Zero, yCubeStart, handleSize); HandleDrawing.DrawCube(yCubeStart + yCubeOffset, smallCubeExtents, handleSize); if (zAxis.State == HandleSlider.StateType.Active) HandleDrawing.Color = Color.White; else if (zAxis.State == HandleSlider.StateType.Hover) HandleDrawing.Color = Color.BansheeOrange; else HandleDrawing.Color = Color.Blue; Vector3 zCubeOffset = Vector3.ZAxis * SMALL_CUBE_SIZE * 0.5f; Vector3 zCubeStart = Vector3.ZAxis - zCubeOffset; HandleDrawing.DrawLine(Vector3.Zero, zCubeStart, handleSize); HandleDrawing.DrawCube(zCubeStart + zCubeOffset, smallCubeExtents, handleSize); // Draw free scale handle if (freeAxis.State == HandleSlider.StateType.Active) HandleDrawing.Color = Color.White; else if (freeAxis.State == HandleSlider.StateType.Hover) HandleDrawing.Color = Color.BansheeOrange; else HandleDrawing.Color = Color.White; //// Rotate it so it always faces the camera, and move it forward a bit to always render in front Vector3 bottomLeft = -Vector3.XAxis * 0.2f - Vector3.YAxis * 0.2f; Vector3 topLeft = -Vector3.XAxis * 0.2f + Vector3.YAxis * 0.2f; Vector3 topRight = Vector3.XAxis * 0.2f + Vector3.YAxis * 0.2f; Vector3 bottomRight = Vector3.XAxis * 0.2f - Vector3.YAxis * 0.2f; Vector3 offset = Vector3.ZAxis*0.1f; Quaternion cameraRot = EditorApplication.SceneViewCamera.SceneObject.Rotation; bottomLeft = cameraRot.Rotate(bottomLeft + offset); topLeft = cameraRot.Rotate(topLeft + offset); topRight = cameraRot.Rotate(topRight + offset); bottomRight = cameraRot.Rotate(bottomRight + offset); HandleDrawing.DrawLine(bottomLeft, bottomRight, handleSize); HandleDrawing.DrawLine(bottomLeft, topLeft, handleSize); HandleDrawing.DrawLine(topLeft, topRight, handleSize); HandleDrawing.DrawLine(bottomRight, topRight, handleSize); }
/// <summary> /// Triggered when the user changes the field value. /// </summary> /// <param name="newValue">New value of the 3D vector field.</param> private void OnFieldValueChanged(Vector3 newValue) { property.SetValue(newValue); state |= InspectableState.ModifyInProgress; }
/// <inheritdoc/> protected internal override void PostInput() { if (activeHandle != null) { if (activeHandle.IsDragged()) { if (!isDragged) { isDragged = true; SceneObject[] selectedSceneObjects = Selection.SceneObjects; activeSelection = new HandledObject[selectedSceneObjects.Length]; for (int i = 0; i < selectedSceneObjects.Length; i++) activeSelection[i] = new HandledObject(selectedSceneObjects[i]); initialHandlePosition = activeHandle.Position; initialHandleRotation = activeHandle.Rotation; } } else { isDragged = false; activeSelection = null; } activeHandle.PostInput(); if (activeHandle.IsDragged()) { switch (activeHandleType) { case SceneViewTool.Move: MoveHandle moveHandle = (MoveHandle) activeHandle; foreach (var selectedObj in activeSelection) selectedObj.so.LocalPosition = selectedObj.initialPosition + moveHandle.Delta; break; case SceneViewTool.Rotate: { RotateHandle rotateHandle = (RotateHandle) activeHandle; // Make sure we transform relative to the handle position SceneObject temporarySO = new SceneObject("Temp"); temporarySO.Position = initialHandlePosition; temporarySO.LocalRotation = initialHandleRotation; SceneObject[] originalParents = new SceneObject[activeSelection.Length]; for (int i = 0; i < activeSelection.Length; i++) { originalParents[i] = activeSelection[i].so.Parent; activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition; activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation; activeSelection[i].so.Parent = temporarySO; } temporarySO.LocalRotation *= rotateHandle.Delta; for (int i = 0; i < activeSelection.Length; i++) activeSelection[i].so.Parent = originalParents[i]; temporarySO.Destroy(); } break; case SceneViewTool.Scale: { ScaleHandle scaleHandle = (ScaleHandle) activeHandle; // Make sure we transform relative to the handle position SceneObject temporarySO = new SceneObject("Temp"); temporarySO.Position = activeHandle.Position; SceneObject[] originalParents = new SceneObject[activeSelection.Length]; for (int i = 0; i < activeSelection.Length; i++) { originalParents[i] = activeSelection[i].so.Parent; activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition; activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation; activeSelection[i].so.LocalScale = activeSelection[i].initialScale; activeSelection[i].so.Parent = temporarySO; } temporarySO.LocalScale += scaleHandle.Delta; for (int i = 0; i < activeSelection.Length; i++) activeSelection[i].so.Parent = originalParents[i]; temporarySO.Destroy(); } break; } EditorApplication.SetSceneDirty(); } } else { isDragged = false; activeSelection = null; } }
/// <summary> /// Creates a new scene object representation by recording the current object transform. /// </summary> /// <param name="so">Scene object that is being modified by a handle.</param> public HandledObject(SceneObject so) { this.so = so; initialPosition = so.LocalPosition; initialRotation = so.LocalRotation; initialScale = so.LocalScale; }
/// <summary> /// Transforms the bounding box by the given matrix. /// /// As the resulting box will no longer be axis aligned, an axis align box is instead created by encompassing the /// transformed oriented bounding box. Retrieving the value as an actual OBB would provide a tighter fit. /// </summary> /// <param name="tfrm">Affine matrix to transform the box with.</param> public void TransformAffine(Matrix4 tfrm) { Vector3 center = Center; Vector3 halfSize = Size*0.5f; Vector3 newCenter = tfrm.MultiplyAffine(center); Vector3 newHalfSize = new Vector3( MathEx.Abs(tfrm.m00) * halfSize.x + MathEx.Abs(tfrm.m01) * halfSize.y + MathEx.Abs(tfrm.m02) * halfSize.z, MathEx.Abs(tfrm.m10) * halfSize.x + MathEx.Abs(tfrm.m11) * halfSize.y + MathEx.Abs(tfrm.m12) * halfSize.z, MathEx.Abs(tfrm.m20) * halfSize.x + MathEx.Abs(tfrm.m21) * halfSize.y + MathEx.Abs(tfrm.m22) * halfSize.z); minimum = newCenter - newHalfSize; maximum = newCenter + newHalfSize; }
/// <summary> /// Creates a new sphere object. /// </summary> /// <param name="center">Center point of the sphere.</param> /// <param name="radius">Radius of the sphere.</param> public Sphere(Vector3 center, float radius) { _center = center; _radius = radius; }
/// <summary> /// Creates a new axis aligned box. /// </summary> /// <param name="min">Corner of the box with minimum values.</param> /// <param name="max">Corner of the box with maximum values.</param> public AABox(Vector3 min, Vector3 max) { minimum = min; maximum = max; }
/// <summary> /// Converts a point on the circle to an angle on the circle. /// </summary> /// <param name="up">Up vector determining the orientation of the circle.</param> /// <param name="point">Point along a unit circle centered around the origin.</param> /// <returns>Angle at which the provided point is located on the circle.</returns> private Degree PointOnCircleToAngle(Vector3 up, Vector3 point) { Quaternion rot = Quaternion.FromToRotation(up, Vector3.YAxis); Matrix4 worldToPlane = Matrix4.TRS(Vector3.Zero, rot, Vector3.One); point = worldToPlane.MultiplyDirection(point); return (MathEx.Atan2(-point.z, -point.x) + MathEx.Pi); }