| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- // 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 UnityEngine;
- using UnityEngine.Events;
- using UnityEngine.Rendering;
- #if MATHEMATICS
- using Unity.Mathematics;
- #endif
- #if SPLINES
- using UnityEngine.Splines;
- #endif
- namespace sc.modeling.river.runtime
- {
- /// <summary>
- /// Front-end MonoBehaviour component
- /// </summary>
- [AddComponentMenu("Water/River Modeler")]
- [HelpURL("https://staggart.xyz/river-modeler-docs/?section=river-modeler")]
- [ExecuteInEditMode]
- public partial class RiverModeler : MonoBehaviour
- {
- /// <summary>
- /// Flags used to indicate which aspects of a river is being modified
- /// </summary>
- [Flags]
- public enum ChangeFlags
- {
- All = 1,
- Spline = 2,
- Geometry = 4,
- VertexAttribute = 8,
- Foam = 16,
- Scale = 32,
- Transparency = 64,
- Data = 128
- }
-
- [Flags]
- public enum RebuildTriggers
- {
- [InspectorName("Via scripting")]
- None = 0,
- OnSplineChanged = 1,
- OnSplineAdded = 2,
- OnSplineRemoved = 4,
- [InspectorName("On Start()")]
- OnStart = 8,
- OnUIChange = 16,
- OnSplineTransformChange = 32
- }
- [Tooltip("Control which sort of events cause the mesh to be regenerated." +
- "\n\n" +
- "For instance when the spline changes (default), or on the component's Start() function." +
- "\n\n" +
- "If none are selected you need to call the Rebuild() function through script.")]
- public RebuildTriggers rebuildTriggers = RebuildTriggers.OnSplineAdded | RebuildTriggers.OnSplineRemoved | RebuildTriggers.OnSplineChanged | RebuildTriggers.OnUIChange | RebuildTriggers.OnSplineTransformChange;
-
- [Tooltip("The target mesh filter the generated mesh is stored in. Attaching a Mesh Renderer to the same object will render it using a material")]
- public MeshFilter meshFilter;
- [Range(-3, 3)]
- [Tooltip("Sets the rendering offset for the Mesh Renderer component." +
- "\n\n" +
- "This relates directly to transparency sorting and may be used to force one river to render on top of another one." +
- "\n\n" +
- "For this to have any effect, the renderer must used a shader that doesn't write to the depth buffer (ZWrite Off) ")]
- public int orderInLayer = 0;
- /* LOD Group support WIP
- public LODGroup lodGroup;
-
- [Serializable]
- public class LOD
- {
- [Range(5f, 100f)]
- public float resolution = 100f;
- public LOD(float resolution)
- {
- this.resolution = resolution;
- }
- }
- public List<LOD> lods = new List<LOD>()
- {
- new LOD(100f)
- };
- */
- /// <summary>
- /// Settings used for geometry generation
- /// </summary>
- public Settings settings = new Settings();
- public bool exportToFBX;
- public string fbxFilePath;
- #pragma warning disable CS0067
- public delegate void OnRebuildRiver(RiverModeler instance, ChangeFlags updateFlags);
- public static event OnRebuildRiver onPreRebuildRiver;
- public static event OnRebuildRiver onPostRebuildRiver;
-
- /// <summary>
- /// UnityEvent for a GameObject's function to be executed when river is rebuild. This is exposed in the inspector.
- /// </summary>
- [Serializable]
- public class RebuildEvent : UnityEvent<ChangeFlags> { }
- /// <summary>
- /// UnityEvent, fires whenever spline is rebuild (eg. editing nodes)
- /// </summary>
- public RebuildEvent onPreRebuild;
- public RebuildEvent onPostRebuild;
- #pragma warning restore CS0067
- public void Reset()
- {
- #if !SPLINES
- Debug.LogError("This component requires the Splines package. Please install this through the Package Manager");
- #endif
- #if !MATHEMATICS
- Debug.LogError("This component requires the Mathematics package. Please install this through the Package Manager");
- #endif
-
- meshFilter = GetComponent<MeshFilter>();
- #if SPLINES && MATHEMATICS
- if(!splineContainer) splineContainer = GetComponentInParent<SplineContainer>();
-
- ValidateData(splineContainer);
- #endif
-
- Rebuild();
- }
- private void OnEnable()
- {
- #if SPLINES
- SubscribeSplineCallbacks();
- #endif
- }
- private void OnDisable()
- {
- #if SPLINES
- UnsubscribeSplineCallbacks();
- #endif
- }
-
- private void Start()
- {
- //In this case the component was likely copied somewhere, or prefabbed. Mesh data will have been lost, so regenerating it is an alternative
- if (rebuildTriggers.HasFlag(RebuildTriggers.OnStart)) Rebuild();
- }
- #if SPLINES
- private partial void SubscribeSplineCallbacks();
- private partial void UnsubscribeSplineCallbacks();
- #endif
- public void Rebuild(ChangeFlags updateFlags = ChangeFlags.All)
- {
- //Debug.Log($"Rebuilding river with update flags: {updateFlags}", this);
-
- if (!meshFilter) return;
-
- onPreRebuildRiver?.Invoke(this, updateFlags);
- onPreRebuild?.Invoke(updateFlags);
-
- settings.foam.Validate();
- #if SPLINES && MATHEMATICS
- if (!splineContainer) return;
-
- ValidateData(splineContainer);
-
- if(updateFlags.HasFlag(ChangeFlags.All | ChangeFlags.Spline)) ValidateData(splineContainer);
-
- /* LOD Group support WIP
- //Single mesh
- if (lods.Count == 1 && meshFilter)
- {
- meshFilter.sharedMesh = Geometry.Create(splineContainer, ScaleData, OpacityData, generationSettings, meshFilter.transform.worldToLocalMatrix);
- }
-
- //LOD set up
- if (lods.Count > 1 && lodGroup)
- {
- UnityEngine.LOD[] lodGroupLODS = lodGroup.GetLODs();
-
- for (int i = 0; i < lodGroupLODS.Length; i++)
- {
- MeshFilter lodMF = lodGroupLODS[i].renderers[0].GetComponent<MeshFilter>();
- if (lodMF)
- {
- lodMF.sharedMesh = Geometry.Create(splineContainer, ScaleData, OpacityData, generationSettings, meshFilter.transform.worldToLocalMatrix, lods[i].resolution);
-
- Debug.Log($"Creating LOD {i} at {lods[i].resolution}% for {lodMF.gameObject.name}");
- }
- }
- }
- */
- meshFilter.sharedMesh = Geometry.Create(splineContainer, settings, meshFilter.transform.worldToLocalMatrix, 100f, ScaleData, TransparencyData, FoamData);
-
- MeshRenderer meshRenderer = meshFilter.GetComponent<MeshRenderer>();
- if (meshRenderer)
- {
- meshRenderer.sortingOrder = orderInLayer;
- meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
- if (settings.transparency.vertexColorChannel == Settings.VertexColorChannel.Green)
- {
- //If the material uses Stylized Water 2, enable vertex color transparency. Quickfix to avoid support overhead
- var vertexColorAlphaProp = Shader.PropertyToID("_VertexColorDepth");
- if (meshRenderer.sharedMaterial.HasProperty(vertexColorAlphaProp))
- {
- if (meshRenderer.sharedMaterial.GetFloat(vertexColorAlphaProp) == 0)
- {
- Debug.Log($"[River Modeler] A Stylized Water 2 material is in use, yet vertex color Transparency wasn't enabled on the material. Enabled now.", this.gameObject);
- meshRenderer.sharedMaterial.SetFloat(vertexColorAlphaProp, 1);
-
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(meshRenderer.sharedMaterial);
- #endif
- }
- }
- //If the material uses Stylized Water 3, enable vertex color transparency. Quickfix to avoid support overhead
- vertexColorAlphaProp = Shader.PropertyToID("_VertexColorTransparency");
- if (meshRenderer.sharedMaterial.HasProperty(vertexColorAlphaProp))
- {
- if (meshRenderer.sharedMaterial.GetFloat(vertexColorAlphaProp) == 0)
- {
- Debug.Log($"[River Modeler] A Stylized Water 3 material is in use, yet vertex color Transparency wasn't enabled on the material. Enabled now.", this.gameObject);
- meshRenderer.sharedMaterial.SetFloat(vertexColorAlphaProp, 1);
-
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(meshRenderer.sharedMaterial);
- #endif
- }
- }
- }
- if (settings.transparency.vertexColorChannel == Settings.VertexColorChannel.Alpha)
- {
- //If the material uses Stylized Water, enable vertex color foam. Quickfix to avoid support overhead
- var vertexColorFoamProp = Shader.PropertyToID("_VertexColorFoam");
- if (meshRenderer.sharedMaterial.HasProperty(vertexColorFoamProp))
- {
- if (meshRenderer.sharedMaterial.GetFloat(vertexColorFoamProp) == 0)
- {
- Debug.Log($"[River Modeler] A Stylized Water material is in use, yet vertex color Foam wasn't enabled on the material. Enabled now.", this.gameObject);
- meshRenderer.sharedMaterial.SetFloat(vertexColorFoamProp, 1);
-
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(meshRenderer.sharedMaterial);
- #endif
- }
- }
- }
- }
- //Update mesh collider
- MeshCollider meshCollider = GetComponent<MeshCollider>();
- if (meshCollider) meshCollider.sharedMesh = meshFilter.sharedMesh;
-
- onPostRebuildRiver?.Invoke(this, updateFlags);
- onPostRebuild?.Invoke(updateFlags);
-
- #if MICROVERSE_SPLINES
- if (updateFlags.HasFlag(ChangeFlags.All) || updateFlags.HasFlag(ChangeFlags.Spline) || updateFlags.HasFlag(ChangeFlags.Geometry) || updateFlags.HasFlag(ChangeFlags.Data))
- {
- //MicroVerse syncing
- UpdateMicroVerseSpline();
- }
- #endif
-
- #endif
- }
- public partial void UpdateMicroVerseSpline();
- partial void DrawDebugging();
-
- private void OnDrawGizmosSelected()
- {
- DrawDebugging();
-
- #if SPLINES && MATHEMATICS
- //Moving the spline, then selecting the river again
- if (splineContainer && splineContainer.transform.hasChanged)
- {
- if (rebuildTriggers.HasFlag(RebuildTriggers.OnSplineTransformChange))
- {
- splineContainer.transform.hasChanged = false;
- Rebuild();
- }
- }
- #endif
- }
- }
- }
|