修改水
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9705fd80c227847b1b2c21279a353316
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d75412fa9c7c743ddb0bc94b3a5c7622
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5be9f1155ece744ac9b4e52aa05d7ef9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest")]
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8af62055026f246e7a9d675f69b994d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:457756d89b35d2941b3e7b37b4ece6f1"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c358b569712814645b33be93fdc16c4d
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b91042832cea4543b4c617e5ee9501b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9a650914f9e44519ab747c4366060de
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest")]
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46afa615b9e4b409481f591af6c8d671
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:15fc0a57446b3144c949da3e2b9737a9"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c91763ce81814a8cb7f57f7e18525bb
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using WaveHarmonic.Crest.Utility;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
/// <summary>
|
||||
/// Overrides global quality settings.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public sealed partial class QualitySettingsOverride
|
||||
{
|
||||
[Tooltip("Whether to override the LOD bias.")]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal bool _OverrideLodBias;
|
||||
|
||||
[Tooltip("Overrides the LOD bias for meshes.\n\nHighest quality is infinity.")]
|
||||
[@Predicated(nameof(_OverrideLodBias))]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal float _LodBias;
|
||||
|
||||
[Tooltip("Whether to override the maximum LOD level.")]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal bool _OverrideMaximumLodLevel;
|
||||
|
||||
[Tooltip("Overrides the maximum LOD level.\n\nHighest quality is zero.")]
|
||||
[@Predicated(nameof(_OverrideMaximumLodLevel))]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal int _MaximumLodLevel;
|
||||
|
||||
|
||||
[Tooltip("Whether to override the terrain pixel error.")]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal bool _OverrideTerrainPixelError;
|
||||
|
||||
[Tooltip("Overrides the pixel error value for terrains.\n\nHighest quality is zero.")]
|
||||
[@Predicated(nameof(_OverrideTerrainPixelError))]
|
||||
[@GenerateAPI]
|
||||
[@DecoratedField, SerializeField]
|
||||
internal float _TerrainPixelError;
|
||||
|
||||
float _OldLodBias;
|
||||
int _OldMaximumLodLevelOverride;
|
||||
float _OldTerrainPixelError;
|
||||
TerrainQualityOverrides _OldTerrainOverrides;
|
||||
|
||||
internal void Override()
|
||||
{
|
||||
if (_OverrideLodBias)
|
||||
{
|
||||
_OldLodBias = QualitySettings.lodBias;
|
||||
QualitySettings.lodBias = _LodBias;
|
||||
}
|
||||
|
||||
if (_OverrideMaximumLodLevel)
|
||||
{
|
||||
_OldMaximumLodLevelOverride = QualitySettings.maximumLODLevel;
|
||||
QualitySettings.maximumLODLevel = _MaximumLodLevel;
|
||||
}
|
||||
|
||||
if (_OverrideTerrainPixelError)
|
||||
{
|
||||
_OldTerrainOverrides = QualitySettings.terrainQualityOverrides;
|
||||
_OldTerrainPixelError = QualitySettings.terrainPixelError;
|
||||
QualitySettings.terrainQualityOverrides = TerrainQualityOverrides.PixelError;
|
||||
QualitySettings.terrainPixelError = _TerrainPixelError;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Restore()
|
||||
{
|
||||
if (_OverrideLodBias)
|
||||
{
|
||||
QualitySettings.lodBias = _OldLodBias;
|
||||
}
|
||||
|
||||
if (_OverrideMaximumLodLevel)
|
||||
{
|
||||
QualitySettings.maximumLODLevel = _OldMaximumLodLevelOverride;
|
||||
}
|
||||
|
||||
if (_OverrideTerrainPixelError)
|
||||
{
|
||||
QualitySettings.terrainQualityOverrides = _OldTerrainOverrides;
|
||||
QualitySettings.terrainPixelError = _OldTerrainPixelError;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = Hash.CreateHash();
|
||||
Hash.AddBool(_OverrideLodBias, ref hash);
|
||||
Hash.AddFloat(_LodBias, ref hash);
|
||||
Hash.AddBool(_OverrideMaximumLodLevel, ref hash);
|
||||
Hash.AddInt(_MaximumLodLevel, ref hash);
|
||||
Hash.AddBool(_OverrideTerrainPixelError, ref hash);
|
||||
Hash.AddFloat(_TerrainPixelError, ref hash);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c534680c2c3c4912bfabb90bfa03574
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37d8168c36cf74fdea3eef047313d378
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Shared.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Examples")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Ripples")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Submarine")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.CPUQueries")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.CPUQueries.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Paint")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Paint.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShallowWater")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShallowWater.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShiftingOrigin")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShiftingOrigin.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Splines")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Splines.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Watercraft")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Watercraft.Editor")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Whirlpool")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Whirlpool.Editor")]
|
||||
|
||||
// Define empty namespaces for when assemblies are not present.
|
||||
namespace UnityEditor.SceneManagement { }
|
||||
namespace UnityEngine.Rendering.HighDefinition { }
|
||||
namespace UnityEngine.Rendering.Universal { }
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4f89cf7fe52246cb883953865c0ae55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c01e8ab7829a9475d86ca9975ce640aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Circular buffer to store a multiple sets of data.
|
||||
/// </summary>
|
||||
sealed class BufferedData<T>
|
||||
{
|
||||
readonly T[] _Buffers;
|
||||
int _CurrentFrameIndex;
|
||||
|
||||
public T Current { get => _Buffers[_CurrentFrameIndex]; set => _Buffers[_CurrentFrameIndex] = value; }
|
||||
public int Size => _Buffers.Length;
|
||||
|
||||
public BufferedData(int size, Func<T> initialize)
|
||||
{
|
||||
_Buffers = new T[size];
|
||||
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
_Buffers[i] = initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public T Previous(int framesBack)
|
||||
{
|
||||
Debug.Assert(framesBack >= 0 && framesBack < _Buffers.Length);
|
||||
return _Buffers[(_CurrentFrameIndex - framesBack + _Buffers.Length) % _Buffers.Length];
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
_CurrentFrameIndex = (_CurrentFrameIndex + 1) % _Buffers.Length;
|
||||
}
|
||||
|
||||
public void RunLambda(Action<T> lambda)
|
||||
{
|
||||
foreach (var buffer in _Buffers)
|
||||
{
|
||||
lambda(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5666bcd450914e3e980a32dd866957e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a list this is meant to be similar in behaviour to the C#
|
||||
/// SortedList, but without allocations when used directly in a foreach loop.
|
||||
///
|
||||
/// It works by using a regular list as as backing and ensuring that it is
|
||||
/// sorted when the enumerator is accessed and used. This is a simple approach
|
||||
/// that means we avoid sorting each time an element is added, and helps us
|
||||
/// avoid having to develop our own more complex data structure.
|
||||
/// </summary>
|
||||
sealed class SortedList<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
|
||||
{
|
||||
public int Count => _BackingList.Count;
|
||||
|
||||
readonly List<KeyValuePair<TKey, TValue>> _BackingList = new();
|
||||
readonly System.Comparison<TKey> _Comparison;
|
||||
bool _NeedsSorting = false;
|
||||
|
||||
int Comparison(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
|
||||
{
|
||||
return _Comparison(x.Key, y.Key);
|
||||
}
|
||||
|
||||
public SortedList(System.Comparison<TKey> comparison)
|
||||
{
|
||||
// We provide the only constructors that SortedList provides that
|
||||
// we need. We wrap the input IComparer to ensure that our backing list
|
||||
// is sorted in the same way a SortedList would be with the same one.
|
||||
_Comparison = comparison;
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
_BackingList.Add(new(key, value));
|
||||
_NeedsSorting = true;
|
||||
}
|
||||
|
||||
public bool Remove(TValue value)
|
||||
{
|
||||
// This remove function has a fairly high complexity, as we need to search
|
||||
// the list for a matching Key-Value pair, and then remove it. However,
|
||||
// for the small lists we work with this is fine, as we don't use this
|
||||
// function more often. But it's worth bearing in mind if we decide to
|
||||
// expand where we use this list. At that point we might need to take a
|
||||
// different approach.
|
||||
|
||||
var removeIndex = -1;
|
||||
var index = 0;
|
||||
foreach (var item in _BackingList)
|
||||
{
|
||||
if (item.Value.Equals(value))
|
||||
{
|
||||
removeIndex = index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (removeIndex > -1)
|
||||
{
|
||||
// Remove method produces garbage.
|
||||
_BackingList.RemoveAt(removeIndex);
|
||||
}
|
||||
|
||||
return removeIndex > -1;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_BackingList.Clear();
|
||||
_NeedsSorting = false;
|
||||
}
|
||||
|
||||
#region GetEnumerator
|
||||
public List<KeyValuePair<TKey, TValue>>.Enumerator GetEnumerator()
|
||||
{
|
||||
ResortArrays();
|
||||
return _BackingList.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
void ResortArrays()
|
||||
{
|
||||
if (_NeedsSorting)
|
||||
{
|
||||
// @GC: Allocates 112B.
|
||||
_BackingList.Sort(Comparison);
|
||||
}
|
||||
_NeedsSorting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f796ed8d9971b4795b28bcb1c4dc3a01
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A less rigid stack implementation which is easier to use. Prevents duplicates.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to store.</typeparam>
|
||||
public sealed class Stack<T>
|
||||
{
|
||||
readonly List<T> _Items = new();
|
||||
|
||||
internal Stack() { }
|
||||
|
||||
/// <summary>
|
||||
/// Add item to the end of the stack.
|
||||
/// </summary>
|
||||
/// <param name="item">Item to add.</param>
|
||||
public void Push(T item)
|
||||
{
|
||||
Debug.Assert(item != null, "Null item pushed");
|
||||
// Remove any instances of item already in the stack.
|
||||
Pop(item);
|
||||
// Add it to the top.
|
||||
_Items.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all instances of item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to be removed.</param>
|
||||
public void Pop(T item)
|
||||
{
|
||||
Debug.Assert(item != null, "Null item popped");
|
||||
_Items.RemoveAll(candidate => candidate.Equals(item));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object at the top of the Stack without removing it.
|
||||
/// </summary>
|
||||
/// <returns>Object at the top of the Stack.</returns>
|
||||
public T Peek() => _Items[^1];
|
||||
|
||||
/// <summary>
|
||||
/// Number of items.
|
||||
/// </summary>
|
||||
public int Count => _Items.Count;
|
||||
|
||||
internal void Clear()
|
||||
{
|
||||
_Items.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0c68f77a1b8b43359f34cb46ce19801
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9f06a06d4570449fbc0c55e262f5ea9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,238 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma warning disable IDE0005 // Using directive is unnecessary.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class Symbols
|
||||
{
|
||||
public const string k_UnityEditor = "UNITY_EDITOR";
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
|
||||
sealed class ExecuteDuringEditMode : Attribute
|
||||
{
|
||||
[Flags]
|
||||
public enum Include
|
||||
{
|
||||
None,
|
||||
PrefabStage,
|
||||
BuildPipeline,
|
||||
All = PrefabStage | BuildPipeline,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Options
|
||||
{
|
||||
None,
|
||||
Singleton,
|
||||
}
|
||||
|
||||
public Include _Including;
|
||||
public Options _Options;
|
||||
|
||||
public ExecuteDuringEditMode(Include including = Include.PrefabStage, Options options = Options.None)
|
||||
{
|
||||
_Including = including;
|
||||
_Options = options;
|
||||
}
|
||||
}
|
||||
|
||||
enum Getter
|
||||
{
|
||||
Default,
|
||||
Custom,
|
||||
}
|
||||
|
||||
enum Setter
|
||||
{
|
||||
Default,
|
||||
Custom,
|
||||
Internal,
|
||||
Dirty,
|
||||
None,
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
sealed class GenerateAPI : Attribute
|
||||
{
|
||||
public readonly Getter _Getter;
|
||||
public readonly Setter _Setter;
|
||||
public readonly string _Name;
|
||||
public readonly string _ScriptingSymbol;
|
||||
|
||||
public GenerateAPI(Getter getter = Getter.Default, Setter setter = Setter.Default, string name = null, string symbol = null)
|
||||
{
|
||||
_Getter = getter;
|
||||
_Setter = setter;
|
||||
_Name = name;
|
||||
_ScriptingSymbol = symbol;
|
||||
}
|
||||
|
||||
public GenerateAPI(Setter setter, string name = null, string symbol = null)
|
||||
{
|
||||
_Setter = setter;
|
||||
_Name = name;
|
||||
_ScriptingSymbol = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
|
||||
abstract class Decorator : PropertyAttribute { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Layer : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Stripped : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Delayed : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Disabled : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class AttachMaterialEditor : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Embedded : Decorator
|
||||
{
|
||||
public Embedded(int margin = 0) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class DecoratedField : Decorator
|
||||
{
|
||||
public DecoratedField(bool isCustomFoldout = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Group : Decorator
|
||||
{
|
||||
public enum Style { None, Foldout, Accordian, }
|
||||
public Group(string title = null, Style style = Style.Foldout, bool isCustomFoldout = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Stepped : Decorator
|
||||
{
|
||||
public Stepped(int minimum, int maximum, int step = 1, bool power = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Range : Decorator
|
||||
{
|
||||
[Flags]
|
||||
public enum Clamp { None = 0, Minimum = 1, Maximum = 2, Both = Minimum | Maximum }
|
||||
public Range(float minimum, float maximum, Clamp clamp = Clamp.Both, float scale = 1f, bool delayed = false, int step = 0, bool power = false) {}
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Minimum : Decorator
|
||||
{
|
||||
public Minimum(float minimum) {}
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Maximum : Decorator
|
||||
{
|
||||
public Maximum(float maximum) {}
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class WarnIfAbove : Decorator
|
||||
{
|
||||
public WarnIfAbove(float maximum) {}
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Filtered : Decorator
|
||||
{
|
||||
public enum Mode { Include, Exclude, }
|
||||
public Filtered(int unset = 0) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class FilterEnum : Decorator
|
||||
{
|
||||
public FilterEnum(string property, Filtered.Mode mode, params int[] values) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Label : Decorator
|
||||
{
|
||||
public Label(string label) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Heading : Decorator
|
||||
{
|
||||
public enum Style { Normal, Settings, }
|
||||
public Heading(string heading, Style style = Style.Normal, bool alwaysVisible = false, bool alwaysEnabled = false, string helpLink = null) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Space : Decorator
|
||||
{
|
||||
public Space(float height, bool isAlwaysVisible = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Predicated : Decorator
|
||||
{
|
||||
public Predicated(Type type, string member, bool inverted = false, bool hide = false) { }
|
||||
public Predicated(Type type, bool inverted = false, bool hide = false) { }
|
||||
public Predicated(string property, bool inverted = false, object disableValue = null, bool hide = false) { }
|
||||
public Predicated(RenderPipeline rp, bool inverted = false, bool hide = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class OnChange : Decorator
|
||||
{
|
||||
public OnChange(bool skipIfInactive = true) { }
|
||||
public OnChange(Type type, bool skipIfInactive = true) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class HelpURL : Decorator
|
||||
{
|
||||
public HelpURL(string path = "") { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class HelpBox : Decorator
|
||||
{
|
||||
public enum MessageType { Info, Warning, Error, }
|
||||
public enum Visibility { Always, PropertyEnabled, PropertyDisabled, }
|
||||
public HelpBox(string message, MessageType messageType = MessageType.Info, Visibility visibility = Visibility.Always) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class MaterialField : Decorator
|
||||
{
|
||||
public MaterialField(string shader, string title = "", string name = "", string parent = null) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class PrefabField : Decorator
|
||||
{
|
||||
public PrefabField(string title = "", string name = "") { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class ShowComputedProperty : Decorator
|
||||
{
|
||||
public ShowComputedProperty(string name) { }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10b67a4d95adf4592abe527745be027b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,81 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using MonoBehaviour = WaveHarmonic.Crest.Internal.EditorBehaviour;
|
||||
#else
|
||||
using MonoBehaviour = UnityEngine.MonoBehaviour;
|
||||
#endif
|
||||
|
||||
namespace WaveHarmonic.Crest.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements logic to smooth out Unity's wrinkles.
|
||||
/// </summary>
|
||||
public abstract class CustomBehaviour : MonoBehaviour
|
||||
{
|
||||
bool _AfterStart;
|
||||
|
||||
#pragma warning disable 114
|
||||
private protected virtual void Awake()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
base.Awake();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity's Start method. Make sure to call base if overriden.
|
||||
/// </summary>
|
||||
protected void Start()
|
||||
{
|
||||
_AfterStart = true;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
base.Start();
|
||||
if (!enabled) return;
|
||||
#endif
|
||||
|
||||
OnStart();
|
||||
}
|
||||
#pragma warning restore 114
|
||||
|
||||
/// <summary>
|
||||
/// Called in OnEnable only after Start has ran.
|
||||
/// </summary>
|
||||
private protected virtual void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces Start. Only called in the editor if passes validation.
|
||||
/// </summary>
|
||||
private protected virtual void OnStart()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity's OnEnable method. Make sure to call base if overriden.
|
||||
/// </summary>
|
||||
private protected virtual void OnEnable()
|
||||
{
|
||||
if (!_AfterStart) return;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnEnterPlayMode]
|
||||
static void OnEnterPlayModeInEditor(EnterPlayModeOptions options)
|
||||
{
|
||||
foreach (var @object in FindObjectsByType<CustomBehaviour>(FindObjectsInactive.Include, FindObjectsSortMode.None))
|
||||
{
|
||||
@object._AfterStart = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 636b808a07ad9446c84091c05f393663
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,184 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
namespace WaveHarmonic.Crest.Internal
|
||||
{
|
||||
using Include = ExecuteDuringEditMode.Include;
|
||||
|
||||
/// <summary>
|
||||
/// Implements custom behaviours common to all components.
|
||||
/// </summary>
|
||||
public abstract partial class EditorBehaviour : MonoBehaviour
|
||||
{
|
||||
bool _IsFirstOnValidate = true;
|
||||
internal bool _IsPrefabStageInstance;
|
||||
|
||||
private protected virtual void Awake()
|
||||
{
|
||||
// When copy and pasting from one scene to another, destroy instance objects as
|
||||
// they will have bad state.
|
||||
foreach (var generated in transform.GetComponentsInChildren<ManagedGameObject>(includeInactive: true))
|
||||
{
|
||||
if (generated.Owner == this)
|
||||
{
|
||||
Helpers.Destroy(generated.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start method. Must be called if overriden.
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
if (Application.isPlaying && !(bool)s_ExecuteValidators.Invoke(null, new object[] { this }))
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Unity does not call OnDisable/OnEnable on Reset.
|
||||
private protected virtual void Reset()
|
||||
{
|
||||
if (!enabled) return;
|
||||
enabled = false;
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnValidate method. Must be called if overriden.
|
||||
/// </summary>
|
||||
private protected virtual void OnValidate()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_IsFirstOnValidate)
|
||||
{
|
||||
var attribute = Helpers.GetCustomAttribute<ExecuteDuringEditMode>(GetType());
|
||||
|
||||
var enableInEditMode = attribute != null;
|
||||
|
||||
if (enableInEditMode && !attribute._Including.HasFlag(Include.BuildPipeline))
|
||||
{
|
||||
// Do not execute when building the player.
|
||||
enableInEditMode = !BuildPipeline.isBuildingPlayer;
|
||||
}
|
||||
|
||||
// Components that use the singleton pattern are candidates for not executing in the prefab stage
|
||||
// as a new instance will be created which could interfere with the scene stage instance.
|
||||
if (enableInEditMode && !attribute._Including.HasFlag(Include.PrefabStage))
|
||||
{
|
||||
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
_IsPrefabStageInstance = stage != null && gameObject.scene == stage.scene;
|
||||
|
||||
// Do not execute in prefab stage.
|
||||
enableInEditMode = !_IsPrefabStageInstance;
|
||||
}
|
||||
|
||||
// When singleton, destroy instance objects.
|
||||
if (enableInEditMode && attribute._Options.HasFlag(ExecuteDuringEditMode.Options.Singleton) &&
|
||||
FindObjectsByType(GetType(), FindObjectsSortMode.None).Length > 1)
|
||||
{
|
||||
enableInEditMode = false;
|
||||
EditorApplication.update -= InternalDestroyNonSaveables;
|
||||
EditorApplication.update += InternalDestroyNonSaveables;
|
||||
}
|
||||
|
||||
// runInEditMode will immediately call Awake and OnEnable so we must not do this in OnValidate as there
|
||||
// are many restrictions which Unity will produce warnings for:
|
||||
// https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnValidate.html
|
||||
if (enableInEditMode)
|
||||
{
|
||||
if (BuildPipeline.isBuildingPlayer)
|
||||
{
|
||||
// EditorApplication.update and Invoke are not called when building.
|
||||
InternalEnableEditMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Called between OnAwake/OnEnable and Start which makes it seamless.
|
||||
EditorApplication.update -= InternalEnableEditMode;
|
||||
EditorApplication.update += InternalEnableEditMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_IsFirstOnValidate = false;
|
||||
}
|
||||
|
||||
void InternalDestroyNonSaveables()
|
||||
{
|
||||
EditorApplication.update -= InternalDestroyNonSaveables;
|
||||
|
||||
// See comment below.
|
||||
if (this == null) return;
|
||||
|
||||
foreach (Transform transform in transform.GetComponentInChildren<Transform>(includeInactive: true))
|
||||
{
|
||||
if (transform.gameObject.hideFlags.HasFlag(HideFlags.DontSaveInEditor))
|
||||
{
|
||||
Helpers.Destroy(transform.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InternalEnableEditMode()
|
||||
{
|
||||
EditorApplication.update -= InternalEnableEditMode;
|
||||
|
||||
// If the scene that is being built is already opened then, there can be a rogue instance which registers
|
||||
// an event but is destroyed by the time it gets here. It has something to do with OnValidate being called
|
||||
// after the object is destroyed with _isFirstOnValidate being true.
|
||||
if (this == null) return;
|
||||
// Workaround to ExecuteAlways also executing during building which is often not what we want.
|
||||
runInEditMode = true;
|
||||
}
|
||||
|
||||
static MethodInfo s_ExecuteValidators;
|
||||
[InitializeOnLoadMethod]
|
||||
static void Load()
|
||||
{
|
||||
var type = System.Type.GetType("WaveHarmonic.Crest.Editor.ValidatedHelper, WaveHarmonic.Crest.Shared.Editor");
|
||||
s_ExecuteValidators = type.GetMethod
|
||||
(
|
||||
"ExecuteValidators",
|
||||
BindingFlags.Public | BindingFlags.Static,
|
||||
null,
|
||||
new[] { typeof(Object) },
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
// Stores a reference to the owner so the GO can be deleted safely when duplicated/pasted.
|
||||
sealed class ManagedGameObject : MonoBehaviour
|
||||
{
|
||||
[field: SerializeField]
|
||||
public Component Owner { get; set; }
|
||||
}
|
||||
|
||||
static class Extentions
|
||||
{
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
public static void Manage(this Component owner, GameObject @object)
|
||||
{
|
||||
@object.AddComponent<ManagedGameObject>().Owner = owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f9b0b7f0a05449e4952db2c0e3a5516
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,177 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WaveHarmonic.Crest.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages ManagedBehaviours. Replaces Unity's event system.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The manager type.</typeparam>
|
||||
public abstract class ManagerBehaviour<T> : CustomBehaviour where T : ManagerBehaviour<T>
|
||||
{
|
||||
internal static readonly List<Action<T>> s_OnUpdate = new();
|
||||
internal static readonly List<Action<T>> s_OnLateUpdate = new();
|
||||
internal static readonly List<Action<T>> s_OnFixedUpdate = new();
|
||||
internal static readonly List<Action<T>> s_OnEnable = new();
|
||||
internal static readonly List<Action<T>> s_OnDisable = new();
|
||||
|
||||
/// <summary>
|
||||
/// The singleton instance.
|
||||
/// </summary>
|
||||
public static T Instance { get; private set; }
|
||||
|
||||
void Broadcast(List<Action<T>> listeners, T instance)
|
||||
{
|
||||
for (var i = listeners.Count - 1; i >= 0; --i)
|
||||
{
|
||||
listeners[i].Invoke(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void Broadcast(List<Action<T>> listeners)
|
||||
{
|
||||
Broadcast(listeners, Instance);
|
||||
}
|
||||
|
||||
private protected virtual void Enable()
|
||||
{
|
||||
// Setting up instance should be last.
|
||||
Instance = (T)this;
|
||||
Broadcast(s_OnEnable);
|
||||
}
|
||||
|
||||
private protected virtual void Disable()
|
||||
{
|
||||
Broadcast(s_OnDisable);
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
private protected virtual void FixedUpdate() => Broadcast(s_OnFixedUpdate);
|
||||
private protected void BroadcastUpdate() => Broadcast(s_OnUpdate);
|
||||
private protected virtual void LateUpdate() => Broadcast(s_OnLateUpdate);
|
||||
|
||||
// OnLoad etc cannot be used on open generic types.
|
||||
internal static void AfterRuntimeLoad()
|
||||
{
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
internal static void AfterScriptReload()
|
||||
{
|
||||
Instance = FindFirstObjectByType<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A behaviour which is driven by a ManagerBehaviour instead of Unity's event system.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The manager type.</typeparam>
|
||||
public abstract class ManagedBehaviour<T> : CustomBehaviour where T : ManagerBehaviour<T>
|
||||
{
|
||||
readonly Action<T> _OnUpdate;
|
||||
readonly Action<T> _OnLateUpdate;
|
||||
readonly Action<T> _OnFixedUpdate;
|
||||
readonly Action<T> _OnEnable;
|
||||
readonly Action<T> _OnDisable;
|
||||
|
||||
/// <summary>
|
||||
/// The Update method called by the manager class.
|
||||
/// </summary>
|
||||
private protected virtual Action<T> OnUpdateMethod => null;
|
||||
|
||||
/// <summary>
|
||||
/// The LateUpdate method called by the manager class.
|
||||
/// </summary>
|
||||
private protected virtual Action<T> OnLateUpdateMethod => null;
|
||||
|
||||
/// <summary>
|
||||
/// The FixedUpdated method called by the manager class.
|
||||
/// </summary>
|
||||
private protected virtual Action<T> OnFixedUpdateMethod => null;
|
||||
|
||||
/// <summary>
|
||||
/// The OnEnable method called by the manager class.
|
||||
/// </summary>
|
||||
private protected virtual Action<T> OnEnableMethod => null;
|
||||
|
||||
/// <summary>
|
||||
/// The OnDisable method called by the manager class.
|
||||
/// </summary>
|
||||
private protected virtual Action<T> OnDisableMethod => null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which caches Actions to avoid allocations.
|
||||
/// </summary>
|
||||
public ManagedBehaviour()
|
||||
{
|
||||
if (OnUpdateMethod != null) _OnUpdate = new(OnUpdateMethod);
|
||||
if (OnLateUpdateMethod != null) _OnLateUpdate = new(OnLateUpdateMethod);
|
||||
if (OnFixedUpdateMethod != null) _OnFixedUpdate = new(OnFixedUpdateMethod);
|
||||
if (OnEnableMethod != null) _OnEnable = new(OnEnableMethod);
|
||||
if (OnDisableMethod != null) _OnDisable = new(OnDisableMethod);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
private protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
UpdateSubscription(listen: true);
|
||||
|
||||
// Trigger OnEnable as it has already passed.
|
||||
if (_OnEnable != null && ManagerBehaviour<T>.Instance != null)
|
||||
{
|
||||
_OnEnable(ManagerBehaviour<T>.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity's OnDisable method. Make sure to call base if overriden.
|
||||
/// </summary>
|
||||
private protected virtual void OnDisable()
|
||||
{
|
||||
UpdateSubscription(listen: false);
|
||||
|
||||
if (_OnDisable != null && ManagerBehaviour<T>.Instance != null)
|
||||
{
|
||||
_OnDisable(ManagerBehaviour<T>.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateSubscription(bool listen)
|
||||
{
|
||||
if (_OnUpdate != null)
|
||||
{
|
||||
ManagerBehaviour<T>.s_OnUpdate.Remove(_OnUpdate);
|
||||
if (listen) ManagerBehaviour<T>.s_OnUpdate.Add(_OnUpdate);
|
||||
}
|
||||
|
||||
if (_OnLateUpdate != null)
|
||||
{
|
||||
ManagerBehaviour<T>.s_OnLateUpdate.Remove(_OnLateUpdate);
|
||||
if (listen) ManagerBehaviour<T>.s_OnLateUpdate.Add(_OnLateUpdate);
|
||||
}
|
||||
|
||||
if (_OnFixedUpdate != null)
|
||||
{
|
||||
ManagerBehaviour<T>.s_OnFixedUpdate.Remove(_OnFixedUpdate);
|
||||
if (listen) ManagerBehaviour<T>.s_OnFixedUpdate.Add(_OnFixedUpdate);
|
||||
}
|
||||
|
||||
if (_OnEnable != null)
|
||||
{
|
||||
ManagerBehaviour<T>.s_OnEnable.Remove(_OnEnable);
|
||||
if (listen) ManagerBehaviour<T>.s_OnEnable.Add(_OnEnable);
|
||||
}
|
||||
|
||||
if (_OnDisable != null)
|
||||
{
|
||||
ManagerBehaviour<T>.s_OnDisable.Remove(_OnDisable);
|
||||
if (listen) ManagerBehaviour<T>.s_OnDisable.Add(_OnDisable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b697363737b2425180c036dc593512e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2119ba437f41246979c9c6b448977c10
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8125db46507e461ea5334eddf20dc1d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#if d_UnityHDRP
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.HighDefinition;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class CustomPassHelpers
|
||||
{
|
||||
internal static List<CustomPassVolume> s_Volumes = new();
|
||||
|
||||
// Create or update Game Object.
|
||||
public static GameObject CreateOrUpdate
|
||||
(
|
||||
Transform parent,
|
||||
string name,
|
||||
bool hide = true
|
||||
)
|
||||
{
|
||||
GameObject gameObject = null;
|
||||
|
||||
// Find the existing custom pass volume.
|
||||
// During recompiles, the reference will be lost so we need to find the game object. It could be limited to
|
||||
// the editor if it is safe to do so, but there is a potential for leaking game objects.
|
||||
if (gameObject == null)
|
||||
{
|
||||
var transform = parent.Find(name);
|
||||
if (transform != null)
|
||||
{
|
||||
gameObject = transform.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
// Create or update the custom pass volume.
|
||||
if (gameObject == null)
|
||||
{
|
||||
gameObject = new()
|
||||
{
|
||||
name = name,
|
||||
hideFlags = hide ? HideFlags.HideAndDontSave : HideFlags.DontSave,
|
||||
};
|
||||
// Place the custom pass under the water renderer since it is easier to find later. Transform.Find can
|
||||
// find inactive game objects unlike GameObject.Find.
|
||||
gameObject.transform.parent = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameObject.hideFlags = hide ? HideFlags.HideAndDontSave : HideFlags.DontSave;
|
||||
gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
// Create or update Custom Pass Volume.
|
||||
public static void CreateOrUpdate<T>
|
||||
(
|
||||
GameObject gameObject,
|
||||
ref T pass,
|
||||
string name,
|
||||
CustomPassInjectionPoint injectionPoint
|
||||
)
|
||||
where T : CustomPass, new()
|
||||
{
|
||||
CustomPassVolume volume = null;
|
||||
gameObject.GetComponents(s_Volumes);
|
||||
|
||||
foreach (var v in s_Volumes)
|
||||
{
|
||||
if (v.injectionPoint == injectionPoint)
|
||||
{
|
||||
volume = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the custom pass volume if it does not exist.
|
||||
if (volume == null)
|
||||
{
|
||||
// It appears that this is currently the only way to add a custom pass.
|
||||
volume = gameObject.AddComponent<CustomPassVolume>();
|
||||
volume.injectionPoint = injectionPoint;
|
||||
volume.isGlobal = true;
|
||||
}
|
||||
|
||||
// Create custom pass.
|
||||
pass ??= new()
|
||||
{
|
||||
name = $"Crest {name}",
|
||||
targetColorBuffer = CustomPass.TargetBuffer.None,
|
||||
targetDepthBuffer = CustomPass.TargetBuffer.None,
|
||||
};
|
||||
|
||||
// Add custom pass.
|
||||
if (!volume.customPasses.Contains(pass))
|
||||
{
|
||||
volume.customPasses.Add(pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03b1e50fbb96a49f1ac7de50cc1f30db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,189 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
/// <summary>
|
||||
/// Unified interface for setting properties on both materials and material property blocks
|
||||
/// </summary>
|
||||
interface IPropertyWrapper
|
||||
{
|
||||
void SetFloat(int param, float value);
|
||||
void SetFloatArray(int param, float[] value);
|
||||
void SetVector(int param, Vector4 value);
|
||||
void SetVectorArray(int param, Vector4[] value);
|
||||
void SetTexture(int param, Texture value);
|
||||
void SetMatrix(int param, Matrix4x4 matrix);
|
||||
void SetInteger(int param, int value);
|
||||
void SetBoolean(int param, bool value);
|
||||
void GetBlock();
|
||||
void SetBlock();
|
||||
}
|
||||
|
||||
static class PropertyWrapperConstants
|
||||
{
|
||||
internal const string k_NoShaderMessage = "Cannot create required material because shader <i>{0}</i> could not be found or loaded."
|
||||
+ " Try right clicking the Crest folder in the Project view and selecting Reimport, and checking for errors.";
|
||||
}
|
||||
|
||||
readonly struct PropertyWrapperBuffer : IPropertyWrapper
|
||||
{
|
||||
public CommandBuffer Buffer { get; }
|
||||
public PropertyWrapperBuffer(CommandBuffer mpb) => Buffer = mpb;
|
||||
public void SetFloat(int param, float value) => Buffer.SetGlobalFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => Buffer.SetGlobalFloatArray(param, value);
|
||||
public void SetTexture(int param, Texture value) => Buffer.SetGlobalTexture(param, value);
|
||||
public void SetVector(int param, Vector4 value) => Buffer.SetGlobalVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => Buffer.SetGlobalVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => Buffer.SetGlobalMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => Buffer.SetGlobalInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => Buffer.SetGlobalInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
}
|
||||
|
||||
readonly struct PropertyWrapperRenderer : IPropertyWrapper
|
||||
{
|
||||
public MaterialPropertyBlock PropertyBlock { get; }
|
||||
public Renderer Renderer { get; }
|
||||
|
||||
public PropertyWrapperRenderer(Renderer renderer, MaterialPropertyBlock block)
|
||||
{
|
||||
Renderer = renderer;
|
||||
PropertyBlock = block;
|
||||
}
|
||||
|
||||
public void SetFloat(int param, float value) => PropertyBlock.SetFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => PropertyBlock.SetFloatArray(param, value);
|
||||
public void SetTexture(int param, Texture value) => PropertyBlock.SetTexture(param, value);
|
||||
public void SetBuffer(int param, ComputeBuffer value) => PropertyBlock.SetBuffer(param, value);
|
||||
public void SetVector(int param, Vector4 value) => PropertyBlock.SetVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => PropertyBlock.SetVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => PropertyBlock.SetMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => PropertyBlock.SetInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => PropertyBlock.SetInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() => Renderer.GetPropertyBlock(PropertyBlock);
|
||||
public void SetBlock() => Renderer.SetPropertyBlock(PropertyBlock);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
readonly struct PropertyWrapperMaterial : IPropertyWrapper
|
||||
{
|
||||
public Material Material { get; }
|
||||
|
||||
public PropertyWrapperMaterial(Material material) => Material = material;
|
||||
public PropertyWrapperMaterial(Shader shader)
|
||||
{
|
||||
Debug.Assert(shader != null, "Crest: PropertyWrapperMaterial: Cannot create required material because shader is null");
|
||||
Material = new(shader);
|
||||
}
|
||||
public PropertyWrapperMaterial(string shaderPath)
|
||||
{
|
||||
var shader = Shader.Find(shaderPath);
|
||||
Debug.AssertFormat(shader != null, $"Crest.PropertyWrapperMaterial: {PropertyWrapperConstants.k_NoShaderMessage}", shaderPath);
|
||||
Material = new(shader);
|
||||
}
|
||||
|
||||
public void SetFloat(int param, float value) => Material.SetFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => Material.SetFloatArray(param, value);
|
||||
public void SetTexture(int param, Texture value) => Material.SetTexture(param, value);
|
||||
public void SetBuffer(int param, ComputeBuffer value) => Material.SetBuffer(param, value);
|
||||
public void SetVector(int param, Vector4 value) => Material.SetVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => Material.SetVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => Material.SetMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => Material.SetInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => Material.SetInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
|
||||
// Non-Interface Methods
|
||||
public void SetKeyword(in LocalKeyword keyword, bool value) => Material.SetKeyword(keyword, value);
|
||||
}
|
||||
|
||||
readonly struct PropertyWrapperMPB : IPropertyWrapper
|
||||
{
|
||||
public MaterialPropertyBlock MaterialPropertyBlock { get; }
|
||||
public PropertyWrapperMPB(MaterialPropertyBlock mpb) => MaterialPropertyBlock = mpb;
|
||||
public void SetFloat(int param, float value) => MaterialPropertyBlock.SetFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => MaterialPropertyBlock.SetFloatArray(param, value);
|
||||
public void SetTexture(int param, Texture value) => MaterialPropertyBlock.SetTexture(param, value);
|
||||
public void SetVector(int param, Vector4 value) => MaterialPropertyBlock.SetVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => MaterialPropertyBlock.SetVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => MaterialPropertyBlock.SetMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => MaterialPropertyBlock.SetInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => MaterialPropertyBlock.SetInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
readonly struct PropertyWrapperCompute : IPropertyWrapper
|
||||
{
|
||||
readonly CommandBuffer _Buffer;
|
||||
readonly ComputeShader _Shader;
|
||||
readonly int _Kernel;
|
||||
|
||||
public PropertyWrapperCompute(CommandBuffer buffer, ComputeShader shader, int kernel)
|
||||
{
|
||||
_Buffer = buffer;
|
||||
_Shader = shader;
|
||||
_Kernel = kernel;
|
||||
}
|
||||
|
||||
public void SetFloat(int param, float value) => _Buffer.SetComputeFloatParam(_Shader, param, value);
|
||||
public void SetFloatArray(int param, float[] value) => _Buffer.SetGlobalFloatArray(param, value);
|
||||
public void SetInteger(int param, int value) => _Buffer.SetComputeIntParam(_Shader, param, value);
|
||||
public void SetBoolean(int param, bool value) => _Buffer.SetComputeIntParam(_Shader, param, value ? 1 : 0);
|
||||
public void SetTexture(int param, Texture value) => _Buffer.SetComputeTextureParam(_Shader, _Kernel, param, value);
|
||||
public void SetTexture(int param, RenderTargetIdentifier value) => _Buffer.SetComputeTextureParam(_Shader, _Kernel, param, value);
|
||||
public void SetBuffer(int param, ComputeBuffer value) => _Buffer.SetComputeBufferParam(_Shader, _Kernel, param, value);
|
||||
public void SetVector(int param, Vector4 value) => _Buffer.SetComputeVectorParam(_Shader, param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => _Buffer.SetComputeVectorArrayParam(_Shader, param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => _Buffer.SetComputeMatrixParam(_Shader, param, value);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
|
||||
// Non-Interface Methods
|
||||
public void SetKeyword(in LocalKeyword keyword, bool value) => _Buffer.SetKeyword(_Shader, keyword, value);
|
||||
public void Dispatch(int x, int y, int z) => _Buffer.DispatchCompute(_Shader, _Kernel, x, y, z);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
readonly struct PropertyWrapperComputeStandalone : IPropertyWrapper
|
||||
{
|
||||
readonly ComputeShader _Shader;
|
||||
readonly int _Kernel;
|
||||
|
||||
public PropertyWrapperComputeStandalone(ComputeShader shader, int kernel)
|
||||
{
|
||||
_Shader = shader;
|
||||
_Kernel = kernel;
|
||||
}
|
||||
|
||||
public void SetFloat(int param, float value) => _Shader.SetFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => _Shader.SetFloats(param, value);
|
||||
public void SetInteger(int param, int value) => _Shader.SetInt(param, value);
|
||||
public void SetBoolean(int param, bool value) => _Shader.SetBool(param, value);
|
||||
public void SetTexture(int param, Texture value) => _Shader.SetTexture(_Kernel, param, value);
|
||||
public void SetBuffer(int param, ComputeBuffer value) => _Shader.SetBuffer(_Kernel, param, value);
|
||||
public void SetConstantBuffer(int param, ComputeBuffer value) => _Shader.SetConstantBuffer(param, value, 0, value.stride);
|
||||
public void SetVector(int param, Vector4 value) => _Shader.SetVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => _Shader.SetVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => _Shader.SetMatrix(param, value);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
|
||||
// Non-Interface Methods
|
||||
public void SetKeyword(in LocalKeyword keyword, bool value) => _Shader.SetKeyword(keyword, value);
|
||||
public void Dispatch(int x, int y, int z) => _Shader.Dispatch(_Kernel, x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2659ec9b44b34272a21ea388cd354d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#if d_UnityURP
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.RenderGraphModule;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class RenderGraphHelper
|
||||
{
|
||||
public struct Handle
|
||||
{
|
||||
RTHandle _RTHandle;
|
||||
TextureHandle _TextureHandle;
|
||||
|
||||
public readonly RTHandle Texture { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _RTHandle ?? _TextureHandle; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Handle(RTHandle handle) => new() { _RTHandle = handle };
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Handle(TextureHandle handle) => new() { _TextureHandle = handle };
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator RTHandle(Handle texture) => texture.Texture;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator TextureHandle(Handle texture) => texture._TextureHandle;
|
||||
}
|
||||
|
||||
static readonly FieldInfo s_RenderContext = typeof(InternalRenderGraphContext).GetField("renderContext", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo s_WrappedContext = typeof(UnsafeGraphContext).GetField("wrappedContext", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo s_FrameData = typeof(RenderingData).GetField("frameData", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static ScriptableRenderContext GetRenderContext(this UnsafeGraphContext unsafeContext)
|
||||
{
|
||||
return (ScriptableRenderContext)s_RenderContext.GetValue((InternalRenderGraphContext)s_WrappedContext.GetValue(unsafeContext));
|
||||
}
|
||||
|
||||
public static ContextContainer GetFrameData(this ref RenderingData renderingData)
|
||||
{
|
||||
return (ContextContainer)s_FrameData.GetValue(renderingData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UNITY_6000_0_OR_NEWER
|
||||
#endif // d_UnityURP
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed778baa1b8804c5ca0074af8b68f7e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,169 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class RenderPipelineCompatibilityHelper
|
||||
{
|
||||
// Taken from:
|
||||
// https://github.com/Unity-Technologies/Graphics/blob/19ec161f3f752db865597374b3ad1b3eaf110097/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs#L588-L634
|
||||
|
||||
/// <summary>
|
||||
/// Return true if handle does not match descriptor
|
||||
/// </summary>
|
||||
/// <param name="handle">RTHandle to check (can be null)</param>
|
||||
/// <param name="descriptor">Descriptor for the RTHandle to match</param>
|
||||
/// <param name="filterMode">Filtering mode of the RTHandle.</param>
|
||||
/// <param name="wrapMode">Addressing mode of the RTHandle.</param>
|
||||
/// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
|
||||
/// <param name="anisoLevel">Anisotropic filtering level.</param>
|
||||
/// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
|
||||
/// <param name="name">Name of the RTHandle.</param>
|
||||
/// <param name="scaled">Check if the RTHandle has auto scaling enabled if not, check the widths and heights</param>
|
||||
/// <returns></returns>
|
||||
internal static bool RTHandleNeedsReAlloc(
|
||||
RTHandle handle,
|
||||
in RenderTextureDescriptor descriptor,
|
||||
FilterMode filterMode,
|
||||
TextureWrapMode wrapMode,
|
||||
bool isShadowMap,
|
||||
int anisoLevel,
|
||||
float mipMapBias,
|
||||
string name,
|
||||
bool scaled)
|
||||
{
|
||||
if (handle == null || handle.rt == null)
|
||||
return true;
|
||||
if (handle.useScaling != scaled)
|
||||
return true;
|
||||
if (!scaled && (handle.rt.width != descriptor.width || handle.rt.height != descriptor.height))
|
||||
return true;
|
||||
return
|
||||
handle.rt.descriptor.depthBufferBits != descriptor.depthBufferBits ||
|
||||
(handle.rt.descriptor.depthBufferBits == (int)DepthBits.None && !isShadowMap && handle.rt.descriptor.graphicsFormat != descriptor.graphicsFormat) ||
|
||||
handle.rt.descriptor.dimension != descriptor.dimension ||
|
||||
handle.rt.descriptor.enableRandomWrite != descriptor.enableRandomWrite ||
|
||||
handle.rt.descriptor.useMipMap != descriptor.useMipMap ||
|
||||
handle.rt.descriptor.autoGenerateMips != descriptor.autoGenerateMips ||
|
||||
handle.rt.descriptor.msaaSamples != descriptor.msaaSamples ||
|
||||
handle.rt.descriptor.bindMS != descriptor.bindMS ||
|
||||
handle.rt.descriptor.useDynamicScale != descriptor.useDynamicScale ||
|
||||
handle.rt.descriptor.memoryless != descriptor.memoryless ||
|
||||
handle.rt.filterMode != filterMode ||
|
||||
handle.rt.wrapMode != wrapMode ||
|
||||
handle.rt.anisoLevel != anisoLevel ||
|
||||
handle.rt.mipMapBias != mipMapBias ||
|
||||
handle.name != name;
|
||||
}
|
||||
|
||||
|
||||
// https://github.com/Unity-Technologies/Graphics/blob/19ec161f3f752db865597374b3ad1b3eaf110097/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs#L666-L695
|
||||
|
||||
/// <summary>
|
||||
/// Re-allocate fixed-size RTHandle if it is not allocated or doesn't match the descriptor
|
||||
/// </summary>
|
||||
/// <param name="handle">RTHandle to check (can be null)</param>
|
||||
/// <param name="descriptor">Descriptor for the RTHandle to match</param>
|
||||
/// <param name="filterMode">Filtering mode of the RTHandle.</param>
|
||||
/// <param name="wrapMode">Addressing mode of the RTHandle.</param>
|
||||
/// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
|
||||
/// <param name="anisoLevel">Anisotropic filtering level.</param>
|
||||
/// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
|
||||
/// <param name="name">Name of the RTHandle.</param>
|
||||
/// <returns></returns>
|
||||
public static bool ReAllocateIfNeeded(
|
||||
ref RTHandle handle,
|
||||
in RenderTextureDescriptor descriptor,
|
||||
FilterMode filterMode = FilterMode.Point,
|
||||
TextureWrapMode wrapMode = TextureWrapMode.Repeat,
|
||||
bool isShadowMap = false,
|
||||
int anisoLevel = 1,
|
||||
float mipMapBias = 0,
|
||||
string name = "")
|
||||
{
|
||||
if (RTHandleNeedsReAlloc(handle, descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name, false))
|
||||
{
|
||||
handle?.Release();
|
||||
handle = RTHandles.Alloc(descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://github.com/Unity-Technologies/Graphics/blob/19ec161f3f752db865597374b3ad1b3eaf110097/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs#L697-L729
|
||||
|
||||
/// <summary>
|
||||
/// Re-allocate dynamically resized RTHandle if it is not allocated or doesn't match the descriptor
|
||||
/// </summary>
|
||||
/// <param name="handle">RTHandle to check (can be null)</param>
|
||||
/// <param name="scaleFactor">Constant scale for the RTHandle size computation.</param>
|
||||
/// <param name="descriptor">Descriptor for the RTHandle to match</param>
|
||||
/// <param name="filterMode">Filtering mode of the RTHandle.</param>
|
||||
/// <param name="wrapMode">Addressing mode of the RTHandle.</param>
|
||||
/// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
|
||||
/// <param name="anisoLevel">Anisotropic filtering level.</param>
|
||||
/// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
|
||||
/// <param name="name">Name of the RTHandle.</param>
|
||||
/// <returns>If the RTHandle should be re-allocated</returns>
|
||||
public static bool ReAllocateIfNeeded(
|
||||
ref RTHandle handle,
|
||||
Vector2 scaleFactor,
|
||||
in RenderTextureDescriptor descriptor,
|
||||
FilterMode filterMode = FilterMode.Point,
|
||||
TextureWrapMode wrapMode = TextureWrapMode.Repeat,
|
||||
bool isShadowMap = false,
|
||||
int anisoLevel = 1,
|
||||
float mipMapBias = 0,
|
||||
string name = "")
|
||||
{
|
||||
var usingConstantScale = handle != null && handle.useScaling && handle.scaleFactor == scaleFactor;
|
||||
if (!usingConstantScale || RTHandleNeedsReAlloc(handle, descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name, true))
|
||||
{
|
||||
handle?.Release();
|
||||
handle = RTHandles.Alloc(scaleFactor, descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://github.com/Unity-Technologies/Graphics/blob/19ec161f3f752db865597374b3ad1b3eaf110097/Packages/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs#L731-L764
|
||||
|
||||
/// <summary>
|
||||
/// Re-allocate dynamically resized RTHandle if it is not allocated or doesn't match the descriptor
|
||||
/// </summary>
|
||||
/// <param name="handle">RTHandle to check (can be null)</param>
|
||||
/// <param name="scaleFunc">Function used for the RTHandle size computation.</param>
|
||||
/// <param name="descriptor">Descriptor for the RTHandle to match</param>
|
||||
/// <param name="filterMode">Filtering mode of the RTHandle.</param>
|
||||
/// <param name="wrapMode">Addressing mode of the RTHandle.</param>
|
||||
/// <param name="isShadowMap">Set to true if the depth buffer should be used as a shadow map.</param>
|
||||
/// <param name="anisoLevel">Anisotropic filtering level.</param>
|
||||
/// <param name="mipMapBias">Bias applied to mipmaps during filtering.</param>
|
||||
/// <param name="name">Name of the RTHandle.</param>
|
||||
/// <returns>If an allocation was done</returns>
|
||||
public static bool ReAllocateIfNeeded(
|
||||
ref RTHandle handle,
|
||||
ScaleFunc scaleFunc,
|
||||
in RenderTextureDescriptor descriptor,
|
||||
FilterMode filterMode = FilterMode.Point,
|
||||
TextureWrapMode wrapMode = TextureWrapMode.Repeat,
|
||||
bool isShadowMap = false,
|
||||
int anisoLevel = 1,
|
||||
float mipMapBias = 0,
|
||||
string name = "")
|
||||
{
|
||||
var usingScaleFunction = handle != null && handle.useScaling && handle.scaleFactor == Vector2.zero;
|
||||
if (!usingScaleFunction || RTHandleNeedsReAlloc(handle, descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name, true))
|
||||
{
|
||||
handle?.Release();
|
||||
handle = RTHandles.Alloc(scaleFunc, descriptor, filterMode, wrapMode, isShadowMap, anisoLevel, mipMapBias, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39dff4a7749404569b14b7395adc361a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.HighDefinition;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
enum RenderPipeline
|
||||
{
|
||||
Legacy,
|
||||
HighDefinition,
|
||||
Universal,
|
||||
}
|
||||
|
||||
sealed class RenderPipelineHelper
|
||||
{
|
||||
public static RenderPipeline RenderPipeline => GraphicsSettings.currentRenderPipeline switch
|
||||
{
|
||||
#if d_UnityHDRP
|
||||
HDRenderPipelineAsset => RenderPipeline.HighDefinition,
|
||||
#endif
|
||||
#if d_UnityURP
|
||||
UniversalRenderPipelineAsset => RenderPipeline.Universal,
|
||||
#endif
|
||||
_ => RenderPipeline.Legacy,
|
||||
};
|
||||
|
||||
// GraphicsSettings.currentRenderPipeline could be from the graphics setting or current quality level.
|
||||
public static bool IsLegacy => GraphicsSettings.currentRenderPipeline == null;
|
||||
|
||||
public static bool IsUniversal
|
||||
{
|
||||
get
|
||||
{
|
||||
#if d_UnityURP
|
||||
return GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsHighDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
#if d_UnityHDRP
|
||||
return GraphicsSettings.currentRenderPipeline is HDRenderPipelineAsset;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00e1b88667d3544fd875d2f9184fdd78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class TextureArrayHelpers
|
||||
{
|
||||
const int k_SmallTextureSize = 4;
|
||||
|
||||
public static Texture2D CreateTexture2D(Color color, TextureFormat format)
|
||||
{
|
||||
var texture = new Texture2D(k_SmallTextureSize, k_SmallTextureSize, format, false, false);
|
||||
var pixels = new Color[texture.height * texture.width];
|
||||
for (var i = 0; i < pixels.Length; i++)
|
||||
{
|
||||
pixels[i] = color;
|
||||
}
|
||||
texture.SetPixels(pixels);
|
||||
texture.Apply();
|
||||
return texture;
|
||||
}
|
||||
|
||||
public static Texture2DArray CreateTexture2DArray(Texture2D texture, int depth)
|
||||
{
|
||||
var array = new Texture2DArray(
|
||||
k_SmallTextureSize, k_SmallTextureSize,
|
||||
depth,
|
||||
texture.format,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
for (var textureArrayIndex = 0; textureArrayIndex < array.depth; textureArrayIndex++)
|
||||
{
|
||||
Graphics.CopyTexture(texture, 0, 0, array, textureArrayIndex, 0);
|
||||
}
|
||||
|
||||
array.Apply();
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18d910d25ea794953b63417c1a72d587
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Based on Unity's ScriptableSingleton but works with Assets and Packages
|
||||
// directory. Works in builds except loading from file so it will need a
|
||||
// reference in the scene for it to instantiate.
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
sealed class FilePath : Attribute
|
||||
{
|
||||
public readonly string _Path;
|
||||
|
||||
public FilePath(string path)
|
||||
{
|
||||
_Path = path;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ScriptableSingleton<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
public static T Instance { get; private set; }
|
||||
|
||||
public ScriptableSingleton()
|
||||
{
|
||||
// Constructor will be called during run-time if there is a asset reference saved
|
||||
// in a scene or preloaded assets.
|
||||
// BUG: There appears to be a Unity bug where this will not happen which required
|
||||
// recreating the asset. Perhaps after renaming the script.
|
||||
Instance = this as T;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
static string GetFilePath()
|
||||
{
|
||||
foreach (var attribute in typeof(T).GetCustomAttributes(inherit: true))
|
||||
{
|
||||
if (attribute is FilePath f)
|
||||
{
|
||||
return f._Path;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
internal static void LoadFromAsset()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// This will trigger the constructor and set Instance. But setting it here first
|
||||
// prevents exceptions when data changes.
|
||||
Instance = AssetDatabase.LoadAssetAtPath<T>(GetFilePath());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b7f4d7de990a4a049d9aa9a442fa866
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "WaveHarmonic.Crest.Shared",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
|
||||
"GUID:457756d89b35d2941b3e7b37b4ece6f1",
|
||||
"GUID:15fc0a57446b3144c949da3e2b9737a9"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"UNITY_2022_3_OR_NEWER"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.modules.xr",
|
||||
"expression": "",
|
||||
"define": "d_UnityModuleVR"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.render-pipelines.high-definition",
|
||||
"expression": "",
|
||||
"define": "d_UnityHDRP"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.render-pipelines.universal",
|
||||
"expression": "",
|
||||
"define": "d_UnityURP"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 056ff2a5b2f124d468c6655552acdca5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a1193a5fe7614861bf6312bb57afe80
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,183 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adaptor layer for XR module. Could be replaced with the following one day:
|
||||
// com.unity.render-pipelines.core/Runtime/Common/XRGraphics.cs
|
||||
|
||||
// Currently, only the horizon line uses it.
|
||||
|
||||
// ENABLE_VR is defined if platform support XR.
|
||||
// d_UnityModuleVR is defined if VR module is installed.
|
||||
// VR module depends on XR module so we only need to check the VR module.
|
||||
#if ENABLE_VR && d_UnityModuleVR
|
||||
#define _XR_ENABLED
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class XRHelpers
|
||||
{
|
||||
// NOTE: This is the same value as Unity, but in the future it could be higher.
|
||||
const int k_MaximumViews = 2;
|
||||
|
||||
#if _XR_ENABLED
|
||||
static readonly List<XRDisplaySubsystem> s_DisplayList = new();
|
||||
|
||||
// Unity only supports one display right now.
|
||||
static XRDisplaySubsystem Display => IsRunning ? s_DisplayList[0] : null;
|
||||
#endif
|
||||
|
||||
static Matrix4x4 LeftEyeProjectionMatrix { get; set; }
|
||||
static Matrix4x4 RightEyeProjectionMatrix { get; set; }
|
||||
static Matrix4x4 LeftEyeViewMatrix { get; set; }
|
||||
static Matrix4x4 RightEyeViewMatrix { get; set; }
|
||||
static Matrix4x4 LeftInverseViewProjectionMatrixGPU { get; set; }
|
||||
static Matrix4x4 RightInverseViewProjectionMatrixGPU { get; set; }
|
||||
|
||||
static class ShaderIDs
|
||||
{
|
||||
public static readonly int s_InverseViewProjection = Shader.PropertyToID("_Crest_InverseViewProjection");
|
||||
public static readonly int s_InverseViewProjectionRight = Shader.PropertyToID("_Crest_InverseViewProjectionRight");
|
||||
}
|
||||
|
||||
internal static bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return XRSettings.enabled;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSinglePass
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return IsRunning && (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced ||
|
||||
XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static Texture2DArray s_WhiteTexture = null;
|
||||
public static Texture2DArray WhiteTexture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_WhiteTexture == null)
|
||||
{
|
||||
s_WhiteTexture = TextureArrayHelpers.CreateTexture2DArray(Texture2D.whiteTexture, k_MaximumViews);
|
||||
s_WhiteTexture.name = "Crest White Texture XR";
|
||||
}
|
||||
return s_WhiteTexture;
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderTextureDescriptor GetRenderTextureDescriptor(Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (camera.stereoEnabled)
|
||||
{
|
||||
return XRSettings.eyeTextureDesc;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// As recommended by Unity, in 2021.2 using SystemInfo.GetGraphicsFormat with DefaultFormat.LDR is
|
||||
// necessary or gamma color space texture is returned:
|
||||
// https://docs.unity3d.com/ScriptReference/Experimental.Rendering.DefaultFormat.html
|
||||
return new(camera.pixelWidth, camera.pixelHeight, SystemInfo.GetGraphicsFormat(UnityEngine.Experimental.Rendering.DefaultFormat.LDR), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetViewProjectionMatrices(Camera camera, int passIndex)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!XRSettings.enabled || IsSinglePass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Not going to use cached values here just in case.
|
||||
Display.GetRenderPass(passIndex, out var xrPass);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrEye);
|
||||
camera.projectionMatrix = xrEye.projection;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void UpdatePassIndex(ref int passIndex)
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.MultiPass)
|
||||
{
|
||||
// Alternate between left and right eye.
|
||||
passIndex += 1;
|
||||
passIndex %= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
passIndex = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
passIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInverseViewProjectionMatrix(Camera camera)
|
||||
{
|
||||
// Have to set these explicitly as the built-in transforms aren't in world-space for the blit function.
|
||||
if (camera.stereoEnabled && IsSinglePass)
|
||||
{
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU);
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjectionRight, RightInverseViewProjectionMatrixGPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Update(Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
SubsystemManager.GetSubsystems(s_DisplayList);
|
||||
#endif
|
||||
|
||||
if (!camera.stereoEnabled || !IsSinglePass)
|
||||
{
|
||||
// Built-in renderer does not provide these matrices.
|
||||
LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(camera.projectionMatrix, false) * camera.worldToCameraMatrix).inverse;
|
||||
return;
|
||||
}
|
||||
|
||||
#if _XR_ENABLED
|
||||
// XR SPI only has one pass by definition.
|
||||
Display.GetRenderPass(renderPassIndex: 0, out var xrPass);
|
||||
// Grab left and right eye.
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrLeftEye);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 1, out var xrRightEye);
|
||||
// Store all the matrices.
|
||||
LeftEyeViewMatrix = xrLeftEye.view;
|
||||
RightEyeViewMatrix = xrRightEye.view;
|
||||
LeftEyeProjectionMatrix = xrLeftEye.projection;
|
||||
RightEyeProjectionMatrix = xrRightEye.projection;
|
||||
LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(LeftEyeProjectionMatrix, false) * LeftEyeViewMatrix).inverse;
|
||||
RightInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(RightEyeProjectionMatrix, false) * RightEyeViewMatrix).inverse;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3893707ad62c4444985948429b69651
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user