| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- // River Modeler
- // Staggart Creations (http://staggart.xyz)
- // Copyright protected under Unity Asset Store EULA
- // Copying or referencing source code for the production of new asset store content is strictly prohibited.
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- #if MATHEMATICS
- using Unity.Mathematics;
- #endif
- #if SPLINES
- using UnityEngine.Splines;
- #endif
- namespace sc.modeling.river.runtime
- {
- public partial class RiverModeler
- {
- #if SPLINES
- public SplineContainer splineContainer;
-
- public enum SplineChangeReaction
- {
- During,
- WhenDone,
- }
- [Tooltip("Determines when a change to the spline should be detected")]
- public SplineChangeReaction splineChangeMode = SplineChangeReaction.During;
-
- #if MATHEMATICS
- /// <summary>
- /// X-component defines the width of the river. Y-component scales the displacement. Sample data using length units.
- /// </summary>
- public List<SplineData<float3>> ScaleData = new List<SplineData<float3>>();
- /// <summary>
- /// Weights for transparency data stored in vertex colors. Sample data using length units.
- /// </summary>
- public List<SplineData<float>> TransparencyData = new List<SplineData<float>>();
- /// Weights for foam strength stored in vertex colors. Normalized value where 0=subtracting 0.5=none 1.0=adding. Sample data using length units.
- public List<SplineData<float>> FoamData = new List<SplineData<float>>();
- #endif
-
- private partial void SubscribeSplineCallbacks()
- {
- #if SPLINES && MATHEMATICS
- SplineContainer.SplineAdded += OnSplineAdded;
- SplineContainer.SplineRemoved += OnSplineRemoved;
- Spline.Changed += OnSplineChanged;
- #endif
- }
-
- private partial void UnsubscribeSplineCallbacks()
- {
- #if SPLINES && MATHEMATICS
- SplineContainer.SplineAdded -= OnSplineAdded;
- SplineContainer.SplineRemoved -= OnSplineRemoved;
- Spline.Changed -= OnSplineChanged;
- #endif
- }
- #endif
-
- #if SPLINES && MATHEMATICS
- private int lastEditedSplineIndex = -1;
-
- private void OnSplineChanged(Spline spline, int index, SplineModification modificationType)
- {
- if (!splineContainer) return;
- if (rebuildTriggers.HasFlag(RebuildTriggers.OnSplineChanged) == false) return;
-
- //Spline belongs to the assigned container?
- var splineIndex = Array.IndexOf(splineContainer.Splines.ToArray(), spline);
- if (splineIndex < 0)
- return;
-
- lastEditedSplineIndex = splineIndex;
-
- if (splineChangeMode == SplineChangeReaction.WhenDone)
- {
- lastChangeTime = Time.realtimeSinceStartup;
- if (Application.isPlaying)
- {
- //Coroutines only work in play mode and builds
-
- //Cancel any existing debounce coroutine
- if (debounceCoroutine != null) StopCoroutine(debounceCoroutine);
-
- debounceCoroutine = StartCoroutine(DebounceCoroutine());
- }
- else
- {
- if (!isTrackingChanges)
- {
- isTrackingChanges = true;
-
- #if UNITY_EDITOR
- UnityEditor.EditorApplication.update += EditorUpdate;
- #endif
- }
-
- }
- }
- else if (splineChangeMode == SplineChangeReaction.During)
- {
- ExecuteAfterSplineChanges();
- }
- }
-
- public float debounceTime = 0.1f;
- private float lastChangeTime = -1f;
- private bool isTrackingChanges = false;
-
- private void EditorUpdate()
- {
- if (isTrackingChanges && Time.realtimeSinceStartup - lastChangeTime >= debounceTime)
- {
- ExecuteAfterSplineChanges();
-
- isTrackingChanges = false;
-
- #if UNITY_EDITOR
- UnityEditor.EditorApplication.update -= EditorUpdate;
- #endif
- }
- }
-
- private Coroutine debounceCoroutine;
- private IEnumerator DebounceCoroutine()
- {
- yield return new WaitForSeconds(debounceTime);
-
- ExecuteAfterSplineChanges();
- }
- private void ExecuteAfterSplineChanges()
- {
- if(lastEditedSplineIndex < 0) return;
-
- Rebuild(ChangeFlags.Spline);
- }
-
- void OnSplineAdded(SplineContainer container, int index)
- {
- if (rebuildTriggers.HasFlag(RebuildTriggers.OnSplineAdded) == false) return;
-
- if (container.GetHashCode() != splineContainer.GetHashCode())
- return;
-
- //Debug.Log("OnSplineContainerAdded");
-
- ValidateData(container);
-
- Rebuild(ChangeFlags.Spline);
- }
- /// <summary>
- /// Ensures that the component has Scale/Transparency/Foam data set up for every spline, and there's a default value point at the start & end.
- /// </summary>
- /// <param name="container"></param>
- public void ValidateData(SplineContainer container)
- {
- #if MATHEMATICS
- int splineCount = container.Splines.Count;
- if (ScaleData.Count < splineCount)
- {
- var delta = splineCount - ScaleData.Count;
-
- //Debug.Log($"OnSplineContainerAdded. Adding {delta} new data");
- for (var i = 0; i < delta; i++)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Modifying river Scale");
- #endif
-
- float length = container.Splines[i].CalculateLength(container.transform.localToWorldMatrix);
-
- SplineData<float3> data = new SplineData<float3>();
- data.DefaultValue = Vector3.one;
- data.PathIndexUnit = PathIndexUnit.Distance;
- data.AddDataPointWithDefaultValue(0f);
- data.AddDataPointWithDefaultValue(length);
-
- ScaleData.Add(data);
- }
- }
-
- if (TransparencyData.Count < splineCount)
- {
- var delta = splineCount - TransparencyData.Count;
- for (var i = 0; i < delta; i++)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Modifying river Transparency");
- #endif
-
- float length = container.Splines[i].CalculateLength(container.transform.localToWorldMatrix);
- SplineData<float> data = new SplineData<float>();
- data.DefaultValue = 0f;
- data.PathIndexUnit = PathIndexUnit.Distance;
- data.AddDataPointWithDefaultValue(0f);
- data.AddDataPointWithDefaultValue(length);
-
- TransparencyData.Add(data);
- }
- }
-
- if (FoamData.Count < splineCount)
- {
- var delta = splineCount - FoamData.Count;
- for (var i = 0; i < delta; i++)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Modifying river Foam");
- #endif
-
- float length = container.Splines[i].CalculateLength(container.transform.localToWorldMatrix);
- SplineData<float> data = new SplineData<float>();
- data.DefaultValue = 0.5f;
- data.PathIndexUnit = PathIndexUnit.Distance;
- data.AddDataPointWithDefaultValue(0f);
- data.AddDataPointWithDefaultValue(length);
-
- FoamData.Add(data);
- }
- }
- #endif
- }
- [ContextMenu("Reset spline Transparency")]
- public void ResetTransparencyData()
- {
- if (!splineContainer) return;
-
- TransparencyData.Clear();
- ValidateData(splineContainer);
-
- Rebuild(ChangeFlags.Data);
- }
-
- [ContextMenu("Reset spline Scale")]
- public void ResetDisplacementData()
- {
- if (!splineContainer) return;
-
- ScaleData.Clear();
- ValidateData(splineContainer);
-
- Rebuild(ChangeFlags.Data);
- }
-
- [ContextMenu("Reset spline Foam")]
- public void ResetFoamData()
- {
- if (!splineContainer) return;
-
- FoamData.Clear();
- ValidateData(splineContainer);
-
- Rebuild(ChangeFlags.Data);
- }
-
- void OnSplineRemoved(SplineContainer container, int index)
- {
- if (rebuildTriggers.HasFlag(RebuildTriggers.OnSplineRemoved) == false) return;
-
- if (container != splineContainer)
- return;
- if (index < ScaleData.Count)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Deleting river Scale data");
- #endif
-
- ScaleData.RemoveAt(index);
- }
-
- if (index < TransparencyData.Count)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Deleting river Transparency data");
- #endif
-
- TransparencyData.RemoveAt(index);
- }
-
- if (index < FoamData.Count)
- {
- #if UNITY_EDITOR
- UnityEditor.Undo.RecordObject(this, "Deleting river Foam data");
- #endif
-
- FoamData.RemoveAt(index);
- }
- Rebuild(ChangeFlags.Data);
- }
- #endif
- }
- }
|