174 lines
4.4 KiB
C#
174 lines
4.4 KiB
C#
// Crest Water System
|
|
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
|
|
|
using UnityEngine;
|
|
|
|
namespace WaveHarmonic.Crest.Examples
|
|
{
|
|
[AddComponentMenu(Constants.k_MenuPrefixSample + "Waterfall (Sample)")]
|
|
[ExecuteAlways]
|
|
sealed class Waterfall : MonoBehaviour
|
|
{
|
|
[SerializeField, HideInInspector]
|
|
#pragma warning disable 414
|
|
int _Version = 0;
|
|
#pragma warning restore 414
|
|
|
|
public Transform _Crest;
|
|
public float _CrestRadius = 1f;
|
|
|
|
public Transform _Face;
|
|
public float _FaceAngle = 5f;
|
|
|
|
public Transform _Waves;
|
|
|
|
[Tooltip("The bottom of the waterfall. If unset, it will use sea level.")]
|
|
public Transform _PlungePool;
|
|
|
|
public Transform _Foam;
|
|
public float _FoamOffset;
|
|
public float _FoamPadding;
|
|
|
|
public Transform _Flow;
|
|
public float _FlowPadding = 10f;
|
|
|
|
float HeightFromPlungePool => transform.position.y - (_PlungePool != null
|
|
? _PlungePool.position.y
|
|
: WaterRenderer.Instance != null
|
|
? WaterRenderer.Instance.SeaLevel
|
|
: 0f);
|
|
|
|
void OnEnable()
|
|
{
|
|
Update();
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
UpdateFace();
|
|
UpdateCrest();
|
|
UpdateWaves();
|
|
UpdateFoam();
|
|
UpdateFlow();
|
|
}
|
|
|
|
void UpdateCrest()
|
|
{
|
|
if (_Crest == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var crest = _Crest;
|
|
|
|
var position = crest.localPosition;
|
|
position.y = -_CrestRadius;
|
|
crest.localPosition = position;
|
|
|
|
var scale = crest.localScale;
|
|
scale.x = _CrestRadius * 2f;
|
|
scale.z = _CrestRadius * 2f;
|
|
crest.localScale = scale;
|
|
}
|
|
|
|
void UpdateFace()
|
|
{
|
|
if (_Face == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var face = _Face;
|
|
var angle = _FaceAngle * Mathf.Deg2Rad;
|
|
var ratio = 1f / Mathf.Cos(angle);
|
|
var height = HeightFromPlungePool - _CrestRadius;
|
|
var center = height * 0.5f;
|
|
|
|
var rotation = face.localRotation.eulerAngles;
|
|
rotation.x = 90f - _FaceAngle;
|
|
face.localRotation = Quaternion.Euler(rotation);
|
|
|
|
// Plane is 10m.
|
|
var scale = face.localScale;
|
|
scale.z = height * 0.1f * ratio;
|
|
face.localScale = scale;
|
|
|
|
var position = face.localPosition;
|
|
position.y = -center;
|
|
position.z = center * ratio * Mathf.Sin(angle);
|
|
|
|
position.y += -_CrestRadius;
|
|
position.z += _CrestRadius;
|
|
|
|
face.localPosition = position;
|
|
}
|
|
|
|
void UpdateWaves()
|
|
{
|
|
if (_Waves == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var waves = _Waves;
|
|
|
|
var feather = 0f;
|
|
|
|
if (_Waves.TryGetComponent<Renderer>(out var renderer) && renderer.sharedMaterial != null && renderer.sharedMaterial.IsKeywordEnabled("d_Feather"))
|
|
{
|
|
feather = renderer.sharedMaterial.GetFloat(Shader.PropertyToID("_Crest_FeatherWidth"));
|
|
}
|
|
|
|
var position = waves.localPosition;
|
|
|
|
var scale = waves.localScale.x;
|
|
|
|
position.z = scale * 0.5f + (_Face.localPosition.z * 2f - _CrestRadius) - feather * scale;
|
|
|
|
position.y = -HeightFromPlungePool;
|
|
|
|
waves.localPosition = position;
|
|
}
|
|
|
|
void UpdateFoam()
|
|
{
|
|
if (_Foam == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var foam = _Foam;
|
|
|
|
var size = _Face.localPosition.z * 2f - _CrestRadius;
|
|
|
|
var scale = foam.localScale;
|
|
scale.y = size + _FoamPadding;
|
|
foam.localScale = scale;
|
|
|
|
var position = _Foam.localPosition;
|
|
position.z = size * 0.5f + _FoamOffset;
|
|
_Foam.localPosition = position;
|
|
}
|
|
|
|
void UpdateFlow()
|
|
{
|
|
if (_Flow == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var flow = _Flow;
|
|
|
|
var size = _Face.localPosition.z * 2f - _CrestRadius;
|
|
|
|
var scale = flow.localScale;
|
|
scale.y = size + _FlowPadding;
|
|
flow.localScale = scale;
|
|
|
|
var position = _Flow.localPosition;
|
|
position.z = size * 0.5f;
|
|
_Flow.localPosition = position;
|
|
}
|
|
}
|
|
}
|