Files
Fishing2/Assets/Procedural Worlds/GeNa/Scripts/Editor/Unity/CylinderBoundsHandle.cs
2026-02-28 12:43:44 +08:00

250 lines
9.7 KiB
C#

using System;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace GeNa.Core
{
/// <summary>
/// <para>A compound handle to edit a capsule-shaped bounding volume in the Scene view.</para>
/// </summary>
public class CylinderBoundsHandle : PrimitiveBoundsHandle
{
#region Definitons
/// <summary>
/// <para>An enumeration for specifying which axis on a CapsuleBoundsHandle object maps to the CapsuleBoundsHandle.height parameter.</para>
/// </summary>
public enum HeightAxis
{
/// <summary>
/// <para>X-axis.</para>
/// </summary>
X,
/// <summary>
/// <para>Y-axis.</para>
/// </summary>
Y,
/// <summary>
/// <para>Z-axis.</para>
/// </summary>
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
/// <summary>
/// <para>Returns or specifies the axis in the handle's space to which height maps. The radius maps to the remaining axes.</para>
/// </summary>
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);
}
}
/// <summary>
/// <para>Returns or specifies the height of the capsule bounding volume.</para>
/// </summary>
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);
}
}
/// <summary>
/// <para>Returns or specifies the radius of the capsule bounding volume.</para>
/// </summary>
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
/// <summary>
/// <para>Create a new instance of the CapsuleBoundsHandle class.</para>
/// </summary>
/// <param name="controlIDHint">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.</param>
[Obsolete("Use parameterless constructor instead.")]
public CylinderBoundsHandle(int controlIDHint) : base(controlIDHint)
{
}
/// <summary>
/// <para>Create a new instance of the CapsuleBoundsHandle class.</para>
/// </summary>
public CylinderBoundsHandle()
{
}
#endregion
#region Methods
/// <summary>
/// <para>Draw a wireframe capsule for this instance.</para>
/// </summary>
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
}
}