您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
175 行
7.4 KiB
175 行
7.4 KiB
using UnityEngine;
|
|
|
|
namespace UnityEditor.Rendering
|
|
{
|
|
/// <summary>
|
|
/// Provide a gizmo/handle representing a box where all face can be moved independently.
|
|
/// Also add a contained sub gizmo/handle box if contained is used at creation.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// class MyComponentEditor : Editor
|
|
/// {
|
|
/// static HierarchicalSphere sphere;
|
|
/// static HierarchicalSphere containedSphere;
|
|
///
|
|
/// static MyComponentEditor()
|
|
/// {
|
|
/// Color[] handleColors = new Color[]
|
|
/// {
|
|
/// Color.red,
|
|
/// Color.green,
|
|
/// Color.Blue,
|
|
/// new Color(0.5f, 0f, 0f, 1f),
|
|
/// new Color(0f, 0.5f, 0f, 1f),
|
|
/// new Color(0f, 0f, 0.5f, 1f)
|
|
/// };
|
|
/// sphere = new HierarchicalSphere(new Color(1f, 1f, 1f, 0.25));
|
|
/// containedSphere = new HierarchicalSphere(new Color(1f, 0f, 1f, 0.25), container: sphere);
|
|
/// }
|
|
///
|
|
/// [DrawGizmo(GizmoType.Selected|GizmoType.Active)]
|
|
/// void DrawGizmo(MyComponent comp, GizmoType gizmoType)
|
|
/// {
|
|
/// sphere.center = comp.transform.position;
|
|
/// sphere.size = comp.transform.scale;
|
|
/// sphere.DrawHull(gizmoType == GizmoType.Selected);
|
|
///
|
|
/// containedSphere.center = comp.innerposition;
|
|
/// containedSphere.size = comp.innerScale;
|
|
/// containedSphere.DrawHull(gizmoType == GizmoType.Selected);
|
|
/// }
|
|
///
|
|
/// void OnSceneGUI()
|
|
/// {
|
|
/// EditorGUI.BeginChangeCheck();
|
|
///
|
|
/// //container sphere must be also set for contained sphere for clamping
|
|
/// sphere.center = comp.transform.position;
|
|
/// sphere.size = comp.transform.scale;
|
|
/// sphere.DrawHandle();
|
|
///
|
|
/// containedSphere.center = comp.innerposition;
|
|
/// containedSphere.size = comp.innerScale;
|
|
/// containedSphere.DrawHandle();
|
|
///
|
|
/// if(EditorGUI.EndChangeCheck())
|
|
/// {
|
|
/// comp.innerposition = containedSphere.center;
|
|
/// comp.innersize = containedSphere.size;
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public class HierarchicalSphere
|
|
{
|
|
const float k_HandleSizeCoef = 0.05f;
|
|
|
|
static Material k_Material_Cache;
|
|
static Material k_Material => (k_Material_Cache == null || k_Material_Cache.Equals(null) ? (k_Material_Cache = new Material(Shader.Find("Hidden/UnlitTransparentColored"))) : k_Material_Cache);
|
|
static Mesh k_MeshSphere_Cache;
|
|
static Mesh k_MeshSphere => k_MeshSphere_Cache == null || k_MeshSphere_Cache.Equals(null) ? (k_MeshSphere_Cache = Resources.GetBuiltinResource<Mesh>("New-Sphere.fbx")) : k_MeshSphere_Cache;
|
|
|
|
Material m_Material;
|
|
readonly HierarchicalSphere m_Parent;
|
|
Color m_HandleColor;
|
|
Color m_WireframeColor;
|
|
Color m_WireframeColorBehind;
|
|
|
|
Material material => m_Material == null || m_Material.Equals(null)
|
|
? (m_Material = new Material(k_Material))
|
|
: m_Material;
|
|
|
|
/// <summary>The position of the center of the box in Handle.matrix space.</summary>
|
|
public Vector3 center { get; set; }
|
|
|
|
/// <summary>The size of the box in Handle.matrix space.</summary>
|
|
public float radius { get; set; }
|
|
|
|
/// <summary>The baseColor used to fill hull. All other colors are deduced from it.</summary>
|
|
public Color baseColor
|
|
{
|
|
get { return material.color; }
|
|
set
|
|
{
|
|
value.a = 8f / 255;
|
|
material.color = value;
|
|
value.a = 1f;
|
|
m_HandleColor = value;
|
|
value.a = 0.7f;
|
|
m_WireframeColor = value;
|
|
value.a = 0.2f;
|
|
m_WireframeColorBehind = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>Constructor. Used to setup colors and also the container if any.</summary>
|
|
/// <param name="baseColor">The color of filling. All other colors are deduced from it.</param>
|
|
/// <param name="parent">The HierarchicalSphere containing this sphere. If null, the sphere will not be limited in size.</param>
|
|
public HierarchicalSphere(Color baseColor, HierarchicalSphere parent = null)
|
|
{
|
|
m_Parent = parent;
|
|
m_Material = new Material(k_Material);
|
|
this.baseColor = baseColor;
|
|
}
|
|
|
|
/// <summary>Draw the hull which means the boxes without the handles</summary>
|
|
public void DrawHull(bool filled)
|
|
{
|
|
Color wireframeColor = m_HandleColor;
|
|
wireframeColor.a = 0.8f;
|
|
using (new Handles.DrawingScope(m_WireframeColor, Matrix4x4.TRS((Vector3)Handles.matrix.GetColumn(3) + center, Quaternion.identity, Vector3.one)))
|
|
{
|
|
if (filled)
|
|
{
|
|
material.SetPass(0);
|
|
Matrix4x4 drawMatrix = Matrix4x4.TRS((Vector3)Handles.matrix.GetColumn(3), Quaternion.identity, Vector3.one * radius * 2f);
|
|
Graphics.DrawMeshNow(k_MeshSphere, drawMatrix);
|
|
}
|
|
|
|
var drawCenter = Vector3.zero;
|
|
var viewPlaneNormal = Vector3.zero;
|
|
var drawnRadius = radius;
|
|
if (Camera.current.orthographic)
|
|
viewPlaneNormal = Camera.current.transform.forward;
|
|
else
|
|
{
|
|
viewPlaneNormal = (Vector3)Handles.matrix.GetColumn(3) - Camera.current.transform.position;
|
|
var sqrDist = viewPlaneNormal.sqrMagnitude; // squared distance from camera to center
|
|
var sqrRadius = radius * radius; // squared radius
|
|
var sqrOffset = sqrRadius * sqrRadius / sqrDist; // squared distance from actual center to drawn disc center
|
|
var insideAmount = sqrOffset / sqrRadius;
|
|
|
|
// If we are not inside the sphere, calculate where to draw the periphery
|
|
if (insideAmount < 1)
|
|
{
|
|
drawnRadius = Mathf.Sqrt(sqrRadius - sqrOffset); // the radius of the drawn disc
|
|
drawCenter -= (sqrRadius / sqrDist) * viewPlaneNormal;
|
|
}
|
|
}
|
|
|
|
Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
|
|
Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius);
|
|
Handles.DrawWireDisc(drawCenter, viewPlaneNormal, drawnRadius);
|
|
|
|
Handles.color = m_WireframeColorBehind;
|
|
Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
|
|
Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius);
|
|
Handles.DrawWireDisc(drawCenter, viewPlaneNormal, drawnRadius);
|
|
Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
|
|
}
|
|
}
|
|
|
|
/// <summary>Draw the manipulable handles</summary>
|
|
public void DrawHandle()
|
|
{
|
|
using (new Handles.DrawingScope(m_HandleColor))
|
|
{
|
|
radius = Handles.RadiusHandle(Quaternion.identity, center, radius, handlesOnly: true);
|
|
if(m_Parent != null)
|
|
radius = Mathf.Min(radius, m_Parent.radius - Vector3.Distance(center, m_Parent.center));
|
|
}
|
|
}
|
|
}
|
|
}
|