using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
/// <summary>
/// Collection of static methods to draw gizmos for volume colliders.
/// </summary>
public static class VolumeGizmoDrawer
{
/// <summary>
/// Draws a box collider gizmo.
/// </summary>
/// <param name="transform">Transform of the box collider.</param>
/// <param name="center">Center position of the box collider.</param>
/// <param name="size">Size of the box collider.</param>
public static void DrawBoxCollider(Transform transform, Vector3 center, Vector3 size)
{
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale);
if (VolumesPreferences.drawWireFrame)
Gizmos.DrawWireCube(center, size);
if (VolumesPreferences.drawSolid)
Gizmos.DrawCube(center, size);
}
/// <summary>
/// Draws a sphere collider gizmo.
/// </summary>
/// <param name="transform">Transform of the sphere collider.</param>
/// <param name="center">Center position of the sphere collider.</param>
/// <param name="radius">Radius of the sphere collider.</param>
public static void DrawSphereCollider(Transform transform, Vector3 center, float radius)
{
// For sphere the only scale that is used is the transform.x
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one * transform.lossyScale.x);
if (VolumesPreferences.drawWireFrame)
Gizmos.DrawWireSphere(center, radius);
if (VolumesPreferences.drawSolid)
Gizmos.DrawSphere(center, radius);
}
/// <summary>
/// Draws a mesh collider gizmo.
/// </summary>
/// <param name="transform">Transform of the mesh collider.</param>
/// <param name="mesh">Mesh to draw.</param>
public static void DrawMeshCollider(Transform transform, Mesh mesh)
{
// We'll just use scaling as an approximation for volume skin. It's far from being
// correct (and is completely wrong in some cases). Ultimately we'd use a distance
// field or at least a tessellate + push modifier on the collider's mesh to get a
// better approximation, but the current Gizmo system is a bit limited and because
// everything is dynamic in Unity and can be changed at anytime, it's hard to keep
// track of changes in an elegant way (which we'd need to implement a nice cache
// system for generated volume meshes).
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale);
if (VolumesPreferences.drawWireFrame)
Gizmos.DrawWireMesh(mesh);
if (VolumesPreferences.drawSolid)
Gizmos.DrawMesh(mesh); // Mesh pivot should be centered or this won't work
}
#if ENABLE_PHYSICS_MODULE
[DrawGizmo(GizmoType.Active | GizmoType.Selected | GizmoType.NonSelected)]
static void OnDrawGizmos(Volume volume, GizmoType gizmoType)
{
if (!volume.enabled || volume.isGlobal || volume.colliders == null)
return;
var gizmoColor = VolumesPreferences.volumeGizmoColor;
var gizmoColorWhenBlendRegionEnabled = new Color(gizmoColor.r, gizmoColor.g, gizmoColor.b, 0.5f * gizmoColor.a);
foreach (var collider in volume.colliders)
{
if (!collider || !collider.enabled)
continue;
// Reduce gizmo opacity when blend region is enabled because there are two of them
bool blendDistanceEnabled = volume.blendDistance > 0f;
Gizmos.color = blendDistanceEnabled && VolumesPreferences.drawSolid ? gizmoColorWhenBlendRegionEnabled : gizmoColor;
switch (collider)
{
case BoxCollider c:
DrawBoxCollider(c.transform, c.center, c.size);
if (blendDistanceEnabled)
DrawBlendDistanceBox(c, volume.blendDistance);
break;
case SphereCollider c:
DrawSphereCollider(c.transform, c.center, c.radius);
if (blendDistanceEnabled)
DrawBlendDistanceSphere(c, volume.blendDistance);
break;
case MeshCollider c:
DrawMeshCollider(c.transform, c.sharedMesh);
break;
}
}
}
static void DrawBlendDistanceBox(BoxCollider c, float blendDistance)
{
var twiceFadeRadius = blendDistance * 2;
var transformScale = c.transform.localScale;
// Divide by scale because blendDistance is absolute units and we don't want transform scale to affect it
Vector3 size = c.size + new Vector3(
twiceFadeRadius / transformScale.x,
twiceFadeRadius / transformScale.y,
twiceFadeRadius / transformScale.z
);
if (VolumesPreferences.drawWireFrame)
Gizmos.DrawWireCube(c.center, size);
if (VolumesPreferences.drawSolid)
Gizmos.DrawCube(c.center, size);
}
static void DrawBlendDistanceSphere(SphereCollider c, float blendDistance)
{
// Divide by scale because blendDistance is absolute units and we don't want transform scale to affect it
var blendSphereSize = c.radius + blendDistance / c.transform.lossyScale.x;
if (VolumesPreferences.drawWireFrame)
Gizmos.DrawWireSphere(c.center, blendSphereSize);
if (VolumesPreferences.drawSolid)
Gizmos.DrawSphere(c.center, blendSphereSize);
}
#endif
}
}