using System; using NWH.DWP2.WaterObjects; using UnityEngine; namespace NWH.DWP2.WaterData { /// /// Class for providing water height and velocity data to WaterObjectManager. /// public abstract class WaterDataProvider : MonoBehaviour { protected Vector3[] _singlePointArray; protected float[] _singleHeightArray; protected Collider _triggerCollider; private void OnTriggerEnter(Collider other) { // Assign the current water data provider Rigidbody targetRigidbody = other.attachedRigidbody; if (targetRigidbody != null) { WaterObject[] targetWaterObjects = targetRigidbody.GetComponentsInChildren(); for (int i = 0; i < targetWaterObjects.Length; i++) { targetWaterObjects[i].OnEnterWaterDataProvider(this); } } } private void OnTriggerExit(Collider other) { // Assign the current water data provider Rigidbody targetRigidbody = other.attachedRigidbody; if (targetRigidbody != null) { WaterObject[] targetWaterObjects = targetRigidbody.GetComponentsInChildren(); for (int i = 0; i < targetWaterObjects.Length; i++) { targetWaterObjects[i].OnExitWaterDataProvider(this); } } } public virtual void Awake() { _singleHeightArray = new float[1]; _singlePointArray = new Vector3[1]; _triggerCollider = GetComponent(); if (_triggerCollider == null) { // Debug.LogWarning("WaterDataProvider requires a Collider with 'Is Trigger' ticked to be present " + // "on the same GameObject to act as a trigger volume. Creating one."); _triggerCollider = gameObject.AddComponent(); _triggerCollider.isTrigger = true; ((SphereCollider) _triggerCollider).radius = 1000000f; } if (!_triggerCollider.isTrigger) { Debug.LogWarning("WaterDataProvider Collider has to have 'Is Trigger' ticked. Fixing."); _triggerCollider.isTrigger = true; } } /// /// Does this water system support water height queries? /// /// True if it does, false if it does not. public abstract bool SupportsWaterHeightQueries(); /// /// Does this water system support water normal queries? /// /// True if it does, false if it does not. public abstract bool SupportsWaterNormalQueries(); /// /// Does this water system support water velocity queries? /// /// True if it does, false if it does not. public abstract bool SupportsWaterFlowQueries(); /// /// Returns water height at each given point. /// /// Position array in world coordinates. /// Water height array in world coordinates. Corresponds to positions. public virtual void GetWaterHeights(WaterObject waterObject, ref Vector3[] points, ref float[] waterHeights) { // Do nothing. This will use the initial values of water heights (0). } /// /// Returns water flow at each given point. /// Water flow should be in world coordinates and relative to the world, not the WaterObject itself. /// WaterObject velocity and angularVelocity are both accounted for inside WaterTriangleJob. /// /// Position array in world coordinates. /// Water flow array in world coordinates. Corresponds to positions. public virtual void GetWaterFlows(WaterObject waterObject, ref Vector3[] points, ref Vector3[] waterFlows) { // Do nothing. This will use the initial values of water velocities (0,0,0). } /// /// Returns water normals at each given point. /// /// Position array in world coordinates. /// Water normal array in world coordinates. Corresponds to positions. public virtual void GetWaterNormals(WaterObject waterObject, ref Vector3[] points, ref Vector3[] waterNormals) { // Do nothing. This will use the initial values of water normals (0,0,0). } public void GetWaterHeightsFlowsNormals(WaterObject waterObject, ref Vector3[] points, ref float[] waterHeights, ref Vector3[] waterFlows, ref Vector3[] waterNormals, bool useWaterHeight, bool useWaterNormals, bool useWaterFlow) { if (useWaterHeight) { GetWaterHeights(waterObject, ref points, ref waterHeights); } if (useWaterFlow && SupportsWaterFlowQueries()) { GetWaterFlows(waterObject, ref points, ref waterFlows); } if (useWaterNormals && SupportsWaterNormalQueries()) { GetWaterNormals(waterObject, ref points, ref waterNormals); } } public virtual float GetWaterHeightSingle(WaterObject waterObject, Vector3 point) { _singlePointArray[0] = point; GetWaterHeights(waterObject, ref _singlePointArray, ref _singleHeightArray); return _singleHeightArray[0]; } /// /// Returns true if point is in water. Works with wavy water too. /// public bool PointInWater(WaterObject waterObject, Vector3 worldPoint) { return GetWaterHeight(waterObject, worldPoint) > worldPoint.y; } public float GetWaterHeight(WaterObject waterObject, Vector3 worldPoint) { return GetWaterHeightSingle(waterObject, worldPoint); } private void OnDrawGizmos() { Gizmos.color = Color.green; Gizmos.DrawSphere(transform.position, 0.1f); } } }