| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- using bs;
- namespace bs.Editor
- {
- /** @addtogroup Handles
- * @{
- */
- /// <summary>
- /// Handle that allows an object to be rotated around the three primary axes, as well as a free axis currently
- /// facing the camera.
- /// </summary>
- public sealed class RotateHandle : DefaultHandle
- {
- private Quaternion delta;
- private HandleSliderDisc xAxis;
- private HandleSliderDisc yAxis;
- private HandleSliderDisc zAxis;
- private HandleSliderDisc freeAxis;
- private bool isDragged;
- private Quaternion dragStartRotation;
- /// <summary>
- /// Amount of rotation applied since the last frame. Only valid while the handle is being dragged.
- /// </summary>
- public Quaternion Delta
- {
- get { return delta; }
- }
- /// <inheritdoc/>
- internal override bool IsDragged()
- {
- return xAxis.State == HandleSlider.StateType.Active ||
- yAxis.State == HandleSlider.StateType.Active ||
- zAxis.State == HandleSlider.StateType.Active ||
- freeAxis.State == HandleSlider.StateType.Active;
- }
- /// <summary>
- /// Creates a new rotation handle.
- /// </summary>
- public RotateHandle()
- {
- xAxis = new HandleSliderDisc(this, Vector3.XAxis, 1.0f);
- yAxis = new HandleSliderDisc(this, Vector3.YAxis, 1.0f);
- zAxis = new HandleSliderDisc(this, Vector3.ZAxis, 1.0f);
- freeAxis = new HandleSliderDisc(this, -Vector3.ZAxis, 1.2f);
- }
- /// <inheritdoc/>
- protected internal override void PreInput()
- {
- xAxis.Position = position;
- yAxis.Position = position;
- zAxis.Position = position;
- freeAxis.Position = position;
- Quaternion handleRotation = isDragged ? dragStartRotation : Rotation;
- xAxis.Rotation = handleRotation;
- yAxis.Rotation = handleRotation;
- zAxis.Rotation = handleRotation;
- freeAxis.Rotation = EditorApplication.SceneViewCamera.SceneObject.Rotation;
- xAxis.SetCutoffPlane(GetXStartAngle(isDragged), true);
- yAxis.SetCutoffPlane(GetYStartAngle(isDragged), true);
- zAxis.SetCutoffPlane(GetZStartAngle(isDragged), true);
- }
- /// <inheritdoc/>
- protected internal override void PostInput()
- {
- if (IsDragged())
- {
- if (!isDragged)
- {
- isDragged = true;
- dragStartRotation = Rotation;
- }
- }
- else
- {
- isDragged = false;
- dragStartRotation = Quaternion.Identity;
- }
- Degree xValue = (Degree)0.0f;
- Degree yValue = (Degree)0.0f;
- Degree zValue = (Degree)0.0f;
- Degree freeAxisValue = (Degree)0.0f;
- if (Handles.RotateHandleSnapActive)
- {
- xValue = Handles.SnapValue(xAxis.Delta, Handles.RotateSnapAmount);
- yValue = Handles.SnapValue(yAxis.Delta, Handles.RotateSnapAmount);
- zValue = Handles.SnapValue(zAxis.Delta, Handles.RotateSnapAmount);
- freeAxisValue = Handles.SnapValue(freeAxis.Delta, Handles.RotateSnapAmount);
- }
- else
- {
- xValue = xAxis.Delta;
- yValue = yAxis.Delta;
- zValue = zAxis.Delta;
- freeAxisValue = freeAxis.Delta;
- }
- Vector3 cameraForward = -(dragStartRotation.Inverse * EditorApplication.SceneViewCamera.SceneObject.Rotation).Forward;
- delta = Quaternion.FromEuler(xValue, yValue, zValue);
- delta *= Quaternion.FromAxisAngle(cameraForward, freeAxisValue);
- }
- /// <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 arcs
- 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;
- HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.XAxis, 1.0f, GetXStartAngle(false), new Degree(180.0f), 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;
- HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.YAxis, 1.0f, GetYStartAngle(false), new Degree(180.0f), 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;
- HandleDrawing.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 1.0f, GetZStartAngle(false), new Degree(180.0f), handleSize);
- // Draw "bounds" and free handle
- Color gray = new Color(1.0f, 1.0f, 1.0f, 0.3f);
- Vector3 cameraNormal = EditorApplication.SceneViewCamera.SceneObject.Rotation.Rotate(Vector3.ZAxis);
- HandleDrawing.Transform = Matrix4.TRS(Position, Quaternion.Identity, Vector3.One);
- HandleDrawing.Color = gray;
- HandleDrawing.DrawWireDisc(cameraNormal * 0.1f, cameraNormal, 1.0f, handleSize);
- if (freeAxis.State == HandleSlider.StateType.Active)
- HandleDrawing.Color = Color.White;
- else if (freeAxis.State == HandleSlider.StateType.Hover)
- HandleDrawing.Color = Color.BansheeOrange;
- else
- HandleDrawing.Color = gray;
- HandleDrawing.DrawWireDisc(Vector3.Zero, cameraNormal, 1.2f, handleSize);
- // Draw active rotation pie
- HandleDrawing.Color = gray;
- HandleDrawing.Transform = Matrix4.TRS(Position, EditorApplication.SceneViewCamera.SceneObject.Rotation, Vector3.One);
- if (freeAxis.State == HandleSlider.StateType.Active)
- HandleDrawing.DrawArc(Vector3.Zero, -Vector3.ZAxis, 1.2f, freeAxis.StartAngle, -freeAxis.Delta, handleSize);
- HandleDrawing.Transform = Matrix4.TRS(Position, dragStartRotation, Vector3.One);
- if (xAxis.State == HandleSlider.StateType.Active)
- HandleDrawing.DrawArc(Vector3.Zero, Vector3.XAxis, 1.0f, xAxis.StartAngle, -xAxis.Delta, handleSize);
- else if (yAxis.State == HandleSlider.StateType.Active)
- HandleDrawing.DrawArc(Vector3.Zero, Vector3.YAxis, 1.0f, yAxis.StartAngle, -yAxis.Delta, handleSize);
- else if (zAxis.State == HandleSlider.StateType.Active)
- HandleDrawing.DrawArc(Vector3.Zero, Vector3.ZAxis, 1.0f, zAxis.StartAngle, -zAxis.Delta, handleSize);
- }
- /// <summary>
- /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which
- /// the arc starts for the X axis.
- /// </summary>
- /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
- /// to the value when handle drag started. This is useful because we do not want the visible
- /// arc to change while the user is in the process of rotating the handle.</param>
- /// <returns>Angle at which to display the visible arc for the X axis rotations.</returns>
- private Degree GetXStartAngle(bool frozen)
- {
- Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
- Vector3 xStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.XAxis);
- return PointOnCircleToAngle(Vector3.XAxis, xStartDir);
- }
- /// <summary>
- /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which
- /// the arc starts for the Y axis.
- /// </summary>
- /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
- /// to the value when handle drag started. This is useful because we do not want the visible
- /// arc to change while the user is in the process of rotating the handle.</param>
- /// <returns>Angle at which to display the visible arc for the Y axis rotations.</returns>
- private Degree GetYStartAngle(bool frozen)
- {
- Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
- Vector3 yStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.YAxis);
- return PointOnCircleToAngle(Vector3.YAxis, yStartDir);
- }
- /// <summary>
- /// The rotate handle only displays the 180 degree arc facing the camera and this method returns the angle at which
- /// the arc starts for the Z axis.
- /// </summary>
- /// <param name="frozen">Determines should the local handle rotation be taken into account, or should it be frozen
- /// to the value when handle drag started. This is useful because we do not want the visible
- /// arc to change while the user is in the process of rotating the handle.</param>
- /// <returns>Angle at which to display the visible arc for the Z axis rotations.</returns>
- private Degree GetZStartAngle(bool frozen)
- {
- Quaternion handleRotation = frozen ? dragStartRotation : Rotation;
- Vector3 zStartDir = Vector3.Cross(handleRotation.Inverse.Rotate(EditorApplication.SceneViewCamera.SceneObject.Forward), Vector3.ZAxis);
- return PointOnCircleToAngle(Vector3.ZAxis, zStartDir);
- }
- /// <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);
- }
- }
- /** @} */
- }
|