using System; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; namespace GeNa.Core { /// /// A compound handle to edit a capsule-shaped bounding volume in the Scene view. /// public class CylinderBoundsHandle : PrimitiveBoundsHandle { #region Definitons /// /// An enumeration for specifying which axis on a CapsuleBoundsHandle object maps to the CapsuleBoundsHandle.height parameter. /// public enum HeightAxis { /// /// X-axis. /// X, /// /// Y-axis. /// Y, /// /// Z-axis. /// Z, } #endregion #region Variables protected const int k_DirectionX = 0; protected const int k_DirectionY = 1; protected const int k_DirectionZ = 2; protected static readonly Vector3[] s_HeightAxes = { Vector3.right, Vector3.up, Vector3.forward }; protected static readonly int[] s_NextAxis = new int[] { 1, 2, 0 }; protected int m_HeightAxis = 1; #endregion #region Properties /// /// Returns or specifies the axis in the handle's space to which height maps. The radius maps to the remaining axes. /// public HeightAxis heightAxis { get => (HeightAxis) m_HeightAxis; set { int index = (int) value; if (m_HeightAxis == index) return; Vector3 size = Vector3.one * radius * 2f; size[index] = GetSize()[m_HeightAxis]; m_HeightAxis = index; SetSize(size); } } /// /// Returns or specifies the height of the capsule bounding volume. /// public float height { get => !IsAxisEnabled(m_HeightAxis) ? 0.0f : Mathf.Max(GetSize()[m_HeightAxis], 2f * radius); set { value = Mathf.Max(Mathf.Abs(value), 2f * radius); if (Math.Abs((double) height - (double) value) < .001f) return; Vector3 size = GetSize(); size[m_HeightAxis] = value; SetSize(size); } } /// /// Returns or specifies the radius of the capsule bounding volume. /// public float radius { get { int radiusAxis; return GetRadiusAxis(out radiusAxis) || IsAxisEnabled(m_HeightAxis) ? 0.5f * GetSize()[radiusAxis] : 0.0f; } set { Vector3 size = GetSize(); float b = 2f * value; for (int index = 0; index < 3; ++index) size[index] = index == m_HeightAxis ? Mathf.Max(size[index], b) : b; SetSize(size); } } #endregion #region Constructors /// /// Create a new instance of the CapsuleBoundsHandle class. /// /// An integer value used to generate consistent control IDs for each control handle on this instance. Avoid using the same value for all of your CapsuleBoundsHandle instances. [Obsolete("Use parameterless constructor instead.")] public CylinderBoundsHandle(int controlIDHint) : base(controlIDHint) { } /// /// Create a new instance of the CapsuleBoundsHandle class. /// public CylinderBoundsHandle() { } #endregion #region Methods /// /// Draw a wireframe capsule for this instance. /// protected override void DrawWireframe() { CapsuleBoundsHandle.HeightAxis heightAxis1 = CapsuleBoundsHandle.HeightAxis.Y; CapsuleBoundsHandle.HeightAxis heightAxis2 = CapsuleBoundsHandle.HeightAxis.Z; switch (heightAxis) { case HeightAxis.Y: heightAxis1 = CapsuleBoundsHandle.HeightAxis.Z; heightAxis2 = CapsuleBoundsHandle.HeightAxis.X; break; case HeightAxis.Z: heightAxis1 = CapsuleBoundsHandle.HeightAxis.X; heightAxis2 = CapsuleBoundsHandle.HeightAxis.Y; break; } bool flag1 = IsAxisEnabled((int) heightAxis); bool flag2 = IsAxisEnabled((int) heightAxis1); bool flag3 = IsAxisEnabled((int) heightAxis2); Vector3 heightAx1 = s_HeightAxes[m_HeightAxis]; Vector3 heightAx2 = s_HeightAxes[s_NextAxis[m_HeightAxis]]; Vector3 heightAx3 = s_HeightAxes[s_NextAxis[s_NextAxis[m_HeightAxis]]]; float radius = this.radius; float height = this.height; Vector3 center1 = center + heightAx1 * (height * 0.5f - radius); Vector3 center2 = center - heightAx1 * (height * 0.5f - radius); if (flag1) { if (flag3) { Handles.DrawLine(center1 + heightAx3 * radius, center2 + heightAx3 * radius); Handles.DrawLine(center1 - heightAx3 * radius, center2 - heightAx3 * radius); } if (flag2) { Handles.DrawLine(center1 + heightAx2 * radius, center2 + heightAx2 * radius); Handles.DrawLine(center1 - heightAx2 * radius, center2 - heightAx2 * radius); } } if (!(flag2 & flag3)) return; Handles.DrawWireArc(center1, heightAx1, heightAx2, 360f, radius); Handles.DrawWireArc(center2, heightAx1, heightAx2, -360f, radius); } protected override Bounds OnHandleChanged( HandleDirection handle, Bounds boundsOnClick, Bounds newBounds) { int index1 = 0; switch (handle) { case HandleDirection.PositiveY: case HandleDirection.NegativeY: index1 = 1; break; case HandleDirection.PositiveZ: case HandleDirection.NegativeZ: index1 = 2; break; } Vector3 max = newBounds.max; Vector3 min = newBounds.min; if (index1 == m_HeightAxis) { int radiusAxis; GetRadiusAxis(out radiusAxis); float num = max[radiusAxis] - min[radiusAxis]; if ((double) (max[m_HeightAxis] - min[m_HeightAxis]) < (double) num) { if (handle == HandleDirection.PositiveX || handle == HandleDirection.PositiveY || handle == HandleDirection.PositiveZ) max[m_HeightAxis] = min[m_HeightAxis] + num; else min[m_HeightAxis] = max[m_HeightAxis] - num; } } else { ref Vector3 local1 = ref max; int heightAxis1 = m_HeightAxis; double num1 = (double) boundsOnClick.center[m_HeightAxis]; Vector3 vector3 = boundsOnClick.size; double num2 = 0.5 * (double) vector3[m_HeightAxis]; double num3 = num1 + num2; local1[heightAxis1] = (float) num3; ref Vector3 local2 = ref min; int heightAxis2 = m_HeightAxis; vector3 = boundsOnClick.center; double num4 = (double) vector3[m_HeightAxis]; vector3 = boundsOnClick.size; double num5 = 0.5 * (double) vector3[m_HeightAxis]; double num6 = num4 - num5; local2[heightAxis2] = (float) num6; float b = (float) (0.5 * ((double) max[index1] - (double) min[index1])); float a = (float) (0.5 * ((double) max[m_HeightAxis] - (double) min[m_HeightAxis])); for (int index2 = 0; index2 < 3; ++index2) { if (index2 != index1) { float num7 = index2 == m_HeightAxis ? Mathf.Max(a, b) : b; ref Vector3 local3 = ref min; int index3 = index2; vector3 = center; double num8 = (double) vector3[index2] - (double) num7; local3[index3] = (float) num8; ref Vector3 local4 = ref max; int index4 = index2; vector3 = center; double num9 = (double) vector3[index2] + (double) num7; local4[index4] = (float) num9; } } } return new Bounds((max + min) * 0.5f, max - min); } private bool GetRadiusAxis(out int radiusAxis) { radiusAxis = s_NextAxis[m_HeightAxis]; if (IsAxisEnabled(radiusAxis)) return IsAxisEnabled(s_NextAxis[radiusAxis]); radiusAxis = s_NextAxis[radiusAxis]; return false; } #endregion } }