//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// using System; using bs; namespace bs.Editor { /** @addtogroup Scene-Editor * @{ */ /// /// Draws axes that display the orientation of the scene camera. Also allows you to change camera orientation along /// one of the axes, or change projection modes. /// [CustomHandle(null)] internal class SceneAxesHandle : Handle { public const UInt64 LAYER = 0x7000000000000000; private const float CONE_HEIGHT = 0.25f; private const float CONE_RADIUS = 0.175f; private const float BOX_EXTENT = 0.2f; private const float DISABLE_THRESHOLD = 0.9f; private HandleSliderLine xAxis; private HandleSliderLine yAxis; private HandleSliderLine zAxis; private HandleSliderLine xNegAxis; private HandleSliderLine yNegAxis; private HandleSliderLine zNegAxis; private HandleSliderPlane projTypePlane; private bool[] clickStates = new bool[7]; private Vector3 position = Vector3.Zero; private Quaternion rotation = Quaternion.Identity; /// /// Creates a new scene axes handle. /// public SceneAxesHandle() { xAxis = new HandleSliderLine(this, Vector3.XAxis, 1.0f - BOX_EXTENT, false, LAYER); yAxis = new HandleSliderLine(this, Vector3.YAxis, 1.0f - BOX_EXTENT, false, LAYER); zAxis = new HandleSliderLine(this, Vector3.ZAxis, 1.0f - BOX_EXTENT, false, LAYER); xNegAxis = new HandleSliderLine(this, -Vector3.XAxis, 1.0f - BOX_EXTENT, false, LAYER); yNegAxis = new HandleSliderLine(this, -Vector3.YAxis, 1.0f - BOX_EXTENT, false, LAYER); zNegAxis = new HandleSliderLine(this, -Vector3.ZAxis, 1.0f - BOX_EXTENT, false, LAYER); projTypePlane = new HandleSliderPlane(this, Vector3.XAxis, Vector3.YAxis, BOX_EXTENT * 2.0f, false, LAYER); } /// protected internal override void PreInput() { Camera cam = EditorApplication.SceneViewCamera; if (cam == null) return; position = new Vector3(0, 0, -5.0f); rotation = cam.SceneObject.Rotation.Inverse; Vector3 xOffset = rotation.Rotate(new Vector3(BOX_EXTENT, 0.0f, 0.0f)); Vector3 yOffset = rotation.Rotate(new Vector3(0.0f, BOX_EXTENT, 0.0f)); Vector3 zOffset = rotation.Rotate(new Vector3(0.0f, 0.0f, BOX_EXTENT)); xAxis.Position = position + xOffset; yAxis.Position = position + yOffset; zAxis.Position = position + zOffset; xAxis.Rotation = rotation; yAxis.Rotation = rotation; zAxis.Rotation = rotation; xNegAxis.Position = position - xOffset; yNegAxis.Position = position - yOffset; zNegAxis.Position = position - zOffset; xNegAxis.Rotation = rotation; yNegAxis.Rotation = rotation; zNegAxis.Rotation = rotation; Vector3 cameraForward = cam.SceneObject.Forward; xAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.XAxis)) < DISABLE_THRESHOLD; yAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.YAxis)) < DISABLE_THRESHOLD; zAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.ZAxis)) < DISABLE_THRESHOLD; xNegAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.XAxis)) < DISABLE_THRESHOLD; yNegAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.YAxis)) < DISABLE_THRESHOLD; zNegAxis.Enabled = MathEx.Abs(Vector3.Dot(cameraForward, Vector3.ZAxis)) < DISABLE_THRESHOLD; Vector3 freeAxisOffset = new Vector3(-BOX_EXTENT, -BOX_EXTENT, 0.2f); projTypePlane.Rotation = Quaternion.Identity; projTypePlane.Position = position + freeAxisOffset; } /// protected internal override void PostInput() { var axes = new [] { new Tuple(xAxis, () => RotateCameraTo(Vector3.XAxis)), new Tuple(yAxis, () => RotateCameraTo(Vector3.YAxis)), new Tuple(zAxis, () => RotateCameraTo(Vector3.ZAxis)), new Tuple(xNegAxis, () => RotateCameraTo(-Vector3.XAxis)), new Tuple(yNegAxis, () => RotateCameraTo(-Vector3.YAxis)), new Tuple(zNegAxis, () => RotateCameraTo(-Vector3.ZAxis)), new Tuple(projTypePlane, ToggleProjectionType) }; for (int i = 0; i < axes.Length; i++) { if (axes[i].Item1.State == HandleSlider.StateType.Active) { if (!clickStates[i]) { axes[i].Item2(); clickStates[i] = true; } } else { clickStates[i] = false; } } } /// protected internal override void Draw() { HandleDrawing.Layer = LAYER; HandleDrawing.Transform = Matrix4.TRS(position, rotation, Vector3.One); Vector3 cameraForward = EditorApplication.SceneViewCamera.SceneObject.Forward; // Draw 1D arrows Color xColor = Color.Red; if (xAxis.State == HandleSlider.StateType.Active) xColor = Color.White; else if (xAxis.State == HandleSlider.StateType.Hover) xColor = Color.BansheeOrange; xColor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.XAxis)), 0.8f, 1.0f); HandleDrawing.Color = xColor; Vector3 xLineStart = Vector3.XAxis* BOX_EXTENT; Vector3 xConeStart = Vector3.XAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(xLineStart, xConeStart); HandleDrawing.DrawCone(xConeStart, Vector3.XAxis, CONE_HEIGHT, CONE_RADIUS); Color yColor = Color.Green; if (yAxis.State == HandleSlider.StateType.Active) yColor = Color.White; else if (yAxis.State == HandleSlider.StateType.Hover) yColor = Color.BansheeOrange; yColor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.YAxis)), 0.8f, 1.0f); HandleDrawing.Color = yColor; Vector3 yLineStart = Vector3.YAxis * BOX_EXTENT; Vector3 yConeStart = Vector3.YAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(yLineStart, yConeStart); HandleDrawing.DrawCone(yConeStart, Vector3.YAxis, CONE_HEIGHT, CONE_RADIUS); Color zColor = Color.Blue; if (zAxis.State == HandleSlider.StateType.Active) zColor = Color.White; else if (zAxis.State == HandleSlider.StateType.Hover) zColor = Color.BansheeOrange; zColor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.ZAxis)), 0.8f, 1.0f); HandleDrawing.Color = zColor; Vector3 zLineStart = Vector3.ZAxis * BOX_EXTENT; Vector3 zConeStart = Vector3.ZAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(zLineStart, zConeStart); HandleDrawing.DrawCone(zConeStart, Vector3.ZAxis, CONE_HEIGHT, CONE_RADIUS); // Draw negative 1D arrows Color xNegColor = Color.LightGray; if (xNegAxis.State == HandleSlider.StateType.Active) xNegColor = Color.White; else if (xNegAxis.State == HandleSlider.StateType.Hover) xNegColor = Color.BansheeOrange; xNegColor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.XAxis)), 0.8f, 1.0f); HandleDrawing.Color = xNegColor; Vector3 xNegLineStart = -Vector3.XAxis * BOX_EXTENT; Vector3 xNegConeStart = -Vector3.XAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(xNegLineStart, xNegConeStart); HandleDrawing.DrawCone(xNegConeStart, -Vector3.XAxis, CONE_HEIGHT, CONE_RADIUS); Color yNegColor = Color.LightGray; if (yNegAxis.State == HandleSlider.StateType.Active) yNegColor = Color.White; else if (yNegAxis.State == HandleSlider.StateType.Hover) yNegColor = Color.BansheeOrange; yNegColor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.YAxis)), 0.8f, 1.0f); HandleDrawing.Color = yNegColor; Vector3 yNegLineStart = -Vector3.YAxis * BOX_EXTENT; Vector3 yNegConeStart = -Vector3.YAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(yNegLineStart, yNegConeStart); HandleDrawing.DrawCone(yNegConeStart, -Vector3.YAxis, CONE_HEIGHT, CONE_RADIUS); Color zNegcolor = Color.LightGray; if (zNegAxis.State == HandleSlider.StateType.Active) zNegcolor = Color.White; else if (zNegAxis.State == HandleSlider.StateType.Hover) zNegcolor = Color.BansheeOrange; zNegcolor.a = MathEx.Lerp(1.0f, 0.0f, MathEx.Abs(Vector3.Dot(cameraForward, Vector3.ZAxis)), 0.8f, 1.0f); HandleDrawing.Color = zNegcolor; Vector3 zNegLineStart = -Vector3.ZAxis * BOX_EXTENT; Vector3 zNegConeStart = -Vector3.ZAxis * (1.0f - CONE_HEIGHT); HandleDrawing.DrawLine(zNegLineStart, zNegConeStart); HandleDrawing.DrawCone(zNegConeStart, -Vector3.ZAxis, CONE_HEIGHT, CONE_RADIUS); // Draw projection type handle if (projTypePlane.State == HandleSlider.StateType.Active) HandleDrawing.Color = Color.White; else if (projTypePlane.State == HandleSlider.StateType.Hover) HandleDrawing.Color = Color.BansheeOrange; else HandleDrawing.Color = Color.White; HandleDrawing.DrawCube(Vector3.Zero, new Vector3(BOX_EXTENT, BOX_EXTENT, BOX_EXTENT)); } private void RotateCameraTo(Vector3 axis) { SceneWindow sceneWindow = EditorWindow.GetWindow(); if (sceneWindow != null) sceneWindow.LookAlong(axis); } private void ToggleProjectionType() { SceneWindow sceneWindow = EditorWindow.GetWindow(); if (sceneWindow != null) { if (sceneWindow.Camera.Camera.ProjectionType == ProjectionType.Orthographic) sceneWindow.Camera.ChangeProjectionType(ProjectionType.Perspective); else sceneWindow.Camera.ChangeProjectionType(ProjectionType.Orthographic); } } } /** @} */ }