422 lines
16 KiB
C#
422 lines
16 KiB
C#
// Crest Water System
|
|
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
|
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using WaveHarmonic.Crest.Internal;
|
|
|
|
namespace WaveHarmonic.Crest.Editor
|
|
{
|
|
static class Visualizers
|
|
{
|
|
#if CREST_DEBUG
|
|
static Material s_VisualizeMaterial;
|
|
static Material VisualizeMaterial => s_VisualizeMaterial != null ? s_VisualizeMaterial
|
|
: s_VisualizeMaterial = new(Shader.Find("Local/Debug/Visualize Signed Texture"));
|
|
#endif
|
|
|
|
static void DrawLine(Vector3 start, Vector3 end, Color color, float _)
|
|
{
|
|
Gizmos.color = color;
|
|
Gizmos.DrawLine(start, end);
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
|
|
static void DrawGizmos(WaterRenderer target, GizmoType type)
|
|
{
|
|
#if CREST_DEBUG
|
|
if (target._Debug._DrawLodOutline)
|
|
{
|
|
// Each LOD could have its own position due to snapping.
|
|
foreach (var simulation in target.Simulations.Cast<Lod>())
|
|
{
|
|
if (!simulation._Enabled) continue;
|
|
|
|
for (var index = 0; index < simulation.Slices; index++)
|
|
{
|
|
Gizmos.color = simulation.GizmoColor;
|
|
var rect = simulation.Cascades[index].TexelRect;
|
|
|
|
Gizmos.DrawWireCube
|
|
(
|
|
rect.center.XNZ(target.SeaLevel),
|
|
rect.size.XNZ()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Don't need proxy if in play mode
|
|
if (Application.isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Create proxy if not present already, and proxy enabled
|
|
if (target._ProxyPlane == null && target._ShowWaterProxyPlane)
|
|
{
|
|
target._ProxyPlane = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
|
Helpers.Destroy(target._ProxyPlane.GetComponent<Collider>());
|
|
target._ProxyPlane.hideFlags = HideFlags.HideAndDontSave;
|
|
target._ProxyPlane.transform.parent = target.transform;
|
|
target._ProxyPlane.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.Euler(90f, 0f, 0f));
|
|
target._ProxyPlane.transform.localScale = 1000000f * Vector3.one;
|
|
|
|
target._ProxyPlane.GetComponent<Renderer>().sharedMaterial = new(Shader.Find(WaterRenderer.k_ProxyShader));
|
|
}
|
|
|
|
// Change active state of proxy if necessary
|
|
if (target._ProxyPlane != null && target._ProxyPlane.activeSelf != target._ShowWaterProxyPlane)
|
|
{
|
|
target._ProxyPlane.SetActive(target._ShowWaterProxyPlane);
|
|
|
|
// Scene view doesnt automatically refresh which makes the option confusing, so force it
|
|
EditorWindow view = EditorWindow.GetWindow<SceneView>();
|
|
view.Repaint();
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGizmos(LodInput target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
|
|
if (target._DrawBounds)
|
|
{
|
|
var rect = target.Rect;
|
|
if (rect != Rect.zero)
|
|
{
|
|
var water = WaterRenderer.Instance;
|
|
var height = water ? water.SeaLevel : target.transform.position.y;
|
|
Gizmos.color = Color.magenta;
|
|
Gizmos.DrawWireCube
|
|
(
|
|
new(rect.center.x, height, rect.center.y),
|
|
new(rect.size.x, 0, rect.size.y)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawRendererGizmos(LodInput target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
if (target.Data is not RendererLodInputData data) return;
|
|
|
|
var renderer = data._Renderer;
|
|
|
|
if (renderer != null && renderer.TryGetComponent<MeshFilter>(out var mf))
|
|
{
|
|
var transform = renderer.transform;
|
|
Gizmos.color = target.GizmoColor;
|
|
Gizmos.DrawWireMesh(mf.sharedMesh, transform.position, transform.rotation, transform.lossyScale);
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGeometryGizmos(LodInput target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
if (target.Data is not GeometryLodInputData data) return;
|
|
|
|
var geometry = data._Geometry;
|
|
|
|
if (geometry != null)
|
|
{
|
|
var transform = target.transform;
|
|
Gizmos.color = target.GizmoColor;
|
|
Gizmos.DrawWireMesh(geometry, transform.position, transform.rotation, transform.lossyScale);
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawWatertightHullGizmos(WatertightHull target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
|
|
var transform = target.transform;
|
|
|
|
Gizmos.color = ClipLod.s_GizmoColor;
|
|
Gizmos.DrawMesh(target._Mesh, submeshIndex: 0, transform.position, transform.rotation, transform.lossyScale);
|
|
Gizmos.DrawWireMesh(target._Mesh, transform.position, transform.rotation, transform.lossyScale);
|
|
|
|
if (target._Debug._DrawBounds)
|
|
{
|
|
var rect = target.Rect;
|
|
if (rect != Rect.zero)
|
|
{
|
|
var water = WaterRenderer.Instance;
|
|
var height = water ? water.SeaLevel : target.transform.position.y;
|
|
Gizmos.color = Color.magenta;
|
|
Gizmos.DrawWireCube
|
|
(
|
|
new(rect.center.x, height, rect.center.y),
|
|
new(rect.size.x, 0, rect.size.y)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawTextureGizmos(LodInput target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
if (target.Data is not TextureLodInputData) return;
|
|
|
|
Gizmos.color = target.GizmoColor;
|
|
Gizmos.matrix = Matrix4x4.TRS
|
|
(
|
|
target.transform.position,
|
|
Quaternion.Euler(Vector3.up * target.transform.rotation.eulerAngles.y),
|
|
target.transform.lossyScale.XNZ()
|
|
);
|
|
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGizmos(ClipLodInput target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
Gizmos.color = target.GizmoColor;
|
|
|
|
if (target.Mode == LodInputMode.Primitive)
|
|
{
|
|
Gizmos.matrix = target.transform.localToWorldMatrix;
|
|
|
|
switch (target._Primitive)
|
|
{
|
|
case LodInputPrimitive.Sphere:
|
|
// Use Unity's UV sphere mesh for gizmos as Gizmos.DrawSphere is too low resolution.
|
|
// Render mesh and wire sphere at default size (0.5m radius) which is scaled by gizmo matrix.
|
|
Gizmos.DrawMesh(Helpers.SphereMesh, submeshIndex: 0, Vector3.zero, Quaternion.identity, Vector3.one);
|
|
Gizmos.DrawWireSphere(Vector3.zero, 0.5f);
|
|
break;
|
|
case LodInputPrimitive.Cube:
|
|
// Render mesh and wire box at default size which is scaled by gizmo matrix.
|
|
Gizmos.DrawCube(Vector3.zero, Vector3.one);
|
|
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
|
|
break;
|
|
case LodInputPrimitive.Quad:
|
|
// Face quad upwards.
|
|
Gizmos.matrix *= Matrix4x4.Rotate(Quaternion.AngleAxis(90, Vector3.right));
|
|
Gizmos.DrawMesh(Helpers.QuadMesh, submeshIndex: 0, Vector3.zero, Quaternion.identity, Vector3.one);
|
|
Gizmos.DrawWireMesh(Helpers.QuadMesh, submeshIndex: 0, Vector3.zero, Quaternion.identity, Vector3.one);
|
|
break;
|
|
default:
|
|
Debug.LogError("Crest: Not a valid primitive type!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
|
|
static void DrawGizmos(CollisionAreaVisualizer target, GizmoType type)
|
|
{
|
|
var water = WaterRenderer.Instance;
|
|
if (water == null) return;
|
|
target.Render(water, DrawLine);
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
|
|
static void DrawGizmos(DepthProbe target, GizmoType type)
|
|
{
|
|
#if CREST_DEBUG
|
|
if (target._Debug._ShowSimulationDataInScene)
|
|
{
|
|
VisualizeMaterial.mainTexture = target.Texture;
|
|
VisualizeMaterial.SetPass(0);
|
|
Graphics.DrawMeshNow
|
|
(
|
|
Helpers.QuadMesh,
|
|
Matrix4x4.TRS(target.Position, Quaternion.Euler(90f, 0, 0), target.Scale)
|
|
);
|
|
}
|
|
#endif
|
|
|
|
if (!type.HasFlag(GizmoType.Selected))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Lod Input gizmo.
|
|
Gizmos.matrix = Matrix4x4.TRS(target.Position, target.Rotation, target.Scale.XNZ(1f));
|
|
Gizmos.color = DepthLod.s_GizmoColor;
|
|
Gizmos.DrawWireCube(Vector3.zero, new(1f, 0f, 1f));
|
|
|
|
if (target.Type == DepthProbeMode.RealTime)
|
|
{
|
|
Gizmos.color = Color.white;
|
|
|
|
var scale = Vector3.one;
|
|
var position = Vector3.zero;
|
|
|
|
position.y = Mathf.LerpUnclamped(target._CaptureRange.x, target._CaptureRange.y, target._CaptureRange.y / scale.y);
|
|
position.y *= 0.5f;
|
|
Gizmos.DrawWireCube(position, scale.XNZ(-target._CaptureRange.x + target._CaptureRange.y));
|
|
|
|
position.y = target._CaptureRange.y + target._FillHolesCaptureHeight * 0.5f;
|
|
Gizmos.DrawWireCube(position, scale.XNZ(target._FillHolesCaptureHeight));
|
|
|
|
var size = Gizmos.matrix.lossyScale.XZ();
|
|
var offset = Vector3.one * 0.5f;
|
|
var height0 = target._CaptureRange.y;
|
|
var height1 = target._CaptureRange.x;
|
|
var height2 = target._CaptureRange.y + target._FillHolesCaptureHeight;
|
|
|
|
DrawGrid(size, offset.XNZ(-height0));
|
|
DrawGrid(size, offset.XNZ(-height1));
|
|
DrawGrid(size, offset.XNZ(-height2));
|
|
|
|
Gizmos.color = new(1f, 1f, 1f, 0.2f);
|
|
Gizmos.DrawCube(Vector3.zero.XNZ(height0), Vector3.one.XNZ());
|
|
Gizmos.DrawCube(Vector3.zero.XNZ(height1), Vector3.one.XNZ());
|
|
Gizmos.DrawCube(Vector3.zero.XNZ(height2), Vector3.one.XNZ());
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
|
|
static void DrawGizmos(ShapeWaves target, GizmoType type)
|
|
{
|
|
if (!target.Enabled) return;
|
|
|
|
if (target._DrawBounds)
|
|
{
|
|
// Render bounds.
|
|
var water = WaterRenderer.Instance;
|
|
var rect = target._Rect;
|
|
if (water != null && rect != null && target.Mode != LodInputMode.Global)
|
|
{
|
|
Gizmos.DrawWireCube(new(rect.center.x, water.SeaLevel, rect.center.y), new(rect.size.x, 0, rect.size.y));
|
|
}
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGizmos(SphereWaterInteraction target, GizmoType type)
|
|
{
|
|
Gizmos.color = DynamicWavesLod.s_GizmoColor;
|
|
Gizmos.DrawWireSphere(target.transform.position + target._VelocityOffset * target._Velocity, target._Radius);
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGizmos(WaterBody target, GizmoType type)
|
|
{
|
|
var oldColor = Gizmos.color;
|
|
Gizmos.color = new(1f, 1f, 1f, 0.5f);
|
|
var center = target.AABB.center;
|
|
var size = 2f * new Vector3(target.AABB.extents.x, 1f, target.AABB.extents.z);
|
|
Gizmos.DrawCube(center, size);
|
|
Gizmos.color = Color.white;
|
|
Gizmos.DrawWireCube(center, size);
|
|
Gizmos.color = oldColor;
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)]
|
|
static void DrawGizmos(WaterChunkRenderer target, GizmoType type)
|
|
{
|
|
if (target._DrawRenderBounds)
|
|
{
|
|
target.Rend.bounds.GizmosDraw();
|
|
}
|
|
|
|
if (!type.HasFlag(GizmoType.Selected))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (target.Rend != null)
|
|
{
|
|
target.Rend.bounds.GizmosDraw();
|
|
}
|
|
|
|
if (WaterBody.WaterBodies.Count > 0)
|
|
{
|
|
Gizmos.color = Color.green;
|
|
Gizmos.DrawWireCube
|
|
(
|
|
target._UnexpandedBoundsXZ.center.XNZ(target.transform.position.y),
|
|
target._UnexpandedBoundsXZ.size.XNZ()
|
|
);
|
|
}
|
|
}
|
|
|
|
[DrawGizmo(GizmoType.Selected)]
|
|
static void DrawGizmos(FloatingObject target, GizmoType type)
|
|
{
|
|
if (!target.TryGetComponent<Rigidbody>(out var physics)) return;
|
|
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawCube(target.transform.TransformPoint(physics.centerOfMass), Vector3.one * 0.25f);
|
|
|
|
if (target.Model != FloatingObjectModel.Probes) return;
|
|
|
|
for (var i = 0; i < target._Probes.Length; i++)
|
|
{
|
|
var point = target._Probes[i];
|
|
|
|
var transformedPoint = target.transform.TransformPoint(point._Position + new Vector3(0, physics.centerOfMass.y, 0));
|
|
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawCube(transformedPoint, Vector3.one * 0.5f);
|
|
}
|
|
}
|
|
|
|
static void DrawGrid(Vector2 size, Vector3 offset)
|
|
{
|
|
var xPoints = new Vector3[Mathf.FloorToInt(size.x / 2f) * 2];
|
|
var zPoints = new Vector3[Mathf.FloorToInt(size.y / 2f) * 2];
|
|
var xCellSize = 1f / size.x;
|
|
var zCellSize = 1f / size.y;
|
|
var xSize = size.x;
|
|
var zSize = size.y;
|
|
|
|
for (var x = 0; x < xPoints.Length; x += 2)
|
|
{
|
|
xPoints[x + 0] = new Vector3(x * xCellSize, 0, 0) - offset;
|
|
xPoints[x + 1] = new Vector3(x * xCellSize, 0, xSize * xCellSize) - offset;
|
|
}
|
|
|
|
Gizmos.DrawLineList(xPoints);
|
|
|
|
for (var z = 0; z < zPoints.Length; z += 2)
|
|
{
|
|
zPoints[z + 0] = new Vector3(0, 0, z * zCellSize) - offset;
|
|
zPoints[z + 1] = new Vector3(zSize * zCellSize, 0, z * zCellSize) - offset;
|
|
}
|
|
|
|
Gizmos.DrawLineList(zPoints);
|
|
}
|
|
}
|
|
|
|
static class BoundsHelper
|
|
{
|
|
internal static void GizmosDraw(this Bounds b)
|
|
{
|
|
var xmin = b.min.x;
|
|
var ymin = b.min.y;
|
|
var zmin = b.min.z;
|
|
var xmax = b.max.x;
|
|
var ymax = b.max.y;
|
|
var zmax = b.max.z;
|
|
|
|
Gizmos.DrawLine(new(xmin, ymin, zmin), new(xmin, ymin, zmax));
|
|
Gizmos.DrawLine(new(xmin, ymin, zmin), new(xmax, ymin, zmin));
|
|
Gizmos.DrawLine(new(xmax, ymin, zmax), new(xmin, ymin, zmax));
|
|
Gizmos.DrawLine(new(xmax, ymin, zmax), new(xmax, ymin, zmin));
|
|
|
|
Gizmos.DrawLine(new(xmin, ymax, zmin), new(xmin, ymax, zmax));
|
|
Gizmos.DrawLine(new(xmin, ymax, zmin), new(xmax, ymax, zmin));
|
|
Gizmos.DrawLine(new(xmax, ymax, zmax), new(xmin, ymax, zmax));
|
|
Gizmos.DrawLine(new(xmax, ymax, zmax), new(xmax, ymax, zmin));
|
|
|
|
Gizmos.DrawLine(new(xmax, ymax, zmax), new(xmax, ymin, zmax));
|
|
Gizmos.DrawLine(new(xmin, ymin, zmin), new(xmin, ymax, zmin));
|
|
Gizmos.DrawLine(new(xmax, ymin, zmin), new(xmax, ymax, zmin));
|
|
Gizmos.DrawLine(new(xmin, ymax, zmax), new(xmin, ymin, zmax));
|
|
}
|
|
}
|
|
}
|