From ab1867c74580d250154278d3495b0c34bd47afdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Fri, 5 Jul 2024 00:52:09 -0300 Subject: [PATCH 01/53] feat: add scene transition logic and tests to scene manager --- .../Runtime/AdvancedSceneManager.cs | 127 +++++++++++-- .../Runtime/Interfaces/ISceneManager.cs | 49 +++++ .../Tests/Runtime/SceneLoaderTests.cs | 92 --------- .../Tests/Runtime/SceneLoader_DisposeTests.cs | 174 ------------------ .../Tests/Runtime/SceneManagerTests.cs | 83 ++++++++- .../Runtime/SceneManager_DisposeTests.cs | 51 +++++ .../Runtime/Utilities/SceneTestUtilities.cs | 3 - Packages/manifest.json | 2 +- Packages/packages-lock.json | 2 +- ProjectSettings/ProjectVersion.txt | 4 +- 10 files changed, 295 insertions(+), 292 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 4dab3e5b..999e8061 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -1,11 +1,6 @@ -#if ENABLE_UNITASK && !OVERRIDE_DISABLE_UNITASK -#define USE_UNITASK -#endif -#if USE_UNITASK -using Cysharp.Threading.Tasks; -#endif using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using UnityEngine; @@ -141,6 +136,21 @@ public Scene GetLoadedSceneByName(string name) throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); } + public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) + { + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); + return intermediateSceneReference == null + ? TransitionDirectlyAsync(targetScenes, setIndexActive, linkedSource.Token).RunAndDisposeToken(linkedSource) + : TransitionWithIntermediateAsync(targetScenes, setIndexActive, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); + } + + public async ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default, CancellationToken token = default) + { + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); + var result = await TransitionToScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneInfo, linkedSource.Token).RunAndDisposeToken(linkedSource); + return result == null || result.Length == 0 ? default : result[0]; + } + public async ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); @@ -191,11 +201,7 @@ async ValueTask LoadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, i while (!SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray) && !token.IsCancellationRequested) { -#if USE_UNITASK - await UniTask.Yield(token); -#else - await Task.Yield(); -#endif + await Awaitable.NextFrameAsync(token); progress?.Report(SceneDataUtilities.GetAverageSceneLoadOperationProgress(sceneDataArray)); } @@ -235,15 +241,22 @@ async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, while (!SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray) && !token.IsCancellationRequested) { -#if USE_UNITASK - await UniTask.Yield(token); -#else - await Task.Yield(); -#endif + // Since the unload operation will keep running even after cancelling the task, + // we need to remove these scenes from the unloading scenes list on cancellation. + try + { + await Awaitable.NextFrameAsync(token); + } + catch (OperationCanceledException exception) + { + for (i = 0; i < sceneCount; i++) + { + _unloadingScenes.Remove(sceneDataArray[i]); + } + throw exception; + } } - token.ThrowIfCancellationRequested(); - for (i = 0; i < sceneCount; i++) { tempSceneData = sceneDataArray[i]; @@ -255,5 +268,83 @@ async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, return SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray); } + + async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, CancellationToken token) + { + // If only one scene is loaded, we need to create a temporary scene for transition. + Scene tempScene = default; + if (LoadedSceneCount <= 1) + { + tempScene = SceneManager.CreateScene("temp-transition-scene"); + } + await UnloadSourceSceneAsync(token); + + Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, token: token); + + if (tempScene.IsValid()) + { + await Awaitable.FromAsyncOperation(SceneManager.UnloadSceneAsync(tempScene)); + } + return loadedScenes; + } + + async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + { + Scene loadingScene; + try + { + loadingScene = await LoadSceneAsync(intermediateSceneInfo, token: token); + } + catch + { + throw; + } + + intermediateSceneInfo = new LoadSceneInfoScene(loadingScene); + +#if UNITY_2023_2_OR_NEWER + LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None).FirstOrDefault(l => l.gameObject.scene == loadingScene); +#else + LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(l => l.gameObject.scene == loadingScene); +#endif + return loadingBehavior + ? await TransitionWithIntermediateLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, loadingBehavior, token) + : await TransitionWithIntermediateNoLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, token); + } + + async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + { + LoadingProgress progress = loadingBehavior.Progress; + while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) + await Awaitable.NextFrameAsync(token); + + await UnloadSourceSceneAsync(token); + + Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, progress, token); + progress.SetState(LoadingState.TargetSceneLoaded); + + while (progress.State != LoadingState.TransitionComplete && !token.IsCancellationRequested) + await Awaitable.NextFrameAsync(token); + + await UnloadSceneAsync(intermediateSceneInfo, token); + return loadedScenes; + } + + async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + { + await UnloadSourceSceneAsync(token); + Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, token: token); + await UnloadSceneAsync(intermediateSceneInfo, token); + return loadedScenes; + } + + ValueTask UnloadSourceSceneAsync(CancellationToken token) + { + Scene sourceScene = GetActiveScene(); + if (!sourceScene.IsValid()) + return default; + + return UnloadSceneAsync(new LoadSceneInfoScene(sourceScene), token); + } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index ee43a713..103dbb86 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -46,6 +46,55 @@ public interface ISceneManager : IDisposable /// Scene to be enabled as the active scene. void SetActiveScene(Scene scene); + /// + /// Triggers a transition to a group of scens. + /// It will transition from the current active scene () + /// to a group of scenes (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to all scenes that will be transitioned to. + /// + /// + /// Index of the scene in the to be set as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + + /// + /// Triggers a scene transition. + /// It will transition from the current active scene () + /// to the target scene (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load the target scene.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to the scene that's going to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with the loaded scene as the result. + ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + /// /// Loads all scenes provided by the array in parallel. /// You may also provide the desired index to set as the active scene through the parameter. diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs index 0db13432..5274d697 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs @@ -39,98 +39,6 @@ public class SceneLoaderTests : SceneTestBase new SceneLoaderCoroutine(SceneTestEnvironment.SceneManagers[0]), }; - [UnityTest] - public IEnumerator LoadScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) - { - int sceneCount = targetScenes.Length; - var loadedScenes = new List(sceneCount); - - sceneLoader.Manager.SceneLoaded += sceneLoaded; - sceneLoader.LoadScenes(targetScenes, 0); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - - Assert.AreEqual(sceneCount, loadedScenes.Count); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator LoadScene([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader) - { - yield return LoadFirstScene(sceneLoader); - } - - [UnityTest] - public IEnumerator UnloadScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) - { - int sceneCount = targetScenes.Length; - sceneLoader.LoadScenes(targetScenes); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => sceneLoader.Manager.LoadedSceneCount == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - Assert.AreEqual(sceneCount, sceneLoader.Manager.LoadedSceneCount); - - var unloadedScenes = new List(sceneCount); - - sceneLoader.Manager.SceneUnloaded += sceneUnloaded; - sceneLoader.UnloadScenes(targetScenes); - - watch.Restart(); - yield return new WaitUntil(() => unloadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; - - Assert.AreEqual(sceneCount, unloadedScenes.Count); - Assert.AreEqual(0, sceneLoader.Manager.LoadedSceneCount); - - void sceneUnloaded(Scene scene) - { - unloadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator UnloadScene([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader) - { - yield return LoadFirstScene(sceneLoader); - - var loadedScene = sceneLoader.Manager.GetLastLoadedScene(); - - sceneLoader.Manager.SceneUnloaded += sceneUnloaded; - - Scene unloadedScene = default; - sceneLoader.UnloadScene(new LoadSceneInfoName(SceneBuilder.SceneNames[1])); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => unloadedScene.handle != 0 && !unloadedScene.isLoaded || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; - - Assert.Less(watch.ElapsedMilliseconds, SceneTestEnvironment.DefaultTimeout); - Assert.AreEqual(loadedScene, unloadedScene); - Assert.IsFalse(unloadedScene.isLoaded); - - void sceneUnloaded(Scene scene) - { - unloadedScene = scene; - } - } - [UnityTest] public IEnumerator TransitionToScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs index 8826cdde..bddc00da 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs @@ -23,60 +23,6 @@ public class SceneLoader_DisposeTests : SceneTestBase () => new SceneLoaderCoroutine(new AdvancedSceneManager()), }; - [UnityTest] - public IEnumerator Dispose_Simple([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc) - { - ISceneLoader loader = loaderCreateFunc(); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - - [UnityTest] - public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc) - { - ISceneLoader loader = loaderCreateFunc(); - loader.LoadScene(new LoadSceneInfoName(SceneBuilder.SceneNames[1])); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - - [UnityTest] - public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) - { - ISceneLoader loader = loaderCreateFunc(); - loader.LoadScenes(targetScenes); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - - [UnityTest] - public IEnumerator Dispose_DuringUnloadScene([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc) - { - ISceneLoader loader = loaderCreateFunc(); - yield return SceneLoaderTests.LoadFirstScene(loader); - - loader.UnloadScene(new LoadSceneInfoScene(loader.Manager.GetLastLoadedScene())); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - - [UnityTest] - public IEnumerator Dispose_DuringUnloadScenes([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) - { - ISceneLoader loader = loaderCreateFunc(); - int sceneCount = targetScenes.Length; - loader.LoadScenes(targetScenes); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loader.Manager.LoadedSceneCount == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - loader.UnloadScenes(targetScenes); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - [UnityTest] public IEnumerator Dispose_DuringTransitionToScene([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) { @@ -100,126 +46,6 @@ public IEnumerator Dispose_DuringTransitionToScenes([ValueSource(nameof(_sceneLo } #if ENABLE_UNITASK - [UnityTest] - public IEnumerator Dispose_DuringLoadSceneAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - SceneLoaderType type = GetSceneLoaderType(loader); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).LoadSceneAsync(targetScene).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).LoadSceneAsync(targetScene), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).LoadSceneAsync(targetScene).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); - - [UnityTest] - public IEnumerator Dispose_DuringLoadScenesAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - SceneLoaderType type = GetSceneLoaderType(loader); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).LoadScenesAsync(targetScenes).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).LoadScenesAsync(targetScenes), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).LoadScenesAsync(targetScenes).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); - - [UnityTest] - public IEnumerator Dispose_DuringUnloadSceneAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - await SceneLoaderTests.LoadFirstScene(loader); - - SceneLoaderType type = GetSceneLoaderType(loader); - ILoadSceneInfo sceneInfo = new LoadSceneInfoScene(loader.Manager.GetLastLoadedScene()); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).UnloadSceneAsync(sceneInfo).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).UnloadSceneAsync(sceneInfo), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).UnloadSceneAsync(sceneInfo).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); - - [UnityTest] - public IEnumerator Dispose_DuringUnloadScenesAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - int sceneCount = targetScenes.Length; - loader.LoadScenes(targetScenes); - - await UniTask.WaitUntil(() => loader.Manager.LoadedSceneCount == sceneCount).TimeoutWithoutException(TimeSpan.FromMilliseconds(SceneTestEnvironment.DefaultTimeout)); - - SceneLoaderType type = GetSceneLoaderType(loader); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).UnloadScenesAsync(targetScenes).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).UnloadScenesAsync(targetScenes), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).UnloadScenesAsync(targetScenes).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); - [UnityTest] public IEnumerator Dispose_DuringTransitionToSceneAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) => UniTask.ToCoroutine(async () => { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index ba0c6bfa..e154dcdd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -12,6 +12,13 @@ namespace MyGameDevTools.SceneLoading.Tests { public partial class SceneManagerTests : SceneTestBase { + public static readonly ILoadSceneInfo[] LoadingSceneInfos = new ILoadSceneInfo[] + { + null, + new LoadSceneInfoName(SceneBuilder.SceneNames[3]), + new LoadSceneInfoName(SceneBuilder.SceneNames[0]), + }; + static readonly bool[] _setActiveParameterValues = new bool[] { true, false }; static readonly int[] _setIndexActiveParameterValues = new int[] { -1, 1 }; @@ -104,7 +111,7 @@ public IEnumerator SetActive_NotThroughManager([ValueSource(typeof(SceneTestEnvi Assert.Throws(() => manager.SetActiveScene(loadedScene)); - yield return SceneManager.UnloadSceneAsync(SceneBuilder.SceneNames[1]); + yield return SceneManager.UnloadSceneAsync(loadedScene); void assignLoadedScene(Scene scene, LoadSceneMode loadSceneMode) { @@ -340,6 +347,71 @@ public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nam Assert.Throws(() => wait.MoveNext()); } + [UnityTest] + public IEnumerator TransitionToScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + yield return LoadFirstScene(manager); + + int sceneCount = targetScenes.Length; + + var task = manager.TransitionToScenesAsync(targetScenes, 0, loadingScene).AsTask(); + + yield return new WaitTask(task); + + Scene[] loadedScenes = task.Result; + Assert.AreEqual(sceneCount, loadedScenes.Length); + + yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); + } + + [UnityTest] + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + yield return LoadFirstScene(manager); + + var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); + + yield return new WaitTask(task); + + Scene loadedScene = task.Result; + Assert.AreEqual(loadedScene, manager.GetActiveScene()); + + yield return new WaitUntil(() => manager.TotalSceneCount == 1); + } + + [UnityTest] + public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + int expectedLoadedScenes = loadingScene == null ? 1 : 2; + // If there's no loading scene, the scene loader will create a temporary scene + // for the transition, and will unload it after the transition is complete. + int expectedUnloadedScenes = 1; + + int unloadedScenesCount = 0; + + // The temporary scene unload does not go through the ISceneManager + SceneManager.sceneUnloaded += sceneUnloaded; + + var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); + + yield return new WaitTask(task); + + Scene loadedScene = task.Result; + + SceneManager.sceneUnloaded -= sceneUnloaded; + + Assert.AreEqual(loadedScene, manager.GetActiveScene()); + Assert.AreEqual(expectedLoadedScenes, _scenesLoaded); + Assert.AreEqual(expectedUnloadedScenes, unloadedScenesCount); + + yield return new WaitUntil(() => manager.TotalSceneCount == 1); + + void sceneUnloaded(Scene scene) + { + unloadedScenesCount++; + } + } + [UnityTest] public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { @@ -356,6 +428,15 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron Assert.Zero(manager.LoadedSceneCount); } + /// + /// Required to test transition some scenarios. + /// + public static WaitTask LoadFirstScene(ISceneManager sceneManager) + { + var task = sceneManager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true).AsTask(); + return new WaitTask(task); + } + void ReportSceneActivation(Scene previousScene, Scene newScene) { _scenesActivated++; diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index 3acf247b..4350af62 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using System; using System.Collections; +using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TestTools; @@ -66,5 +67,55 @@ public IEnumerator Dipose_DuringUnloadScenes([ValueSource(nameof(_sceneManagerCr yield return waitTask; Assert.True(waitTask.Task.IsCanceled); } + + [UnityTest] + public IEnumerator Dispose_DuringTransitionToSceneAsync([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + async Awaitable Test() + { + ISceneManager manager = managerCreateFunc(); + await SceneManagerTests.LoadFirstScene(manager).Task; + + var task = manager.TransitionToSceneAsync(targetScene, loadingScene); + manager.Dispose(); + + bool canceled = false; + try + { + await task; + } + catch (OperationCanceledException) + { + canceled = true; + } + Assert.True(canceled); + } + return Test(); + } + + [UnityTest] + public IEnumerator Dispose_DuringTransitionToScenesAsync([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + async Awaitable Test() + { + ISceneManager manager = managerCreateFunc(); + await SceneManagerTests.LoadFirstScene(manager).Task; + + var task = manager.TransitionToScenesAsync(targetScenes, 0, loadingScene); + manager.Dispose(); + + bool canceled = false; + try + { + await task; + } + catch (OperationCanceledException) + { + canceled = true; + } + Assert.True(canceled); + } + return Test(); + } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index 221078b2..d6218138 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -16,9 +16,6 @@ public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) lastScene = sceneManager.GetLastLoadedScene(); } - while (sceneManager.LoadedSceneCount > 0) - yield return new WaitUntil(() => sceneManager.LoadedSceneCount == 0); - Assert.Zero(sceneManager.LoadedSceneCount); Assert.False(sceneManager.GetActiveScene().IsValid()); } diff --git a/Packages/manifest.json b/Packages/manifest.json index 1deefd27..8704490a 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -5,7 +5,7 @@ "com.unity.addressables": "2.1.0", "com.unity.feature.development": "1.0.2", "com.unity.ide.visualstudio": "2.0.22", - "com.unity.timeline": "1.8.6", + "com.unity.timeline": "1.8.7", "com.unity.ugui": "2.0.0", "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 6c509788..c63e6ab5 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -130,7 +130,7 @@ "url": "https://packages.unity.com" }, "com.unity.timeline": { - "version": "1.8.6", + "version": "1.8.7", "depth": 0, "source": "registry", "dependencies": { diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 250548d6..b85cebb6 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.4f1 -m_EditorVersionWithRevision: 6000.0.4f1 (b5d5d06b038a) +m_EditorVersion: 6000.0.7f1 +m_EditorVersionWithRevision: 6000.0.7f1 (7dd95c051e11) From eae8de022aa1af53bc20ce518fd287e1fabe7388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Fri, 5 Jul 2024 00:54:21 -0300 Subject: [PATCH 02/53] feat: remove all scene loader logic --- .../Runtime/Interfaces/ISceneLoader.cs | 198 -------------- .../Runtime/Interfaces/ISceneLoader.cs.meta | 11 - .../Runtime/Interfaces/ISceneLoaderAsync.cs | 198 -------------- .../Interfaces/ISceneLoaderAsync.cs.meta | 11 - .../Runtime/SceneLoaders.meta | 8 - .../Runtime/SceneLoaders/SceneLoaderAsync.cs | 244 ----------------- .../SceneLoaders/SceneLoaderAsync.cs.meta | 11 - .../SceneLoaders/SceneLoaderCoroutine.cs | 131 --------- .../SceneLoaders/SceneLoaderCoroutine.cs.meta | 11 - .../SceneLoaders/SceneLoaderUniTask.cs | 134 --------- .../SceneLoaders/SceneLoaderUniTask.cs.meta | 11 - .../Tests/Runtime/SceneLoaderTests.cs | 258 ------------------ .../Tests/Runtime/SceneLoaderTests.cs.meta | 11 - .../Tests/Runtime/SceneLoader_DisposeTests.cs | 124 --------- .../Runtime/SceneLoader_DisposeTests.cs.meta | 2 - .../Tests/Runtime/SceneManagerTests.cs | 2 +- 16 files changed, 1 insertion(+), 1364 deletions(-) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs deleted file mode 100644 index 140b82c4..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading -{ - /// - /// Interface to standardize scene loading operations. - /// - public interface ISceneLoader : IDisposable - { - /// - /// Reference to the , responsible for performing the scene loading operations. - /// You can retrieve the manager to listen to the , and events. - /// - ISceneManager Manager { get; } - - /// - /// Triggers a transition to a group of scenes from the active scene. - /// It will transition from the current active scene () - /// to a group of scenes (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Triggers a transition to the target scene from the active scene. - /// It will transition from the current active scene () - /// to the target scene (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load the target scene.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Triggers a transition to a group of scenes from another group of scenes. - /// It will transition from the provided group of scenes () - /// to a group of scenes (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload all provided scenes.
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// A reference to all scenes that will be unloaded in the transition. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Triggers a transition to the target scene from a group of scens. - /// It will transition from the provided group of scenes () - /// to the target scene (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload all provided scenes.
- /// 3. Load the target scene.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to all scenes that will be unloaded in the transition. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Triggers a transition to a group of scenes from all loaded scenes. - /// It will transition from all loaded scenes - /// to a group of scenes (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload all loaded scenes.
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Triggers a transition to the target scene from all loaded scenes. - /// It will transition from the provided group of scenes () - /// to the target scene (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload all provided scenes.
- /// 3. Load the target scene.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to all scenes that will be unloaded in the transition. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null); - - /// - /// Unloads all the scenes from the current scene stack. - /// - /// - /// Reference to all scenes that will be unloaded. - /// - void UnloadScenes(ILoadSceneInfo[] sceneInfos); - - /// - /// Unloads the given scene from the current scene stack. - /// - /// - /// Reference to the desired scene to be unloaded. - /// - void UnloadScene(ILoadSceneInfo sceneInfo); - - /// - /// Loads all scenes additively on top of the current scene stack, optionally marking one of them as the active scene. - /// - /// - /// Reference to all scenes that will be loaded. - /// - /// - /// Which of the scenes should be marked as active? Default is -1. - /// - void LoadScenes(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1); - - /// - /// Loads a scene additively on top of the current scene stack, optionally marking it as the active scene - /// (). - /// - /// - /// Reference to the scene that's going to be loaded. - /// - /// Should the loaded scene be marked as active? Equivalent to calling . - void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false); - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs.meta deleted file mode 100644 index 32c3b870..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8be1d8db5fbb3ad47ac9419fc7b34a73 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs deleted file mode 100644 index bab84fc8..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs +++ /dev/null @@ -1,198 +0,0 @@ -#if ENABLE_UNITASK -using Cysharp.Threading.Tasks; -#endif -using System; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading -{ - /// - /// Interface to standardize async scene loading operations. - /// can be a or an awaitable type that returns , such as - /// . - /// The can also be a coroutine or an awaitable type that returns a array. - /// - public interface ISceneLoaderAsync : ISceneLoader - { - /// - /// Async version of the - /// - /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncSceneArray TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the . - /// - /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncScene TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the - /// - /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// A reference to all scenes that will be unloaded in the transition. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncSceneArray TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the - /// - /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to all scenes that will be unloaded in the transition. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncScene TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the - /// - /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// Index of the scene in the to be set as the active scene. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncSceneArray TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the - /// - /// - /// A reference to the scene that's going to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The transition operation. - /// - TAsyncScene TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default); - - /// - /// Async version of the . - /// - /// - /// Reference to all scenes that will be loaded. - /// - /// - /// Which of the scenes should be marked as active? Default is -1. - /// - /// - /// Optional reference to report the scene group loading progress (ranging from 0 to 1). - /// - /// - /// The loading operation. - /// - TAsyncSceneArray LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null); - - /// - /// Async version of the . - /// - /// - /// Reference to the scene that's going to be loaded. - /// - /// - /// Should the loaded scene be marked as active? Equivalent to calling . - /// - /// - /// Optional reference to report the scene loading progress (ranging from 0 to 1). - /// - /// - /// The loading operation. - /// - TAsyncScene LoadSceneAsync(ILoadSceneInfo sceneReference, bool setActive = false, IProgress progress = null); - - /// - /// Async version of the - /// - /// - /// Reference to all scenes to be unloaded. - /// - /// - /// The unloading operation. - /// - TAsyncSceneArray UnloadScenesAsync(ILoadSceneInfo[] sceneReferences); - - /// - /// Async version of the . - /// - /// - /// Reference to the desired scene to be unloaded. - /// - /// - /// The unloading operation. - /// - TAsyncScene UnloadSceneAsync(ILoadSceneInfo sceneReference); - } - - /// - /// Convenience interface to standardize async scene loading operations. - /// You can use the to yield return inside coroutines. - /// - public interface ISceneLoaderCoroutine : ISceneLoaderAsync, WaitTask> { } - - /// - /// Convenience interface to standardize async scene loading operations. - /// - public interface ISceneLoaderAsync : ISceneLoaderAsync, ValueTask> { } - -#if ENABLE_UNITASK - /// - /// Convenience interface to standardize async scene loading operations. - /// - public interface ISceneLoaderUniTask : ISceneLoaderAsync, UniTask> { } -#endif -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs.meta deleted file mode 100644 index 8db11ef7..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneLoaderAsync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 76562df7de1a93f4893ccdfbbbe7a33c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders.meta deleted file mode 100644 index da8640b5..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 753ac881f93949248b22da115e8da97f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs deleted file mode 100644 index eed00125..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs +++ /dev/null @@ -1,244 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading -{ - public readonly struct SceneLoaderAsync : ISceneLoaderAsync - { - public ISceneManager Manager => _manager; - - readonly ISceneManager _manager; - readonly CancellationTokenSource _lifetimeTokenSource; - - public SceneLoaderAsync(ISceneManager manager) - { - _manager = manager ?? throw new ArgumentNullException("Cannot create a scene loader with a null Scene Manager"); - _lifetimeTokenSource = new CancellationTokenSource(); - } - - public void Dispose() - { - _lifetimeTokenSource.Cancel(); - _lifetimeTokenSource.Dispose(); - _manager.Dispose(); - } - - public void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesAsync(targetScenes, setIndexActive, intermediateSceneInfo).AsTask().Forget(HandleFireAndForgetException); - } - - public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default) - { - TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo).AsTask().Forget(HandleFireAndForgetException); - } - - public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo).Forget(HandleFireAndForgetException); - } - - public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo).Forget(HandleFireAndForgetException); - } - - public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo).Forget(HandleFireAndForgetException); - } - - public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo).Forget(HandleFireAndForgetException); - } - - public void UnloadScenes(ILoadSceneInfo[] sceneInfos) - { - UnloadScenesAsync(sceneInfos).AsTask().Forget(HandleFireAndForgetException); - } - - public void UnloadScene(ILoadSceneInfo sceneInfo) - { - UnloadSceneAsync(sceneInfo).AsTask().Forget(HandleFireAndForgetException); - } - - public void LoadScenes(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1) - { - LoadScenesAsync(sceneInfos, setIndexActive, null).AsTask().Forget(HandleFireAndForgetException); - } - - public void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false) - { - LoadSceneAsync(sceneInfo, setActive, null).AsTask().Forget(HandleFireAndForgetException); - } - - public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - Scene activeScene = _manager.GetActiveScene(); - ILoadSceneInfo[] fromScenes = activeScene.IsValid() ? new ILoadSceneInfo[] { new LoadSceneInfoScene(activeScene) } : null; - return intermediateSceneReference == null - ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) - : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); - } - - public async ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default) - { - var result = await TransitionToScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneInfo); - return result == null || result.Length == 0 ? default : result[0]; - } - - public ValueTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return intermediateSceneReference == null - ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) - : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); - } - - public async ValueTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) - { - var result = await TransitionToScenesFromScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, fromScenes, 0, intermediateSceneReference); - return result == null || result.Length == 0 ? default : result[0]; - } - - public ValueTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - ILoadSceneInfo[] fromScenes = GetAllLoadedSceneInfos(); - return intermediateSceneReference == null - ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) - : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); - } - - public async ValueTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneReference = null) - { - var result = await TransitionToScenesFromAllAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneReference); - return result == null || result.Length == 0 ? default : result[0]; - } - - public ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null) - { - return _manager.LoadScenesAsync(sceneReferences, setIndexActive, progress, _lifetimeTokenSource.Token); - } - - public ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null) - { - return _manager.LoadSceneAsync(sceneInfo, setActive, progress, _lifetimeTokenSource.Token); - } - - public ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneReferences) - { - return _manager.UnloadScenesAsync(sceneReferences, _lifetimeTokenSource.Token); - } - - public ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo) - { - return _manager.UnloadSceneAsync(sceneInfo, _lifetimeTokenSource.Token); - } - - async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, CancellationToken token) - { - // If only one scene is loaded, we need to create a temporary scene for transition. - Scene tempScene = default; - if (SceneManager.sceneCount <= 1) - { - tempScene = SceneManager.CreateScene("temp-transition-scene"); - } - await UnloadSourceScenesAsync(fromScenes, token); - - Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, token: token); - - if (tempScene.IsValid()) - { - _ = SceneManager.UnloadSceneAsync(tempScene); - } - return loadedScenes; - } - - async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) - { - Scene loadingScene; - try - { - loadingScene = await _manager.LoadSceneAsync(intermediateSceneInfo, token: token); - } - catch - { - throw; - } - - intermediateSceneInfo = new LoadSceneInfoScene(loadingScene); - -#if UNITY_2023_2_OR_NEWER - LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None).FirstOrDefault(l => l.gameObject.scene == loadingScene); -#else - LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(l => l.gameObject.scene == loadingScene); -#endif - return loadingBehavior - ? await TransitionWithIntermediateLoadingAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo, loadingBehavior, token) - : await TransitionWithIntermediateNoLoadingAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo, token); - } - - async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) - { - LoadingProgress progress = loadingBehavior.Progress; - while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) - await Task.Yield(); - - token.ThrowIfCancellationRequested(); - - await UnloadSourceScenesAsync(fromScenes, token); - - Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, progress, token); - progress.SetState(LoadingState.TargetSceneLoaded); - - while (progress.State != LoadingState.TransitionComplete && !token.IsCancellationRequested) - await Task.Yield(); - - token.ThrowIfCancellationRequested(); - - _manager.UnloadSceneAsync(intermediateSceneInfo, token).Forget(HandleFireAndForgetException); - return loadedScenes; - } - - async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) - { - await UnloadSourceScenesAsync(fromScenes, token); - Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, token: token); - _manager.UnloadSceneAsync(intermediateSceneInfo, token).Forget(HandleFireAndForgetException); - return loadedScenes; - } - - ValueTask UnloadSourceScenesAsync(ILoadSceneInfo[] fromScenes, CancellationToken token) - { - if (fromScenes == null || fromScenes.Length == 0) - return default; - - return _manager.UnloadScenesAsync(fromScenes, token); - } - - ILoadSceneInfo[] GetAllLoadedSceneInfos() - { - int count = _manager.LoadedSceneCount; - ILoadSceneInfo[] loadedSceneInfos = new ILoadSceneInfo[count]; - for (int i = 0; i < count; i++) - { - loadedSceneInfos[i] = new LoadSceneInfoScene(_manager.GetLoadedSceneAt(i)); - } - return loadedSceneInfos; - } - - void HandleFireAndForgetException(Exception exception) - { - Debug.LogWarningFormat("[SceneLoader] An exception was caught during a fire and forget task. Usually this can be caused due to internal task cancellation on exiting playmode. If that's not the case, investigate for issues on the async scene operations. Exception:\n{0}", exception); - } - - public override string ToString() - { - return $"Scene Loader [Async] with {_manager.GetType().Name}"; - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs.meta deleted file mode 100644 index d6fdea44..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f802bf78b50900147ac7055768fe668d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs deleted file mode 100644 index 11d5afb0..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading -{ - public readonly struct SceneLoaderCoroutine : ISceneLoaderCoroutine - { - public ISceneManager Manager => _sceneLoaderAsync.Manager; - - readonly ISceneLoaderAsync _sceneLoaderAsync; - - public SceneLoaderCoroutine(ISceneManager sceneManager) - { - if (sceneManager == null) - { - throw new ArgumentNullException($"Cannot create a {nameof(SceneLoaderCoroutine)} with a null {nameof(ISceneManager)}.", nameof(sceneManager)); - } - _sceneLoaderAsync = new SceneLoaderAsync(sceneManager); - } - - public void Dispose() - { - _sceneLoaderAsync.Dispose(); - } - - public void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesAsync(targetScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo); - } - - public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo); - } - - public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo); - } - - public void UnloadScenes(ILoadSceneInfo[] sceneInfos) - { - UnloadScenesAsync(sceneInfos); - } - - public void UnloadScene(ILoadSceneInfo sceneInfo) - { - UnloadSceneAsync(sceneInfo); - } - - public void LoadScenes(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1) - { - LoadScenesAsync(sceneInfos, setIndexActive); - } - - public void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false) - { - LoadSceneAsync(sceneInfo, setActive); - } - - public WaitTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToScenesAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask()); - } - - public WaitTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToSceneAsync(targetSceneReference, intermediateSceneReference).AsTask()); - } - - public WaitTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference).AsTask()); - } - - public WaitTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToSceneFromScenesAsync(targetSceneReference, fromScenes, intermediateSceneReference).AsTask()); - } - - public WaitTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask()); - } - - public WaitTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) - { - return new WaitTask(_sceneLoaderAsync.TransitionToSceneFromAllAsync(targetSceneReference, intermediateSceneReference).AsTask()); - } - - public WaitTask UnloadScenesAsync(ILoadSceneInfo[] sceneReferences) - { - return new WaitTask(_sceneLoaderAsync.UnloadScenesAsync(sceneReferences).AsTask()); - } - - public WaitTask UnloadSceneAsync(ILoadSceneInfo sceneReference) - { - return new WaitTask(_sceneLoaderAsync.UnloadSceneAsync(sceneReference).AsTask()); - } - - public WaitTask LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null) - { - return new WaitTask(_sceneLoaderAsync.LoadScenesAsync(sceneReferences, setIndexActive, progress).AsTask()); - } - - public WaitTask LoadSceneAsync(ILoadSceneInfo sceneReference, bool setActive = false, IProgress progress = null) - { - return new WaitTask(_sceneLoaderAsync.LoadSceneAsync(sceneReference, setActive, progress).AsTask()); - } - - public override string ToString() - { - return $"Scene Loader [Coroutine] with {_sceneLoaderAsync.Manager.GetType().Name}"; - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs.meta deleted file mode 100644 index 2192d993..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c9843db71fb949748b0128e1754f6b03 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs deleted file mode 100644 index c2c9d9c3..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs +++ /dev/null @@ -1,134 +0,0 @@ -#if ENABLE_UNITASK -using System; -using Cysharp.Threading.Tasks; -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading -{ - public readonly struct SceneLoaderUniTask : ISceneLoaderUniTask - { - public ISceneManager Manager => _sceneLoaderAsync.Manager; - - readonly ISceneLoaderAsync _sceneLoaderAsync; - - public SceneLoaderUniTask(ISceneManager sceneManager) - { - if (sceneManager == null) - { - throw new ArgumentNullException($"Cannot create a {nameof(SceneLoaderUniTask)} with a null {nameof(ISceneManager)}.", nameof(sceneManager)); - } - _sceneLoaderAsync = new SceneLoaderAsync(sceneManager); - } - - public void Dispose() - { - _sceneLoaderAsync.Dispose(); - } - - public void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesAsync(targetScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo); - } - - public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo); - } - - public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo); - } - - public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) - { - TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo); - } - - public void UnloadScenes(ILoadSceneInfo[] sceneInfos) - { - UnloadScenesAsync(sceneInfos); - } - - public void UnloadScene(ILoadSceneInfo sceneInfo) - { - UnloadSceneAsync(sceneInfo); - } - - public void LoadScenes(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1) - { - LoadScenesAsync(sceneInfos, setIndexActive); - } - - public void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false) - { - LoadSceneAsync(sceneInfo, setActive); - } - - public UniTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToScenesAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToSceneAsync(targetSceneReference, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToSceneFromScenesAsync(targetSceneReference, fromScenes, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) - { - return _sceneLoaderAsync.TransitionToSceneFromAllAsync(targetSceneReference, intermediateSceneReference).AsTask().AsUniTask(); - } - - public UniTask UnloadScenesAsync(ILoadSceneInfo[] sceneReferences) - { - return _sceneLoaderAsync.UnloadScenesAsync(sceneReferences).AsTask().AsUniTask(); - } - - public UniTask UnloadSceneAsync(ILoadSceneInfo sceneReference) - { - return _sceneLoaderAsync.UnloadSceneAsync(sceneReference).AsTask().AsUniTask(); - } - - public UniTask LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null) - { - return _sceneLoaderAsync.LoadScenesAsync(sceneReferences, setIndexActive, progress).AsTask().AsUniTask(); - } - - public UniTask LoadSceneAsync(ILoadSceneInfo sceneReference, bool setActive = false, IProgress progress = null) - { - return _sceneLoaderAsync.LoadSceneAsync(sceneReference, setActive, progress).AsTask().AsUniTask(); - } - - public override string ToString() - { - return $"Scene Loader [UniTask] with {_sceneLoaderAsync.Manager.GetType().Name}"; - } - } -} -#endif \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs.meta deleted file mode 100644 index f3e3e4c0..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3cc4fc000345d644c8e1deeafaca3961 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs deleted file mode 100644 index 5274d697..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs +++ /dev/null @@ -1,258 +0,0 @@ -#if ENABLE_UNITASK -#endif -using NUnit.Framework; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - enum SceneLoaderType - { - Async, -#if ENABLE_UNITASK - UniTask, -#endif - Coroutine, - } - - public class SceneLoaderTests : SceneTestBase - { - // Here we don't need to test multiple load scene infos, since that is already done - // in the scene manager tests. - public static readonly ILoadSceneInfo[] LoadingSceneInfos = new ILoadSceneInfo[] - { - null, - new LoadSceneInfoName(SceneBuilder.SceneNames[3]), - new LoadSceneInfoName(SceneBuilder.SceneNames[0]), - }; - - static readonly ISceneLoader[] _sceneLoaders = new ISceneLoader[] - { - new SceneLoaderAsync(SceneTestEnvironment.SceneManagers[0]), -#if ENABLE_UNITASK - new SceneLoaderUniTask(SceneTestEnvironment.SceneManagers[0]), -#endif - new SceneLoaderCoroutine(SceneTestEnvironment.SceneManagers[0]), - }; - - [UnityTest] - public IEnumerator TransitionToScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - yield return LoadFirstScene(sceneLoader); - - int sceneCount = targetScenes.Length; - if (loadingScene != null) - sceneCount++; - - var loadedScenes = new List(sceneCount); - - sceneLoader.Manager.SceneLoaded += sceneLoaded; - sceneLoader.TransitionToScenes(targetScenes, 0, loadingScene); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - - Assert.AreEqual(sceneCount, loadedScenes.Count); - - yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == sceneCount); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator TransitionToScenesFromScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - int sceneCount = targetScenes.Length; - - var loadedScenes = new List(sceneCount); - - sceneLoader.Manager.SceneLoaded += sceneLoaded; - sceneLoader.LoadScenes(targetScenes); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneCount += loadingScene == null ? 0 : 1; - - var unloadedScenes = new List(sceneCount); - sceneLoader.Manager.SceneUnloaded += sceneUnloaded; - - loadedScenes.Clear(); - sceneLoader.TransitionToScenesFromScenes(targetScenes, targetScenes, 0, loadingScene); - - watch.Restart(); - yield return new WaitUntil(() => (loadedScenes.Count == sceneCount && unloadedScenes.Count == sceneCount) || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; - - yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == targetScenes.Length); - - Assert.AreEqual(sceneCount, loadedScenes.Count); - Assert.AreEqual(sceneCount, unloadedScenes.Count); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - - void sceneUnloaded(Scene scene) - { - unloadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator TransitionToScenesFromAll([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - int sceneCount = targetScenes.Length; - - var loadedScenes = new List(sceneCount); - - sceneLoader.Manager.SceneLoaded += sceneLoaded; - sceneLoader.LoadScenes(targetScenes); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneCount += loadingScene == null ? 0 : 1; - - var unloadedScenes = new List(sceneCount); - sceneLoader.Manager.SceneUnloaded += sceneUnloaded; - - loadedScenes.Clear(); - sceneLoader.TransitionToScenesFromAll(targetScenes, 0, loadingScene); - - watch.Restart(); - yield return new WaitUntil(() => (loadedScenes.Count == sceneCount && unloadedScenes.Count == sceneCount) || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; - - yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == targetScenes.Length); - - Assert.AreEqual(sceneCount, loadedScenes.Count); - Assert.AreEqual(sceneCount, unloadedScenes.Count); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - - void sceneUnloaded(Scene scene) - { - unloadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator Transition([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - yield return LoadFirstScene(sceneLoader); - - List loadedScenes = new(); - int expectedScenes = loadingScene == null ? 1 : 2; - sceneLoader.Manager.SceneLoaded += sceneLoaded; - - sceneLoader.TransitionToScene(targetScene, loadingScene); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScenes.Count == expectedScenes || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - - Assert.AreEqual(loadedScenes[expectedScenes - 1], sceneLoader.Manager.GetActiveScene()); - - yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == 1); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - } - - [UnityTest] - public IEnumerator Transition_NoSourceScene([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - List loadedScenes = new(); - List unloadedScenes = new(); - int expectedLoadedScenes = loadingScene == null ? 1 : 2; - // If there's no loading scene, the scene loader will create a temporary scene - // for the transition, and will unload it after the transition is complete. - int expectedUnloadedScenes = 1; - - sceneLoader.Manager.SceneLoaded += sceneLoaded; - // The temporary scene unload does not go through the ISceneManager - SceneManager.sceneUnloaded += sceneUnloaded; - - sceneLoader.TransitionToScene(targetScene, loadingScene); - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => (loadedScenes.Count == expectedLoadedScenes && unloadedScenes.Count == expectedUnloadedScenes) || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - SceneManager.sceneUnloaded -= sceneUnloaded; - - Assert.AreEqual(loadedScenes[expectedLoadedScenes - 1], sceneLoader.Manager.GetActiveScene()); - Assert.AreEqual(expectedUnloadedScenes, unloadedScenes.Count); - - yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == 1); - - void sceneLoaded(Scene scene) - { - loadedScenes.Add(scene); - } - - void sceneUnloaded(Scene scene) - { - unloadedScenes.Add(scene); - } - } - - /// - /// Required to test transition scenarios, otherwise the initial (test) scene would be unloaded and stop the tests. - /// - public static IEnumerator LoadFirstScene(ISceneLoader sceneLoader) - { - sceneLoader.Manager.SceneLoaded += sceneLoaded; - sceneLoader.LoadScene(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true); - Scene loadedScene = default; - - var watch = new Stopwatch(); - watch.Start(); - yield return new WaitUntil(() => loadedScene.IsValid() && loadedScene.isLoaded || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); - watch.Stop(); - - sceneLoader.Manager.SceneLoaded -= sceneLoaded; - - Assert.AreEqual(loadedScene.name, SceneBuilder.SceneNames[1]); - Assert.AreEqual(loadedScene, SceneManager.GetActiveScene()); - - void sceneLoaded(Scene scene) - { - loadedScene = scene; - } - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs.meta deleted file mode 100644 index 6151cab5..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoaderTests.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e251a454cd075084f9d1f26da82fa383 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs deleted file mode 100644 index bddc00da..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs +++ /dev/null @@ -1,124 +0,0 @@ -#if ENABLE_UNITASK -using Cysharp.Threading.Tasks; -#endif -using NUnit.Framework; -using System; -using System.Collections; -using System.Diagnostics; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - public class SceneLoader_DisposeTests : SceneTestBase - { - // Note: These functions must create new scene managers to correctly test the dispose flow - static readonly Func[] _sceneLoaderCreateFuncs = new Func[] - { - () => new SceneLoaderAsync(new AdvancedSceneManager()), -#if ENABLE_UNITASK - () => new SceneLoaderUniTask(new AdvancedSceneManager()), -#endif - () => new SceneLoaderCoroutine(new AdvancedSceneManager()), - }; - - [UnityTest] - public IEnumerator Dispose_DuringTransitionToScene([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - ISceneLoader loader = loaderCreateFunc(); - yield return SceneLoaderTests.LoadFirstScene(loader); - - loader.TransitionToScene(targetScene, loadingScene); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - - [UnityTest] - public IEnumerator Dispose_DuringTransitionToScenes([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - ISceneLoader loader = loaderCreateFunc(); - yield return SceneLoaderTests.LoadFirstScene(loader); - - loader.TransitionToScenes(targetScenes, 0, loadingScene); - Assert.DoesNotThrow(loader.Dispose); - yield return null; - } - -#if ENABLE_UNITASK - [UnityTest] - public IEnumerator Dispose_DuringTransitionToSceneAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - await SceneLoaderTests.LoadFirstScene(loader); - - SceneLoaderType type = GetSceneLoaderType(loader); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).TransitionToSceneAsync(targetScene, loadingScene).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).TransitionToSceneAsync(targetScene, loadingScene), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).TransitionToSceneAsync(targetScene, loadingScene).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); - - [UnityTest] - public IEnumerator Dispose_DuringTransitionToScenesAsync([ValueSource(nameof(_sceneLoaderCreateFuncs))] Func loaderCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(typeof(SceneLoaderTests), nameof(SceneLoaderTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) => UniTask.ToCoroutine(async () => - { - ISceneLoader loader = loaderCreateFunc(); - await SceneLoaderTests.LoadFirstScene(loader); - - SceneLoaderType type = GetSceneLoaderType(loader); - - UniTask task = default; - task = type switch - { - SceneLoaderType.Async => ((ISceneLoaderAsync)loader).TransitionToScenesAsync(targetScenes, 0, loadingScene).AsTask().AsUniTask(), - SceneLoaderType.UniTask => ((ISceneLoaderUniTask)loader).TransitionToScenesAsync(targetScenes, 0, loadingScene), - SceneLoaderType.Coroutine => ((ISceneLoaderCoroutine)loader).TransitionToScenesAsync(targetScenes, 0, loadingScene).Task.AsUniTask(), - _ => throw new NotImplementedException($"Type {type} was not implemented"), - }; - loader.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - }); -#endif - - SceneLoaderType GetSceneLoaderType(ISceneLoader loader) - { - if (loader is SceneLoaderAsync) - return SceneLoaderType.Async; -#if ENABLE_UNITASK - else if (loader is SceneLoaderUniTask) - return SceneLoaderType.UniTask; -#endif - else if (loader is SceneLoaderCoroutine) - return SceneLoaderType.Coroutine; - - throw new Exception("Unexpected ISceneLoader type"); - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs.meta deleted file mode 100644 index d88aa41b..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneLoader_DisposeTests.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e05b4c8d6f189c641a7e50831262ab57 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index e154dcdd..1c3f25bf 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -383,7 +383,7 @@ public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof( public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { int expectedLoadedScenes = loadingScene == null ? 1 : 2; - // If there's no loading scene, the scene loader will create a temporary scene + // If there's no loading scene, the scene manager will create a temporary scene // for the transition, and will unload it after the transition is complete. int expectedUnloadedScenes = 1; From fb01f1889d1d619f1cfe1aae3f8669b81afe3822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 27 Aug 2024 19:28:30 -0300 Subject: [PATCH 03/53] update project to Unity 6 Preview (16f1) --- Packages/manifest.json | 2 +- Packages/packages-lock.json | 20 ++++++++++---------- ProjectSettings/ProjectVersion.txt | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Packages/manifest.json b/Packages/manifest.json index 8704490a..5ac968f5 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -2,7 +2,7 @@ "dependencies": { "com.cysharp.unitask": "2.5.0", "com.mygamedevtools.script-template": "3.4.0", - "com.unity.addressables": "2.1.0", + "com.unity.addressables": "2.2.2", "com.unity.feature.development": "1.0.2", "com.unity.ide.visualstudio": "2.0.22", "com.unity.timeline": "1.8.7", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index c63e6ab5..ee988a22 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -21,11 +21,11 @@ "url": "https://package.openupm.com" }, "com.unity.addressables": { - "version": "2.1.0", + "version": "2.2.2", "depth": 0, "source": "registry", "dependencies": { - "com.unity.scriptablebuildpipeline": "2.1.3", + "com.unity.scriptablebuildpipeline": "2.1.4", "com.unity.modules.assetbundle": "1.0.0", "com.unity.modules.imageconversion": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", @@ -55,15 +55,15 @@ "source": "builtin", "dependencies": { "com.unity.ide.visualstudio": "2.0.22", - "com.unity.ide.rider": "3.0.28", + "com.unity.ide.rider": "3.0.31", "com.unity.editorcoroutines": "1.0.0", "com.unity.performance.profile-analyzer": "1.2.2", - "com.unity.test-framework": "1.4.4", - "com.unity.testtools.codecoverage": "1.2.5" + "com.unity.test-framework": "1.4.5", + "com.unity.testtools.codecoverage": "1.2.6" } }, "com.unity.ide.rider": { - "version": "3.0.28", + "version": "3.0.31", "depth": 1, "source": "registry", "dependencies": { @@ -95,7 +95,7 @@ "url": "https://packages.unity.com" }, "com.unity.scriptablebuildpipeline": { - "version": "2.1.3", + "version": "2.1.4", "depth": 1, "source": "registry", "dependencies": {}, @@ -109,7 +109,7 @@ "url": "https://packages.unity.com" }, "com.unity.test-framework": { - "version": "1.4.4", + "version": "1.4.5", "depth": 1, "source": "registry", "dependencies": { @@ -120,7 +120,7 @@ "url": "https://packages.unity.com" }, "com.unity.testtools.codecoverage": { - "version": "1.2.5", + "version": "1.2.6", "depth": 1, "source": "registry", "dependencies": { @@ -134,9 +134,9 @@ "depth": 0, "source": "registry", "dependencies": { + "com.unity.modules.audio": "1.0.0", "com.unity.modules.director": "1.0.0", "com.unity.modules.animation": "1.0.0", - "com.unity.modules.audio": "1.0.0", "com.unity.modules.particlesystem": "1.0.0" }, "url": "https://packages.unity.com" diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index b85cebb6..9a443f11 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.7f1 -m_EditorVersionWithRevision: 6000.0.7f1 (7dd95c051e11) +m_EditorVersion: 6000.0.16f1 +m_EditorVersionWithRevision: 6000.0.16f1 (ae37dbaefed8) From 3ce18b3b4050030a2e503c32d3e085fb8d71d907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 27 Aug 2024 20:03:09 -0300 Subject: [PATCH 04/53] add scene result struct --- .../Runtime/Structs/SceneResult.cs | 64 +++++++++++++++++++ .../Runtime/Structs/SceneResult.cs.meta | 2 + 2 files changed, 66 insertions(+) create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs new file mode 100644 index 00000000..a74ebac6 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs @@ -0,0 +1,64 @@ +using System.Text; +using UnityEngine.SceneManagement; + +namespace MyGameDevTools.SceneLoading +{ + public readonly struct SceneResult + { + readonly Scene[] _sceneArray; + readonly Scene _singleScene; + + public SceneResult(Scene[] sceneArray) + { + if (sceneArray == null || sceneArray.Length == 0) + throw new System.ArgumentException("Cannot create a `SceneResult` struct out of a null or empty scene array.", nameof(sceneArray)); + + _sceneArray = sceneArray; + _singleScene = sceneArray[0]; + } + + public SceneResult(Scene scene) + { + _sceneArray = null; + _singleScene = scene; + } + + public readonly Scene GetScene() + { + return _singleScene; + } + + public readonly Scene[] GetScenes() + { + return _sceneArray; + } + + public static implicit operator Scene(SceneResult sceneResult) => sceneResult.GetScene(); + public static implicit operator Scene[](SceneResult sceneResult) => sceneResult.GetScenes(); + + public override string ToString() + { + int sceneCount = (_sceneArray == null || _sceneArray.Length == 0) ? 1 : _sceneArray.Length; + + StringBuilder builder = new("{ "); + if (sceneCount == 1) + { + builder.Append(_singleScene.name); + } + else + { + for (int i = 0; i < sceneCount; i++) + { + if (i > 0) + { + builder.Append(","); + } + builder.Append(_sceneArray[i].name); + } + } + + builder.Append(" }"); + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs.meta new file mode 100644 index 00000000..adfdff51 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: aa1ed57359c7aa74a927bc6940b5e68a \ No newline at end of file From b9d60b419498514cc54a65dfc2da71ec0a0ae228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 27 Aug 2024 20:24:52 -0300 Subject: [PATCH 05/53] unify scene operation return types --- .../Runtime/AdvancedSceneManager.cs | 51 ++++++++---------- .../Runtime/Interfaces/ISceneManager.cs | 12 ++--- .../Runtime/Structs/SceneResult.cs | 17 +++--- .../Tests/Runtime/SceneManagerTests.cs | 54 +++++++++---------- .../Runtime/SceneManager_CancellationTests.cs | 9 ++-- .../Runtime/SceneManager_DisposeTests.cs | 8 +-- .../Runtime/Utilities/SceneTestUtilities.cs | 3 +- 7 files changed, 75 insertions(+), 79 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 999e8061..18843c69 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -136,7 +136,7 @@ public Scene GetLoadedSceneByName(string name) throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); } - public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) + public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); return intermediateSceneReference == null @@ -144,46 +144,41 @@ public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, : TransitionWithIntermediateAsync(targetScenes, setIndexActive, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); } - public async ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default, CancellationToken token = default) + public ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - var result = await TransitionToScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneInfo, linkedSource.Token).RunAndDisposeToken(linkedSource); - return result == null || result.Length == 0 ? default : result[0]; + return TransitionToScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneInfo, linkedSource.Token); } - public async ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return await LoadScenesAsync_Internal(sceneInfos, setIndexActive, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); + return LoadScenesAsync_Internal(sceneInfos, setIndexActive, progress, linkedSource.Token); } - public async ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default) + public ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default) { sceneInfo = sceneInfo ?? throw new NullReferenceException($"[{GetType().Name}] Provided scene info is null."); CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - Scene[] loadedScenes = await LoadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, setActive ? 0 : -1, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); - - return loadedScenes != null && loadedScenes.Length > 0 ? loadedScenes[0] : default; + return LoadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, setActive ? 0 : -1, progress, linkedSource.Token); } - public async ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default) + public ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return await UnloadScenesAsync_Internal(sceneInfos, linkedSource.Token).RunAndDisposeToken(linkedSource); + return UnloadScenesAsync_Internal(sceneInfos, linkedSource.Token); } - public async ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default) + public ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default) { sceneInfo = sceneInfo ?? throw new ArgumentNullException(nameof(sceneInfo), $"[{GetType().Name}] Provided scene info is null."); CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - Scene[] unloadedScenes = await UnloadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, linkedSource.Token).RunAndDisposeToken(linkedSource); - - return unloadedScenes != null && unloadedScenes.Length > 0 ? unloadedScenes[0] : default; + return UnloadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, linkedSource.Token); } - async ValueTask LoadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, int setIndexActive, IProgress progress, CancellationToken token) + async ValueTask LoadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, int setIndexActive, IProgress progress, CancellationToken token) { int scenesToLoad = sceneInfos.Length; if (sceneInfos == null || scenesToLoad == 0) @@ -218,10 +213,10 @@ async ValueTask LoadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, i if (setIndexActive >= 0) SetActiveScene(sceneDataArray[setIndexActive].SceneReference); - return SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray); + return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); } - async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) + async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) { if (sceneInfos == null || sceneInfos.Length == 0) throw new ArgumentException($"[{GetType().Name}] Provided scene group is null or empty.", nameof(sceneInfos)); @@ -266,10 +261,10 @@ async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, SetActiveScene(GetLastLoadedScene()); } - return SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray); + return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); } - async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, CancellationToken token) + async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, CancellationToken token) { // If only one scene is loaded, we need to create a temporary scene for transition. Scene tempScene = default; @@ -285,10 +280,10 @@ async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, { await Awaitable.FromAsyncOperation(SceneManager.UnloadSceneAsync(tempScene)); } - return loadedScenes; + return new SceneResult(loadedScenes); } - async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { Scene loadingScene; try @@ -312,7 +307,7 @@ async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] target : await TransitionWithIntermediateNoLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, token); } - async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) @@ -327,18 +322,18 @@ async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] await Awaitable.NextFrameAsync(token); await UnloadSceneAsync(intermediateSceneInfo, token); - return loadedScenes; + return new SceneResult(loadedScenes); } - async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { await UnloadSourceSceneAsync(token); Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, token: token); await UnloadSceneAsync(intermediateSceneInfo, token); - return loadedScenes; + return new SceneResult(loadedScenes); } - ValueTask UnloadSourceSceneAsync(CancellationToken token) + ValueTask UnloadSourceSceneAsync(CancellationToken token) { Scene sourceScene = GetActiveScene(); if (!sourceScene.IsValid()) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index 103dbb86..1540a967 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -70,7 +70,7 @@ public interface ISceneManager : IDisposable /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); /// /// Triggers a scene transition. @@ -93,7 +93,7 @@ public interface ISceneManager : IDisposable /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with the loaded scene as the result. - ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); /// /// Loads all scenes provided by the array in parallel. @@ -107,7 +107,7 @@ public interface ISceneManager : IDisposable /// A with all scenes loaded. /// When scene info group is null, empty or the setIndexName is bigger than the scene length. /// When the provided scene info group fails to produce valid load scene operations. - ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default); + ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default); /// /// Loads a scene referenced by the , optionally enabling it as the active scene. @@ -120,7 +120,7 @@ public interface ISceneManager : IDisposable /// A with the loaded scene as the result. /// When scene info is null. /// When the provided scene info fails to produce a valid load scene operation. - ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default); + ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default); /// /// Unloads all scenes provided by the array in parallel. @@ -134,7 +134,7 @@ public interface ISceneManager : IDisposable /// /// When scene info group is null or empty. /// When the provided scene info group fails to produce valid unload scene operations. - ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default); + ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default); /// /// Unloads a scene referenced by the . @@ -148,7 +148,7 @@ public interface ISceneManager : IDisposable /// /// When scene info is null. /// When the provided scene info fails to produce a valid unload scene operation. - ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default); + ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default); /// /// Gets the current active scene in this instance. diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs index a74ebac6..9ee45171 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs @@ -38,23 +38,26 @@ public readonly Scene[] GetScenes() public override string ToString() { + if (!_singleScene.IsValid()) + return "Empty SceneResult"; + int sceneCount = (_sceneArray == null || _sceneArray.Length == 0) ? 1 : _sceneArray.Length; StringBuilder builder = new("{ "); if (sceneCount == 1) { builder.Append(_singleScene.name); + builder.Append(" }"); + return builder.ToString(); } - else + + for (int i = 0; i < sceneCount; i++) { - for (int i = 0; i < sceneCount; i++) + if (i > 0) { - if (i > 0) - { - builder.Append(","); - } - builder.Append(_sceneArray[i].name); + builder.Append(", "); } + builder.Append(_sceneArray[i].name); } builder.Append(" }"); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 1c3f25bf..bab80ef6 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -94,7 +94,7 @@ public IEnumerator InitializationScene_Unload() ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); - WaitTask waitTask = default; + WaitTask waitTask = default; Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadSceneAsync(new LoadSceneInfoScene(loadedScene)).AsTask())); yield return waitTask; @@ -131,9 +131,9 @@ public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment { var loadTask = manager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true).AsTask(); - yield return new WaitTask(loadTask); + yield return new WaitTask(loadTask); - var loadedScene = loadTask.Result; + Scene loadedScene = loadTask.Result; var managerActiveScene = manager.GetActiveScene(); Assert.True(loadedScene.IsValid()); @@ -150,7 +150,7 @@ public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironmen [UnityTest] public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1])).AsTask()); + yield return new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1])).AsTask()); Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } @@ -177,10 +177,10 @@ public IEnumerator LoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(S Scene eventScene = default; manager.SceneLoaded += setEventScene; - yield return new WaitTask(loadTask); + yield return new WaitTask(loadTask); manager.SceneLoaded -= setEventScene; - var loadedScene = loadTask.Result; + Scene loadedScene = loadTask.Result; Assert.AreEqual(1, manager.LoadedSceneCount); Assert.That(setActive ? loadedScene == manager.GetActiveScene() : loadedScene != manager.GetActiveScene()); @@ -206,10 +206,10 @@ public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof( Assert.AreEqual(0, progress.Value); - yield return new WaitTask(loadTask); + yield return new WaitTask(loadTask); manager.SceneLoaded -= reportSceneLoaded; - var loadedScenes = loadTask.Result; + Scene[] loadedScenes = loadTask.Result; Assert.AreEqual(1, progress.Value); Assert.AreEqual(scenesToLoad, loadedScenes.Length); @@ -229,7 +229,7 @@ public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive, progress).AsTask()); + yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive, progress).AsTask()); Assert.AreEqual(1, progress.Value); } @@ -242,7 +242,7 @@ public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), for (int i = 0; i < length; i++) { var loadTask = manager.LoadSceneAsync(sceneInfos[i], setActive).AsTask(); - yield return new WaitTask(loadTask); + yield return new WaitTask(loadTask); loadedScenes[i] = loadTask.Result; } @@ -264,14 +264,14 @@ public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), name var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(sceneName), false).AsTask()); + var wait = new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(sceneName), false).AsTask()); Assert.Throws(() => wait.MoveNext()); } [UnityTest] public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) { - yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive).AsTask()); + yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive).AsTask()); Scene eventScene = default; manager.SceneUnloaded += setEventScene; @@ -279,10 +279,10 @@ public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof var workingScene = manager.GetLastLoadedScene(); var task = manager.UnloadSceneAsync(new LoadSceneInfoScene(workingScene)).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); manager.SceneUnloaded -= setEventScene; - var unloadedScene = task.Result; + Scene unloadedScene = task.Result; Assert.AreEqual(workingScene, unloadedScene); Assert.AreEqual(workingScene, eventScene); @@ -300,18 +300,18 @@ public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { var loadTask = manager.LoadScenesAsync(sceneInfos, setIndexActive).AsTask(); - yield return new WaitTask(loadTask); - var loadedSceneHandles = loadTask.Result.Select(s => s.handle).ToArray(); + yield return new WaitTask(loadTask); + var loadedSceneHandles = loadTask.Result.GetScenes().Select(s => s.handle).ToArray(); int scenesToUnload = sceneInfos.Length; var reportedScenes = new List(scenesToUnload); manager.SceneUnloaded += reportSceneUnloaded; var task = manager.UnloadScenesAsync(sceneInfos).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); manager.SceneUnloaded -= reportSceneUnloaded; - var unloadedScenes = task.Result; + Scene[] unloadedScenes = task.Result; Assert.AreEqual(scenesToUnload, unloadedScenes.Length); Assert.AreEqual(scenesToUnload, reportedScenes.Count); @@ -343,7 +343,7 @@ public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nam var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = new WaitTask(manager.UnloadSceneAsync(new LoadSceneInfoName(sceneName)).AsTask()); + var wait = new WaitTask(manager.UnloadSceneAsync(new LoadSceneInfoName(sceneName)).AsTask()); Assert.Throws(() => wait.MoveNext()); } @@ -356,7 +356,7 @@ public IEnumerator TransitionToScenes([ValueSource(typeof(SceneTestEnvironment), var task = manager.TransitionToScenesAsync(targetScenes, 0, loadingScene).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); @@ -371,7 +371,7 @@ public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof( var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); Scene loadedScene = task.Result; Assert.AreEqual(loadedScene, manager.GetActiveScene()); @@ -394,7 +394,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); Scene loadedScene = task.Result; @@ -417,13 +417,13 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron { var task = manager.LoadSceneAsync(sceneInfo).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); - var scene = task.Result; + Scene scene = task.Result; task = manager.UnloadSceneAsync(new LoadSceneInfoScene(scene)).AsTask(); - yield return new WaitTask(task); + yield return new WaitTask(task); Assert.Zero(manager.LoadedSceneCount); } @@ -431,10 +431,10 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron /// /// Required to test transition some scenarios. /// - public static WaitTask LoadFirstScene(ISceneManager sceneManager) + public static WaitTask LoadFirstScene(ISceneManager sceneManager) { var task = sceneManager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true).AsTask(); - return new WaitTask(task); + return new WaitTask(task); } void ReportSceneActivation(Scene previousScene, Scene newScene) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index a2baa611..d2f013ae 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -1,7 +1,6 @@ using NUnit.Framework; using System.Collections; using System.Threading; -using UnityEngine.SceneManagement; using UnityEngine.TestTools; namespace MyGameDevTools.SceneLoading.Tests @@ -12,7 +11,7 @@ public class SceneManager_CancellationTests : SceneTestBase public IEnumerator Cancellation_DuringLoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.That(waitTask.Task.IsCompleted); @@ -23,7 +22,7 @@ public IEnumerator Cancellation_DuringLoadScene([ValueSource(typeof(SceneTestEnv public IEnumerator Cancellation_DuringLoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -34,7 +33,7 @@ public IEnumerator Cancellation_DuringLoadScenes([ValueSource(typeof(SceneTestEn public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); yield return waitTask; waitTask = new(manager.UnloadSceneAsync(sceneInfo, token: tokenSource.Token).AsTask()); @@ -48,7 +47,7 @@ public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestE public IEnumerator Cancellation_DuringUnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); yield return waitTask; waitTask = new(manager.UnloadScenesAsync(sceneInfos, token: tokenSource.Token).AsTask()); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index 4350af62..d31032b3 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -26,7 +26,7 @@ public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func< public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); manager.Dispose(); yield return waitTask; Assert.That(waitTask.Task.IsCompleted); @@ -36,7 +36,7 @@ public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneManagerCrea public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -46,7 +46,7 @@ public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneManagerCre public IEnumerator Dipose_DuringUnloadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); yield return waitTask; waitTask = new(manager.UnloadSceneAsync(sceneInfo).AsTask()); @@ -59,7 +59,7 @@ public IEnumerator Dipose_DuringUnloadScene([ValueSource(nameof(_sceneManagerCre public IEnumerator Dipose_DuringUnloadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); yield return waitTask; waitTask = new(manager.UnloadScenesAsync(sceneInfos).AsTask()); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index d6218138..f6aacb3b 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -1,4 +1,3 @@ -using UnityEngine; using System.Collections; using NUnit.Framework; using UnityEngine.SceneManagement; @@ -12,7 +11,7 @@ public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) var lastScene = sceneManager.GetLastLoadedScene(); while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneManager.UnloadSceneAsync(new LoadSceneInfoScene(lastScene)).AsTask()); + yield return new WaitTask(sceneManager.UnloadSceneAsync(new LoadSceneInfoScene(lastScene)).AsTask()); lastScene = sceneManager.GetLastLoadedScene(); } From 07636f460dafc91de1817288b697e3d60b008a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Thu, 19 Dec 2024 16:45:50 -0300 Subject: [PATCH 06/53] update to Unity 6000.0.31f1 --- .../Runtime/Structs/SceneResult.cs | 41 +++++++++++++++++++ .../Runtime/Utilities/WaitTask.cs | 19 +++++++++ Packages/packages-lock.json | 8 ++-- ProjectSettings/ProjectVersion.txt | 4 +- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs index 9ee45171..6cc3f304 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs @@ -64,4 +64,45 @@ public override string ToString() return builder.ToString(); } } + + public readonly struct SceneParameter + { + readonly ILoadSceneInfo[] _loadSceneInfoArray; + readonly ILoadSceneInfo _singleLoadSceneInfo; + readonly int _setIndexActive; + + public SceneParameter(ILoadSceneInfo[] loadSceneInfos, int setIndexActive = -1) + { + _loadSceneInfoArray = loadSceneInfos; + _singleLoadSceneInfo = loadSceneInfos[0]; + _setIndexActive = setIndexActive; + } + + public SceneParameter(ILoadSceneInfo loadSceneInfo, bool setActive = false) + { + _loadSceneInfoArray = null; + _singleLoadSceneInfo = loadSceneInfo; + _setIndexActive = setActive ? 0 : -1; + } + + public readonly ILoadSceneInfo GetLoadSceneInfo() + { + return _singleLoadSceneInfo; + } + + public readonly ILoadSceneInfo[] GetLoadSceneInfos() + { + return _loadSceneInfoArray; + } + + public readonly bool ShouldSetActive() + { + return _setIndexActive == 0; + } + + public readonly int GetIndexActive() + { + return _setIndexActive; + } + } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs index e58830e3..32e321d2 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs @@ -27,4 +27,23 @@ public bool MoveNext() public void Reset() { } } + + public readonly struct WaitValueTask : IEnumerator + { + public object Current => null; + + public readonly ValueTask ValueTask; + + public WaitValueTask(ValueTask valueTask) + { + ValueTask = valueTask; + } + + public bool MoveNext() + { + return !ValueTask.IsCompleted && !ValueTask.IsCanceled && !ValueTask.IsFaulted; + } + + public void Reset() { } + } } \ No newline at end of file diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index ee988a22..3df8411a 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -25,13 +25,13 @@ "depth": 0, "source": "registry", "dependencies": { - "com.unity.scriptablebuildpipeline": "2.1.4", + "com.unity.profiling.core": "1.0.2", "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.profiling.core": "1.0.2" + "com.unity.scriptablebuildpipeline": "2.1.4", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0" }, "url": "https://packages.unity.com" }, diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index 9a443f11..ffdee9b2 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.16f1 -m_EditorVersionWithRevision: 6000.0.16f1 (ae37dbaefed8) +m_EditorVersion: 6000.0.31f1 +m_EditorVersionWithRevision: 6000.0.31f1 (a206c360e2a8) From cff86d321daeee61bd5c674819119d4b9f959b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Fri, 20 Dec 2024 14:04:33 -0300 Subject: [PATCH 07/53] unify multiple and single scene parameter functions --- .../Runtime/AdvancedSceneManager.cs | 70 +++++--------- .../Runtime/Interfaces/ISceneManager.cs | 94 +++++-------------- .../Runtime/Structs/SceneParameters.cs | 43 +++++++++ .../Runtime/Structs/SceneParameters.cs.meta | 2 + .../Runtime/Structs/SceneResult.cs | 41 -------- .../Tests/Runtime/SceneManagerTests.cs | 38 ++++---- .../Runtime/SceneManager_CancellationTests.cs | 14 +-- .../Runtime/SceneManager_DisposeTests.cs | 19 ++-- .../Runtime/Utilities/SceneTestUtilities.cs | 2 +- 9 files changed, 128 insertions(+), 195 deletions(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 18843c69..e89644fb 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -136,55 +136,31 @@ public Scene GetLoadedSceneByName(string name) throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); } - public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) + public ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); return intermediateSceneReference == null - ? TransitionDirectlyAsync(targetScenes, setIndexActive, linkedSource.Token).RunAndDisposeToken(linkedSource) - : TransitionWithIntermediateAsync(targetScenes, setIndexActive, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); + ? TransitionDirectlyAsync(sceneParameters, linkedSource.Token).RunAndDisposeToken(linkedSource) + : TransitionWithIntermediateAsync(sceneParameters, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); } - public ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default, CancellationToken token = default) + public ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return TransitionToScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneInfo, linkedSource.Token); + return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token); } - public ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return LoadScenesAsync_Internal(sceneInfos, setIndexActive, progress, linkedSource.Token); + return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token); } - public ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default) - { - sceneInfo = sceneInfo ?? throw new NullReferenceException($"[{GetType().Name}] Provided scene info is null."); - - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return LoadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, setActive ? 0 : -1, progress, linkedSource.Token); - } - - public ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default) - { - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return UnloadScenesAsync_Internal(sceneInfos, linkedSource.Token); - } - - public ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default) - { - sceneInfo = sceneInfo ?? throw new ArgumentNullException(nameof(sceneInfo), $"[{GetType().Name}] Provided scene info is null."); - - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return UnloadScenesAsync_Internal(new ILoadSceneInfo[] { sceneInfo }, linkedSource.Token); - } - - async ValueTask LoadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, int setIndexActive, IProgress progress, CancellationToken token) + async ValueTask LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) { + ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); + int setIndexActive = sceneParameters.GetIndexActive(); int scenesToLoad = sceneInfos.Length; - if (sceneInfos == null || scenesToLoad == 0) - throw new ArgumentException(nameof(sceneInfos), $"[{GetType().Name}] Provided scene group is null or empty."); - if (setIndexActive >= scenesToLoad) - throw new ArgumentException(nameof(setIndexActive), $"[{GetType().Name}] Provided index to set active is bigger than the provided scene group size."); ISceneData[] sceneDataArray = new ISceneData[scenesToLoad]; int i; @@ -264,7 +240,7 @@ async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneIn return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); } - async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, CancellationToken token) + async ValueTask TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) { // If only one scene is loaded, we need to create a temporary scene for transition. Scene tempScene = default; @@ -274,7 +250,7 @@ async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScen } await UnloadSourceSceneAsync(token); - Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, token: token); + Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); if (tempScene.IsValid()) { @@ -283,12 +259,12 @@ async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScen return new SceneResult(loadedScenes); } - async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { Scene loadingScene; try { - loadingScene = await LoadSceneAsync(intermediateSceneInfo, token: token); + loadingScene = await LoadAsync(new SceneParameters(intermediateSceneInfo, false), token: token); } catch { @@ -303,11 +279,11 @@ async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] ta LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(l => l.gameObject.scene == loadingScene); #endif return loadingBehavior - ? await TransitionWithIntermediateLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, loadingBehavior, token) - : await TransitionWithIntermediateNoLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, token); + ? await TransitionWithIntermediateLoadingAsync(sceneParameters, intermediateSceneInfo, loadingBehavior, token) + : await TransitionWithIntermediateNoLoadingAsync(sceneParameters, intermediateSceneInfo, token); } - async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + async ValueTask TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) @@ -315,21 +291,21 @@ async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneIn await UnloadSourceSceneAsync(token); - Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, progress, token); + Scene[] loadedScenes = await LoadAsync(sceneParameters, progress, token); progress.SetState(LoadingState.TargetSceneLoaded); while (progress.State != LoadingState.TransitionComplete && !token.IsCancellationRequested) await Awaitable.NextFrameAsync(token); - await UnloadSceneAsync(intermediateSceneInfo, token); + await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); return new SceneResult(loadedScenes); } - async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { await UnloadSourceSceneAsync(token); - Scene[] loadedScenes = await LoadScenesAsync(targetScenes, setIndexActive, token: token); - await UnloadSceneAsync(intermediateSceneInfo, token); + Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); + await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); return new SceneResult(loadedScenes); } @@ -339,7 +315,7 @@ ValueTask UnloadSourceSceneAsync(CancellationToken token) if (!sourceScene.IsValid()) return default; - return UnloadSceneAsync(new LoadSceneInfoScene(sourceScene), token); + return UnloadAsync(new SceneParameters(new LoadSceneInfoScene(sourceScene)), token); } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index 1540a967..2602b930 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -47,10 +47,10 @@ public interface ISceneManager : IDisposable void SetActiveScene(Scene scene); /// - /// Triggers a transition to a group of scens. + /// Triggers a transition to a group of scenes. /// It will transition from the current active scene () - /// to a group of scenes (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// to the target scene or a group of scenes via a struct, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: ///

/// 1. Load the intermediate scene (if provided).
@@ -58,11 +58,8 @@ public interface ISceneManager : IDisposable /// 3. Load all target scenes.
/// 4. Unload the intermediate scene (if provided).
///
- /// - /// A reference to all scenes that will be transitioned to. - /// - /// - /// Index of the scene in the to be set as the active scene. + /// + /// A struct that may hold one or more scenes and the target active index. /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). @@ -70,85 +67,38 @@ public interface ISceneManager : IDisposable /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); /// - /// Triggers a scene transition. - /// It will transition from the current active scene () - /// to the target scene (), with an optional intermediate loading scene (). - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load the target scene.
- /// 4. Unload the intermediate scene (if provided).
+ /// Loads the target scene or group of scenes provided via a struct. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. ///
- /// - /// A reference to the scene that's going to be transitioned to. + /// + /// A struct that may hold one or more scenes and the target active index. /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with the loaded scene as the result. - ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); - - /// - /// Loads all scenes provided by the array in parallel. - /// You may also provide the desired index to set as the active scene through the parameter. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// References to all scenes to load. - /// Index of the desired scene to set active, based on the array. - /// Object to report the loading operations progress to, from 0 to 1. - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - /// When scene info group is null, empty or the setIndexName is bigger than the scene length. - /// When the provided scene info group fails to produce valid load scene operations. - ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default); - - /// - /// Loads a scene referenced by the , optionally enabling it as the active scene. - /// Also, you can pass an object to receive the progress of the loading operation, from 0 to 1. - /// - /// A reference to the scene that's going to be loaded. - /// Should the loaded scene be enabled as the active scene? - /// Object to report the loading operation progress to, from 0 to 1. - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with the loaded scene as the result. - /// When scene info is null. - /// When the provided scene info fails to produce a valid load scene operation. - ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default); + ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default); /// - /// Unloads all scenes provided by the array in parallel. + /// Unloads the target scene or group of scenes provided via a struct. /// - /// Reference to all scenes to unload. + /// + /// A struct that may hold one or more scenes and the target active index. + /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- /// When scene info group is null or empty. - /// When the provided scene info group fails to produce valid unload scene operations. - ValueTask UnloadScenesAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default); - - /// - /// Unloads a scene referenced by the . - /// - /// A reference to the scene that's going to be unloaded. - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with the unloaded scene as the result. - ///
- /// Note that in some cases, the returned scene might no longer have a reference to its native representation, which means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- /// When scene info is null. - /// When the provided scene info fails to produce a valid unload scene operation. - ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default); + ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default); /// /// Gets the current active scene in this instance. diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs new file mode 100644 index 00000000..7cf1e359 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs @@ -0,0 +1,43 @@ +namespace MyGameDevTools.SceneLoading +{ + public readonly struct SceneParameters + { + readonly ILoadSceneInfo[] _loadSceneInfoArray; + readonly ILoadSceneInfo _singleLoadSceneInfo; + readonly int _setIndexActive; + + public SceneParameters(ILoadSceneInfo[] loadSceneInfos, int setIndexActive = -1) + { + _loadSceneInfoArray = loadSceneInfos; + _singleLoadSceneInfo = loadSceneInfos[0]; + _setIndexActive = setIndexActive; + } + + public SceneParameters(ILoadSceneInfo loadSceneInfo, bool setActive = false) + { + _loadSceneInfoArray = new ILoadSceneInfo[] { loadSceneInfo }; + _singleLoadSceneInfo = loadSceneInfo; + _setIndexActive = setActive ? 0 : -1; + } + + public readonly ILoadSceneInfo GetLoadSceneInfo() + { + return _singleLoadSceneInfo; + } + + public readonly ILoadSceneInfo[] GetLoadSceneInfos() + { + return _loadSceneInfoArray; + } + + public readonly bool ShouldSetActive() + { + return _setIndexActive == 0; + } + + public readonly int GetIndexActive() + { + return _setIndexActive; + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs.meta new file mode 100644 index 00000000..a472d7fc --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 701953da3da98e54184827cc246e10c6 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs index 6cc3f304..9ee45171 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs @@ -64,45 +64,4 @@ public override string ToString() return builder.ToString(); } } - - public readonly struct SceneParameter - { - readonly ILoadSceneInfo[] _loadSceneInfoArray; - readonly ILoadSceneInfo _singleLoadSceneInfo; - readonly int _setIndexActive; - - public SceneParameter(ILoadSceneInfo[] loadSceneInfos, int setIndexActive = -1) - { - _loadSceneInfoArray = loadSceneInfos; - _singleLoadSceneInfo = loadSceneInfos[0]; - _setIndexActive = setIndexActive; - } - - public SceneParameter(ILoadSceneInfo loadSceneInfo, bool setActive = false) - { - _loadSceneInfoArray = null; - _singleLoadSceneInfo = loadSceneInfo; - _setIndexActive = setActive ? 0 : -1; - } - - public readonly ILoadSceneInfo GetLoadSceneInfo() - { - return _singleLoadSceneInfo; - } - - public readonly ILoadSceneInfo[] GetLoadSceneInfos() - { - return _loadSceneInfoArray; - } - - public readonly bool ShouldSetActive() - { - return _setIndexActive == 0; - } - - public readonly int GetIndexActive() - { - return _setIndexActive; - } - } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index bab80ef6..9b4f6a28 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -95,7 +95,7 @@ public IEnumerator InitializationScene_Unload() ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); WaitTask waitTask = default; - Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadSceneAsync(new LoadSceneInfoScene(loadedScene)).AsTask())); + Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).AsTask())); yield return waitTask; } @@ -129,7 +129,7 @@ public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), name [UnityTest] public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - var loadTask = manager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)).AsTask(); yield return new WaitTask(loadTask); @@ -150,7 +150,7 @@ public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironmen [UnityTest] public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1])).AsTask()); + yield return new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).AsTask()); Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } @@ -172,7 +172,7 @@ public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment [UnityTest] public IEnumerator LoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) { - var loadTask = manager.LoadSceneAsync(sceneInfo, setActive).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfo, setActive)).AsTask(); Scene eventScene = default; manager.SceneLoaded += setEventScene; @@ -202,7 +202,7 @@ public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof( manager.SceneLoaded += reportSceneLoaded; var progress = new SimpleProgress(); - var loadTask = manager.LoadScenesAsync(sceneInfos, setIndexActive, progress).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos, setIndexActive), progress).AsTask(); Assert.AreEqual(0, progress.Value); @@ -229,7 +229,7 @@ public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive, progress).AsTask()); + yield return new WaitTask(manager.LoadAsync(new SceneParameters(sceneInfo, setActive), progress).AsTask()); Assert.AreEqual(1, progress.Value); } @@ -241,7 +241,7 @@ public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), for (int i = 0; i < length; i++) { - var loadTask = manager.LoadSceneAsync(sceneInfos[i], setActive).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)).AsTask(); yield return new WaitTask(loadTask); loadedScenes[i] = loadTask.Result; } @@ -264,21 +264,21 @@ public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), name var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = new WaitTask(manager.LoadSceneAsync(new LoadSceneInfoName(sceneName), false).AsTask()); + var wait = new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(sceneName), false)).AsTask()); Assert.Throws(() => wait.MoveNext()); } [UnityTest] public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) { - yield return new WaitTask(manager.LoadSceneAsync(sceneInfo, setActive).AsTask()); + yield return new WaitTask(manager.LoadAsync(new SceneParameters(sceneInfo, setActive)).AsTask()); Scene eventScene = default; manager.SceneUnloaded += setEventScene; var workingScene = manager.GetLastLoadedScene(); - var task = manager.UnloadSceneAsync(new LoadSceneInfoScene(workingScene)).AsTask(); + var task = manager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(workingScene))).AsTask(); yield return new WaitTask(task); manager.SceneUnloaded -= setEventScene; @@ -299,7 +299,7 @@ public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof [UnityTest] public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { - var loadTask = manager.LoadScenesAsync(sceneInfos, setIndexActive).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos, setIndexActive)).AsTask(); yield return new WaitTask(loadTask); var loadedSceneHandles = loadTask.Result.GetScenes().Select(s => s.handle).ToArray(); @@ -307,7 +307,7 @@ public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameo var reportedScenes = new List(scenesToUnload); manager.SceneUnloaded += reportSceneUnloaded; - var task = manager.UnloadScenesAsync(sceneInfos).AsTask(); + var task = manager.UnloadAsync(new SceneParameters(sceneInfos)).AsTask(); yield return new WaitTask(task); manager.SceneUnloaded -= reportSceneUnloaded; @@ -343,7 +343,7 @@ public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nam var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = new WaitTask(manager.UnloadSceneAsync(new LoadSceneInfoName(sceneName)).AsTask()); + var wait = new WaitTask(manager.UnloadAsync(new SceneParameters(new LoadSceneInfoName(sceneName))).AsTask()); Assert.Throws(() => wait.MoveNext()); } @@ -354,7 +354,7 @@ public IEnumerator TransitionToScenes([ValueSource(typeof(SceneTestEnvironment), int sceneCount = targetScenes.Length; - var task = manager.TransitionToScenesAsync(targetScenes, 0, loadingScene).AsTask(); + var task = manager.TransitionAsync(new SceneParameters(targetScenes, 0), loadingScene).AsTask(); yield return new WaitTask(task); @@ -369,7 +369,7 @@ public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof( { yield return LoadFirstScene(manager); - var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); + var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene).AsTask(); yield return new WaitTask(task); @@ -392,7 +392,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron // The temporary scene unload does not go through the ISceneManager SceneManager.sceneUnloaded += sceneUnloaded; - var task = manager.TransitionToSceneAsync(targetScene, loadingScene).AsTask(); + var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene).AsTask(); yield return new WaitTask(task); @@ -415,13 +415,13 @@ void sceneUnloaded(Scene scene) [UnityTest] public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadSceneAsync(sceneInfo).AsTask(); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)).AsTask(); yield return new WaitTask(task); Scene scene = task.Result; - task = manager.UnloadSceneAsync(new LoadSceneInfoScene(scene)).AsTask(); + task = manager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(scene))).AsTask(); yield return new WaitTask(task); @@ -433,7 +433,7 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron /// public static WaitTask LoadFirstScene(ISceneManager sceneManager) { - var task = sceneManager.LoadSceneAsync(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true).AsTask(); + var task = sceneManager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)).AsTask(); return new WaitTask(task); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index d2f013ae..30d81eb4 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -11,7 +11,7 @@ public class SceneManager_CancellationTests : SceneTestBase public IEnumerator Cancellation_DuringLoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfo), token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.That(waitTask.Task.IsCompleted); @@ -22,7 +22,7 @@ public IEnumerator Cancellation_DuringLoadScene([ValueSource(typeof(SceneTestEnv public IEnumerator Cancellation_DuringLoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfos), token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -33,10 +33,11 @@ public IEnumerator Cancellation_DuringLoadScenes([ValueSource(typeof(SceneTestEn public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + SceneParameters parameters = new SceneParameters(sceneInfo); + WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadSceneAsync(sceneInfo, token: tokenSource.Token).AsTask()); + waitTask = new(manager.UnloadAsync(parameters, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -47,10 +48,11 @@ public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestE public IEnumerator Cancellation_DuringUnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + SceneParameters parameters = new SceneParameters(sceneInfos); + WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadScenesAsync(sceneInfos, token: tokenSource.Token).AsTask()); + waitTask = new(manager.UnloadAsync(parameters, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index d31032b3..f12f2aa6 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -2,7 +2,6 @@ using System; using System.Collections; using UnityEngine; -using UnityEngine.SceneManagement; using UnityEngine.TestTools; namespace MyGameDevTools.SceneLoading.Tests @@ -26,7 +25,7 @@ public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func< public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfo)).AsTask()); manager.Dispose(); yield return waitTask; Assert.That(waitTask.Task.IsCompleted); @@ -36,7 +35,7 @@ public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneManagerCrea public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfos)).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -46,10 +45,11 @@ public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneManagerCre public IEnumerator Dipose_DuringUnloadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadSceneAsync(sceneInfo).AsTask()); + SceneParameters parameters = new SceneParameters(sceneInfo); + WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadSceneAsync(sceneInfo).AsTask()); + waitTask = new(manager.UnloadAsync(parameters).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -59,10 +59,11 @@ public IEnumerator Dipose_DuringUnloadScene([ValueSource(nameof(_sceneManagerCre public IEnumerator Dipose_DuringUnloadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadScenesAsync(sceneInfos).AsTask()); + SceneParameters parameters = new SceneParameters(sceneInfos); + WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadScenesAsync(sceneInfos).AsTask()); + waitTask = new(manager.UnloadAsync(parameters).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -76,7 +77,7 @@ async Awaitable Test() ISceneManager manager = managerCreateFunc(); await SceneManagerTests.LoadFirstScene(manager).Task; - var task = manager.TransitionToSceneAsync(targetScene, loadingScene); + var task = manager.TransitionAsync(new SceneParameters(targetScene), loadingScene); manager.Dispose(); bool canceled = false; @@ -101,7 +102,7 @@ async Awaitable Test() ISceneManager manager = managerCreateFunc(); await SceneManagerTests.LoadFirstScene(manager).Task; - var task = manager.TransitionToScenesAsync(targetScenes, 0, loadingScene); + var task = manager.TransitionAsync(new SceneParameters(targetScenes, 0), loadingScene); manager.Dispose(); bool canceled = false; diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index f6aacb3b..5f74e25f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -11,7 +11,7 @@ public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) var lastScene = sceneManager.GetLastLoadedScene(); while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneManager.UnloadSceneAsync(new LoadSceneInfoScene(lastScene)).AsTask()); + yield return new WaitTask(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(lastScene))).AsTask()); lastScene = sceneManager.GetLastLoadedScene(); } From 076c82e45227c7d47a2d0c2f09c844470f50558b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Fri, 20 Dec 2024 15:54:43 -0300 Subject: [PATCH 08/53] add extensions for load, transition and unload methods --- .../Runtime/Interfaces/ISceneManager.cs | 2 +- .../Runtime/Utilities/SceneDataUtilities.cs | 1 - .../Utilities/SceneManagerExtensions.cs | 649 ++++++++++++++++++ .../Utilities/SceneManagerExtensions.cs.meta | 2 + 4 files changed, 652 insertions(+), 2 deletions(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index 2602b930..f9ad1e8b 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -90,7 +90,7 @@ public interface ISceneManager : IDisposable /// Unloads the target scene or group of scenes provided via a struct. ///
/// - /// A struct that may hold one or more scenes and the target active index. + /// A struct that may hold one or more scenes. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs index a37339db..547877d5 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using UnityEngine; using UnityEngine.SceneManagement; using UnitySceneManager = UnityEngine.SceneManagement.SceneManager; diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs new file mode 100644 index 00000000..e403c960 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -0,0 +1,649 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +#if ENABLE_ADDRESSABLES +using UnityEngine.AddressableAssets; +#endif +using UnityEngine.SceneManagement; + +namespace MyGameDevTools.SceneLoading +{ + public static class SceneManagerExtensions + { + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' names. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(this ISceneManager sceneManager, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + { + ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); + SceneParameters sceneParams = new(sceneInfos, setIndexActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' build indexes. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(this ISceneManager sceneManager, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + { + ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); + SceneParameters sceneParams = new(sceneInfos, setIndexActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's name. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(this ISceneManager sceneManager, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) + { + SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName), setActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's build index. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(this ISceneManager sceneManager, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) + { + SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex), setActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + +#if ENABLE_ADDRESSABLES + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' . + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + { + ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); + SceneParameters sceneParams = new(sceneInfos, setIndexActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' addressable address. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + { + ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); + SceneParameters sceneParams = new(sceneInfos, setIndexActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's . + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) + { + SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference), setActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's addressable address. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) + { + SceneParameters sceneParams = new(new LoadSceneInfoAddress(address), setActive); + return sceneManager.LoadAsync(sceneParams, progress, token); + } +#endif + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their names to transition to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, int setIndexActive = -1, string loadingSceneName = null, CancellationToken token = default) + { + SceneParameters targetParams = new(targetSceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(), setIndexActive); + ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their build index to transition to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int setIndexActive = -1, int? loadingBuildIndex = null, CancellationToken token = default) + { + SceneParameters targetParams = new(targetBuildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(), setIndexActive); + ILoadSceneInfo loadingSceneInfo = loadingBuildIndex.HasValue ? new LoadSceneInfoIndex(loadingBuildIndex.Value) : null; + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene name to be transitioned to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(this ISceneManager sceneManager, string targetSceneName, bool setActive = false, string loadingSceneName = null, CancellationToken token = default) + { + SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), setActive); + ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene build index to be transitioned to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, bool setActive = false, int? loadingBuildIndex = null, CancellationToken token = default) + { + SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), setActive); + ILoadSceneInfo loadingSceneInfo = loadingBuildIndex.HasValue ? new LoadSceneInfoIndex(loadingBuildIndex.Value) : null; + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + +#if ENABLE_ADDRESSABLES + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their to transition to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, int setIndexActive = -1, AssetReference loadingAssetReference = null, CancellationToken token = default) + { + SceneParameters targetParams = new(targetAssetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(), setIndexActive); + ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their addressable addresses to transition to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, int setIndexActive = -1, string loadingAddress = null, CancellationToken token = default) + { + SceneParameters targetParams = new(targetAddresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(), setIndexActive); + ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene to be transitioned to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, bool setActive = false, AssetReference loadingAssetReference = null, CancellationToken token = default) + { + SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), setActive); + ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene addressable address to be transitioned to. + /// + /// + /// The index of the scene to be activated as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, bool setActive = false, string loadingAddress = null, CancellationToken token = default) + { + SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), setActive); + ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + } +#endif + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their names to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) + { + var sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); + var sceneParams = new SceneParameters(sceneInfos); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) + { + var sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); + var sceneParams = new SceneParameters(sceneInfos); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) + { + var sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); + var sceneParams = new SceneParameters(sceneInfos); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's name to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) + { + var sceneParams = new SceneParameters(new LoadSceneInfoName(sceneName)); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) + { + var sceneParams = new SceneParameters(new LoadSceneInfoIndex(buildIndex)); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) + { + var sceneParams = new SceneParameters(new LoadSceneInfoScene(scene)); + return sceneManager.UnloadAsync(sceneParams, token); + } + +#if ENABLE_ADDRESSABLES + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) + { + var sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); + var sceneParams = new SceneParameters(sceneInfos); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) + { + var sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); + var sceneParams = new SceneParameters(sceneInfos); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) + { + var sceneParams = new SceneParameters(new LoadSceneInfoAssetReference(assetReference)); + return sceneManager.UnloadAsync(sceneParams, token); + } + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's addressable address to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) + { + var sceneParams = new SceneParameters(new LoadSceneInfoAddress(address)); + return sceneManager.UnloadAsync(sceneParams, token); + } +#endif + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta new file mode 100644 index 00000000..c0c333f4 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c265d6fdb2414f84b9e8780dc6f07a09 \ No newline at end of file From b5cbfa6876fa90e2540a6d422a58ddfe66d774e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 29 Dec 2024 16:39:41 -0300 Subject: [PATCH 09/53] unify single and multiple scene tests --- .../Runtime/AdvancedSceneManager.cs | 2 +- .../Runtime/Structs/SceneParameters.cs | 4 +- .../Utilities/SceneManagerExtensions.cs | 30 ++--- .../Runtime/Utilities/WaitTask.cs | 19 --- .../Runtime/Utilities/WaitValueTask.cs | 24 ++++ .../Runtime/Utilities/WaitValueTask.cs.meta | 2 + .../Tests/Runtime/SceneManagerTests.cs | 108 ++++-------------- .../SceneManager_AssetReferenceTests.cs | 20 +--- .../Runtime/SceneManager_DisposeTests.cs | 4 +- .../Runtime/Utilities/SceneTestEnvironment.cs | 18 +++ 10 files changed, 94 insertions(+), 137 deletions(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index e89644fb..3d37d84f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -159,7 +159,7 @@ public ValueTask UnloadAsync(SceneParameters sceneParameters, Cance async ValueTask LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); - int setIndexActive = sceneParameters.GetIndexActive(); + int setIndexActive = sceneParameters.GetIndexToActivate(); int scenesToLoad = sceneInfos.Length; ISceneData[] sceneDataArray = new ISceneData[scenesToLoad]; diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs index 7cf1e359..ce40e447 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs @@ -2,6 +2,8 @@ namespace MyGameDevTools.SceneLoading { public readonly struct SceneParameters { + public readonly int Length => _loadSceneInfoArray.Length; + readonly ILoadSceneInfo[] _loadSceneInfoArray; readonly ILoadSceneInfo _singleLoadSceneInfo; readonly int _setIndexActive; @@ -35,7 +37,7 @@ public readonly bool ShouldSetActive() return _setIndexActive == 0; } - public readonly int GetIndexActive() + public readonly int GetIndexToActivate() { return _setIndexActive; } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs index e403c960..5647f11e 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -473,8 +473,8 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag ///
public static ValueTask UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) { - var sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); - var sceneParams = new SceneParameters(sceneInfos); + ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); + SceneParameters sceneParams = new(sceneInfos); return sceneManager.UnloadAsync(sceneParams, token); } @@ -492,8 +492,8 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) { - var sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); - var sceneParams = new SceneParameters(sceneInfos); + ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); + SceneParameters sceneParams = new(sceneInfos); return sceneManager.UnloadAsync(sceneParams, token); } @@ -511,8 +511,8 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) { - var sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); - var sceneParams = new SceneParameters(sceneInfos); + ILoadSceneInfo[] sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); + SceneParameters sceneParams = new(sceneInfos); return sceneManager.UnloadAsync(sceneParams, token); } @@ -530,7 +530,7 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) { - var sceneParams = new SceneParameters(new LoadSceneInfoName(sceneName)); + SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName)); return sceneManager.UnloadAsync(sceneParams, token); } @@ -548,7 +548,7 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) { - var sceneParams = new SceneParameters(new LoadSceneInfoIndex(buildIndex)); + SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex)); return sceneManager.UnloadAsync(sceneParams, token); } @@ -566,7 +566,7 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) { - var sceneParams = new SceneParameters(new LoadSceneInfoScene(scene)); + SceneParameters sceneParams = new(new LoadSceneInfoScene(scene)); return sceneManager.UnloadAsync(sceneParams, token); } @@ -585,8 +585,8 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) { - var sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); - var sceneParams = new SceneParameters(sceneInfos); + ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); + SceneParameters sceneParams = new(sceneInfos); return sceneManager.UnloadAsync(sceneParams, token); } @@ -604,8 +604,8 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) { - var sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); - var sceneParams = new SceneParameters(sceneInfos); + ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); + SceneParameters sceneParams = new(sceneInfos); return sceneManager.UnloadAsync(sceneParams, token); } @@ -623,7 +623,7 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) { - var sceneParams = new SceneParameters(new LoadSceneInfoAssetReference(assetReference)); + SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference)); return sceneManager.UnloadAsync(sceneParams, token); } @@ -641,7 +641,7 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) { - var sceneParams = new SceneParameters(new LoadSceneInfoAddress(address)); + SceneParameters sceneParams = new(new LoadSceneInfoAddress(address)); return sceneManager.UnloadAsync(sceneParams, token); } #endif diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs index 32e321d2..e58830e3 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitTask.cs @@ -27,23 +27,4 @@ public bool MoveNext() public void Reset() { } } - - public readonly struct WaitValueTask : IEnumerator - { - public object Current => null; - - public readonly ValueTask ValueTask; - - public WaitValueTask(ValueTask valueTask) - { - ValueTask = valueTask; - } - - public bool MoveNext() - { - return !ValueTask.IsCompleted && !ValueTask.IsCanceled && !ValueTask.IsFaulted; - } - - public void Reset() { } - } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs new file mode 100644 index 00000000..42a57c31 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs @@ -0,0 +1,24 @@ +using System.Collections; +using System.Threading.Tasks; + +namespace MyGameDevTools.SceneLoading +{ + public readonly struct WaitValueTask : IEnumerator + { + public object Current => null; + + public readonly ValueTask ValueTask; + + public WaitValueTask(ValueTask valueTask) + { + ValueTask = valueTask; + } + + public bool MoveNext() + { + return !ValueTask.IsCompleted && !ValueTask.IsCanceled && !ValueTask.IsFaulted; + } + + public void Reset() { } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta new file mode 100644 index 00000000..beedf3ce --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4c3e708735afb0e4aa8caf712ac9245b \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 9b4f6a28..4d85818b 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using System.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TestTools; @@ -19,10 +20,6 @@ public partial class SceneManagerTests : SceneTestBase new LoadSceneInfoName(SceneBuilder.SceneNames[0]), }; - static readonly bool[] _setActiveParameterValues = new bool[] { true, false }; - - static readonly int[] _setIndexActiveParameterValues = new int[] { -1, 1 }; - int _scenesActivated; int _scenesUnloaded; int _scenesLoaded; @@ -170,39 +167,15 @@ public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment } [UnityTest] - public IEnumerator LoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) + public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - var loadTask = manager.LoadAsync(new SceneParameters(sceneInfo, setActive)).AsTask(); - - Scene eventScene = default; - manager.SceneLoaded += setEventScene; - - yield return new WaitTask(loadTask); - - manager.SceneLoaded -= setEventScene; - Scene loadedScene = loadTask.Result; - - Assert.AreEqual(1, manager.LoadedSceneCount); - Assert.That(setActive ? loadedScene == manager.GetActiveScene() : loadedScene != manager.GetActiveScene()); - Assert.AreEqual(loadedScene, manager.GetLastLoadedScene()); - Assert.AreEqual(loadedScene, manager.GetLoadedSceneByName(loadedScene.name)); - Assert.AreEqual(loadedScene, eventScene); - Assert.AreEqual(1, _scenesLoaded); - Assert.AreEqual(0, _scenesUnloaded); - Assert.AreEqual(setActive ? 1 : 0, _scenesActivated); - - void setEventScene(Scene scene) => eventScene = scene; - } - - [UnityTest] - public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) - { - int scenesToLoad = sceneInfos.Length; + int scenesToLoad = sceneParameters.Length; + int setIndexActive = sceneParameters.GetIndexToActivate(); var reportedScenes = new List(scenesToLoad); manager.SceneLoaded += reportSceneLoaded; var progress = new SimpleProgress(); - var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos, setIndexActive), progress).AsTask(); + var loadTask = manager.LoadAsync(sceneParameters, progress).AsTask(); Assert.AreEqual(0, progress.Value); @@ -225,18 +198,21 @@ public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof( } [UnityTest] - public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) + public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(manager.LoadAsync(new SceneParameters(sceneInfo, setActive), progress).AsTask()); + yield return new WaitTask(manager.LoadAsync(sceneParameters, progress).AsTask()); Assert.AreEqual(1, progress.Value); } [UnityTest] - public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) + public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - var length = sceneInfos.Length; + ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); + int length = sceneInfos.Length; + bool setActive = sceneParameters.GetIndexToActivate() == 1; + var loadedScenes = new Scene[length]; for (int i = 0; i < length; i++) @@ -269,45 +245,17 @@ public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), name } [UnityTest] - public IEnumerator UnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) - { - yield return new WaitTask(manager.LoadAsync(new SceneParameters(sceneInfo, setActive)).AsTask()); - - Scene eventScene = default; - manager.SceneUnloaded += setEventScene; - - var workingScene = manager.GetLastLoadedScene(); - - var task = manager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(workingScene))).AsTask(); - yield return new WaitTask(task); - - manager.SceneUnloaded -= setEventScene; - Scene unloadedScene = task.Result; - - Assert.AreEqual(workingScene, unloadedScene); - Assert.AreEqual(workingScene, eventScene); - Assert.IsFalse(workingScene.isLoaded); - Assert.IsFalse(manager.GetActiveScene().IsValid()); - Assert.AreEqual(0, manager.LoadedSceneCount); - Assert.AreEqual(1, _scenesLoaded); - Assert.AreEqual(1, _scenesUnloaded); - Assert.AreEqual(setActive ? 2 : 0, _scenesActivated, "Activated scenes did not match expectation"); - - void setEventScene(Scene scene) => eventScene = scene; - } - - [UnityTest] - public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) + public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos, setIndexActive)).AsTask(); + var loadTask = manager.LoadAsync(sceneParameters).AsTask(); yield return new WaitTask(loadTask); var loadedSceneHandles = loadTask.Result.GetScenes().Select(s => s.handle).ToArray(); - int scenesToUnload = sceneInfos.Length; + int scenesToUnload = sceneParameters.Length; var reportedScenes = new List(scenesToUnload); manager.SceneUnloaded += reportSceneUnloaded; - var task = manager.UnloadAsync(new SceneParameters(sceneInfos)).AsTask(); + var task = manager.UnloadAsync(sceneParameters).AsTask(); yield return new WaitTask(task); manager.SceneUnloaded -= reportSceneUnloaded; @@ -318,7 +266,6 @@ public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameo Assert.AreEqual(0, manager.LoadedSceneCount); Assert.AreEqual(scenesToUnload, _scenesLoaded); Assert.AreEqual(scenesToUnload, _scenesUnloaded); - Assert.AreEqual(setIndexActive >= 0 ? 2 : 0, _scenesActivated, "Activated scenes did not match expectation"); for (int i = 0; i < scenesToUnload; i++) Assert.True(hasReference(loadedSceneHandles[i], reportedScenes)); @@ -348,13 +295,13 @@ public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nam } [UnityTest] - public IEnumerator TransitionToScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { yield return LoadFirstScene(manager); - int sceneCount = targetScenes.Length; + int sceneCount = sceneParameters.Length; - var task = manager.TransitionAsync(new SceneParameters(targetScenes, 0), loadingScene).AsTask(); + var task = manager.TransitionAsync(sceneParameters, loadingScene).AsTask(); yield return new WaitTask(task); @@ -364,16 +311,13 @@ public IEnumerator TransitionToScenes([ValueSource(typeof(SceneTestEnvironment), yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); } - [UnityTest] - public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition_Template(ISceneManager manager, ValueTask transitionTask) { yield return LoadFirstScene(manager); - var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene).AsTask(); - - yield return new WaitTask(task); + yield return new WaitValueTask(transitionTask); - Scene loadedScene = task.Result; + Scene loadedScene = transitionTask.Result; Assert.AreEqual(loadedScene, manager.GetActiveScene()); yield return new WaitUntil(() => manager.TotalSceneCount == 1); @@ -429,13 +373,9 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron } /// - /// Required to test transition some scenarios. + /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene(ISceneManager sceneManager) - { - var task = sceneManager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)).AsTask(); - return new WaitTask(task); - } + public static WaitValueTask LoadFirstScene(ISceneManager sceneManager) => new(sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); void ReportSceneActivation(Scene previousScene, Scene newScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs index 583fb04f..3ea0377a 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs @@ -14,6 +14,8 @@ public partial class SceneManagerTests { ILoadSceneInfo[] _assetReferenceLoadSceneInfos; + static readonly int[] _setIndexActiveParameterValues = new[] { -1, 1 }; + [OneTimeSetUp] public void AssetReferenceSetup() { @@ -33,28 +35,16 @@ public void AssetReferenceSetup() Addressables.Release(operationHandle); } - [UnityTest] - public IEnumerator LoadScene_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) - { - yield return LoadScene(manager, _assetReferenceLoadSceneInfos[1], setActive); - } - [UnityTest] public IEnumerator LoadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { - yield return LoadScenes(manager, _assetReferenceLoadSceneInfos, setIndexActive); - } - - [UnityTest] - public IEnumerator UnloadScene_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setActiveParameterValues))] bool setActive) - { - yield return UnloadScene(manager, _assetReferenceLoadSceneInfos[1], setActive); + yield return LoadScenes(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); } [UnityTest] - public IEnumerator UnloadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) + public IEnumerator UnloadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return UnloadScenes(manager, _assetReferenceLoadSceneInfos, setIndexActive); + yield return UnloadScenes(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); } } } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index f12f2aa6..5a91433b 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -75,7 +75,7 @@ public IEnumerator Dispose_DuringTransitionToSceneAsync([ValueSource(nameof(_sce async Awaitable Test() { ISceneManager manager = managerCreateFunc(); - await SceneManagerTests.LoadFirstScene(manager).Task; + await SceneManagerTests.LoadFirstScene(manager).ValueTask; var task = manager.TransitionAsync(new SceneParameters(targetScene), loadingScene); manager.Dispose(); @@ -100,7 +100,7 @@ public IEnumerator Dispose_DuringTransitionToScenesAsync([ValueSource(nameof(_sc async Awaitable Test() { ISceneManager manager = managerCreateFunc(); - await SceneManagerTests.LoadFirstScene(manager).Task; + await SceneManagerTests.LoadFirstScene(manager).ValueTask; var task = manager.TransitionAsync(new SceneParameters(targetScenes, 0), loadingScene); manager.Dispose(); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index b36d0abe..1af21053 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -60,6 +60,24 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup #endif }; + public static readonly SceneParameters[] SceneParametersList = new SceneParameters[] + { + new(SingleLoadSceneInfoList[0], false), + new(SingleLoadSceneInfoList[0], true), + new(SingleLoadSceneInfoList[1], false), + new(SingleLoadSceneInfoList[1], true), + new(SingleLoadSceneInfoList[2], false), + new(SingleLoadSceneInfoList[2], true), +#if ENABLE_ADDRESSABLES + new(SingleLoadSceneInfoList[3], false), + new(SingleLoadSceneInfoList[3], true), +#endif + new(MultipleLoadSceneInfoList[0], -1), + new(MultipleLoadSceneInfoList[0], 1), + new(MultipleLoadSceneInfoList[1], -1), + new(MultipleLoadSceneInfoList[1], 1), + }; + public static readonly ISceneManager[] SceneManagers = new ISceneManager[] { new AdvancedSceneManager(), From be613658c6f172fc296b78baea0b5a9e309b166b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 29 Dec 2024 17:42:09 -0300 Subject: [PATCH 10/53] update a few tests, optimize code smells --- .../Runtime/AdvancedSceneManager.cs | 14 ++++-- .../Runtime/Structs/SceneParameters.cs | 2 +- .../Runtime/Structs/SceneResult.cs | 26 ++-------- .../Tests/Runtime/SceneManagerTests.cs | 48 ++++++++----------- .../Runtime/Utilities/SceneTestUtilities.cs | 2 +- .../Settings.json | 10 ++++ 6 files changed, 45 insertions(+), 57 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 3d37d84f..b9044ff5 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -286,21 +286,27 @@ async ValueTask TransitionWithIntermediateAsync(SceneParameters sce async ValueTask TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; - while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) - await Awaitable.NextFrameAsync(token); + await WaitForLoadingStateAsync(progress, LoadingState.Loading, token); await UnloadSourceSceneAsync(token); Scene[] loadedScenes = await LoadAsync(sceneParameters, progress, token); progress.SetState(LoadingState.TargetSceneLoaded); - while (progress.State != LoadingState.TransitionComplete && !token.IsCancellationRequested) - await Awaitable.NextFrameAsync(token); + await WaitForLoadingStateAsync(progress, LoadingState.TransitionComplete, token); await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); return new SceneResult(loadedScenes); } + async ValueTask WaitForLoadingStateAsync(LoadingProgress progress, LoadingState targetState, CancellationToken token = default) + { + while (progress.State != targetState && !token.IsCancellationRequested) + { + await Awaitable.NextFrameAsync(token); + } + } + async ValueTask TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { await UnloadSourceSceneAsync(token); diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs index ce40e447..17f31de0 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneParameters.cs @@ -34,7 +34,7 @@ public readonly ILoadSceneInfo[] GetLoadSceneInfos() public readonly bool ShouldSetActive() { - return _setIndexActive == 0; + return _setIndexActive >= 0; } public readonly int GetIndexToActivate() diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs index 9ee45171..38cdfc96 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneResult.cs @@ -1,4 +1,4 @@ -using System.Text; +using System.Linq; using UnityEngine.SceneManagement; namespace MyGameDevTools.SceneLoading @@ -19,7 +19,7 @@ public SceneResult(Scene[] sceneArray) public SceneResult(Scene scene) { - _sceneArray = null; + _sceneArray = new[] { scene }; _singleScene = scene; } @@ -41,27 +41,7 @@ public override string ToString() if (!_singleScene.IsValid()) return "Empty SceneResult"; - int sceneCount = (_sceneArray == null || _sceneArray.Length == 0) ? 1 : _sceneArray.Length; - - StringBuilder builder = new("{ "); - if (sceneCount == 1) - { - builder.Append(_singleScene.name); - builder.Append(" }"); - return builder.ToString(); - } - - for (int i = 0; i < sceneCount; i++) - { - if (i > 0) - { - builder.Append(", "); - } - builder.Append(_sceneArray[i].name); - } - - builder.Append(" }"); - return builder.ToString(); + return $"{{ {string.Join(", ", _sceneArray.Select(scene => scene.name))} }}"; } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 4d85818b..e1dec46c 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -175,11 +175,11 @@ public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof( manager.SceneLoaded += reportSceneLoaded; var progress = new SimpleProgress(); - var loadTask = manager.LoadAsync(sceneParameters, progress).AsTask(); + var loadTask = manager.LoadAsync(sceneParameters, progress); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(loadTask); + yield return new WaitValueTask(loadTask); manager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = loadTask.Result; @@ -202,12 +202,12 @@ public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(manager.LoadAsync(sceneParameters, progress).AsTask()); + yield return new WaitValueTask(manager.LoadAsync(sceneParameters, progress)); Assert.AreEqual(1, progress.Value); } [UnityTest] - public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator LoadScene_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int length = sceneInfos.Length; @@ -217,8 +217,8 @@ public IEnumerator LoadScene_Multiple([ValueSource(typeof(SceneTestEnvironment), for (int i = 0; i < length; i++) { - var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)).AsTask(); - yield return new WaitTask(loadTask); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); + yield return new WaitValueTask(loadTask); loadedScenes[i] = loadTask.Result; } @@ -240,7 +240,7 @@ public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), name var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(sceneName), false)).AsTask()); + var wait = new WaitTask(manager.LoadAsync(sceneName).AsTask()); Assert.Throws(() => wait.MoveNext()); } @@ -290,39 +290,31 @@ public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nam var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = new WaitTask(manager.UnloadAsync(new SceneParameters(new LoadSceneInfoName(sceneName))).AsTask()); + var wait = new WaitTask(manager.UnloadAsync(sceneName).AsTask()); Assert.Throws(() => wait.MoveNext()); } [UnityTest] public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { - yield return LoadFirstScene(manager); - - int sceneCount = sceneParameters.Length; + yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene).AsTask(), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + } - var task = manager.TransitionAsync(sceneParameters, loadingScene).AsTask(); + public IEnumerator Transition_Template(ISceneManager manager, Func> transitionTask, int sceneCount, int setIndexActive) + { + yield return LoadFirstScene(manager); + var task = transitionTask(); yield return new WaitTask(task); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); + if (setIndexActive >= 0) + Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); } - public IEnumerator Transition_Template(ISceneManager manager, ValueTask transitionTask) - { - yield return LoadFirstScene(manager); - - yield return new WaitValueTask(transitionTask); - - Scene loadedScene = transitionTask.Result; - Assert.AreEqual(loadedScene, manager.GetActiveScene()); - - yield return new WaitUntil(() => manager.TotalSceneCount == 1); - } - [UnityTest] public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { @@ -359,15 +351,15 @@ void sceneUnloaded(Scene scene) [UnityTest] public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadAsync(new SceneParameters(sceneInfo)).AsTask(); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitTask(task); + yield return new WaitValueTask(task); Scene scene = task.Result; - task = manager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(scene))).AsTask(); + task = manager.UnloadAsync(scene); - yield return new WaitTask(task); + yield return new WaitValueTask(task); Assert.Zero(manager.LoadedSceneCount); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index 5f74e25f..d2852f54 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -11,7 +11,7 @@ public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) var lastScene = sceneManager.GetLastLoadedScene(); while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(lastScene))).AsTask()); + yield return new WaitTask(sceneManager.UnloadAsync(lastScene).AsTask()); lastScene = sceneManager.GetLastLoadedScene(); } diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json index e6b3e1a9..985a113a 100644 --- a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -25,6 +25,16 @@ "type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "AutoGenerateReport", "value": "{\"m_Value\":false}" + }, + { + "type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "key": "GenerateAdditionalMetrics", + "value": "{\"m_Value\":true}" + }, + { + "type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "key": "GenerateTestReferences", + "value": "{\"m_Value\":true}" } ] } From ed908f93477dd9c60c6e201bfcf7b3a4ad437b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 29 Dec 2024 17:57:19 -0300 Subject: [PATCH 11/53] optimize scene operation tests --- .../Tests/Runtime/SceneManagerTests.cs | 171 +++++++++--------- .../SceneManager_AssetReferenceTests.cs | 4 +- 2 files changed, 91 insertions(+), 84 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index e1dec46c..6fd6be7e 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -167,38 +167,14 @@ public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment } [UnityTest] - public IEnumerator LoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - int scenesToLoad = sceneParameters.Length; - int setIndexActive = sceneParameters.GetIndexToActivate(); - var reportedScenes = new List(scenesToLoad); - manager.SceneLoaded += reportSceneLoaded; - var progress = new SimpleProgress(); - var loadTask = manager.LoadAsync(sceneParameters, progress); - - Assert.AreEqual(0, progress.Value); - - yield return new WaitValueTask(loadTask); - - manager.SceneLoaded -= reportSceneLoaded; - Scene[] loadedScenes = loadTask.Result; - - Assert.AreEqual(1, progress.Value); - Assert.AreEqual(scenesToLoad, loadedScenes.Length); - Assert.AreEqual(scenesToLoad, reportedScenes.Count); - Assert.AreEqual(scenesToLoad, manager.LoadedSceneCount); - if (setIndexActive >= 0) - Assert.AreEqual(manager.GetActiveScene(), loadedScenes[setIndexActive]); - Assert.AreEqual(scenesToLoad, _scenesLoaded); - Assert.AreEqual(0, _scenesUnloaded); - Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); - - void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); + return Load_Template(manager, () => manager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); @@ -207,7 +183,7 @@ public IEnumerator LoadScene_Progress([ValueSource(typeof(SceneTestEnvironment), } [UnityTest] - public IEnumerator LoadScene_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int length = sceneInfos.Length; @@ -235,7 +211,7 @@ public IEnumerator LoadScene_Stress([ValueSource(typeof(SceneTestEnvironment), n } [Test] - public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) @@ -245,47 +221,13 @@ public void LoadScene_NotInBuild([ValueSource(typeof(SceneTestEnvironment), name } [UnityTest] - public IEnumerator UnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - var loadTask = manager.LoadAsync(sceneParameters).AsTask(); - yield return new WaitTask(loadTask); - var loadedSceneHandles = loadTask.Result.GetScenes().Select(s => s.handle).ToArray(); - - int scenesToUnload = sceneParameters.Length; - var reportedScenes = new List(scenesToUnload); - manager.SceneUnloaded += reportSceneUnloaded; - - var task = manager.UnloadAsync(sceneParameters).AsTask(); - yield return new WaitTask(task); - - manager.SceneUnloaded -= reportSceneUnloaded; - Scene[] unloadedScenes = task.Result; - - Assert.AreEqual(scenesToUnload, unloadedScenes.Length); - Assert.AreEqual(scenesToUnload, reportedScenes.Count); - Assert.AreEqual(0, manager.LoadedSceneCount); - Assert.AreEqual(scenesToUnload, _scenesLoaded); - Assert.AreEqual(scenesToUnload, _scenesUnloaded); - - for (int i = 0; i < scenesToUnload; i++) - Assert.True(hasReference(loadedSceneHandles[i], reportedScenes)); - - void reportSceneUnloaded(Scene loadedScene) => reportedScenes.Add(loadedScene); - - bool hasReference(int handle, List scenes) - { - foreach (var scene in scenes) - if (scene.handle == handle) - { - scenes.Remove(scene); - return true; - } - return false; - } + yield return Unload_Template(manager, () => manager.LoadAsync(sceneParameters), () => manager.UnloadAsync(sceneParameters), sceneParameters.Length); } [Test] - public void UnloadScene_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) @@ -300,21 +242,6 @@ public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof( yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene).AsTask(), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } - public IEnumerator Transition_Template(ISceneManager manager, Func> transitionTask, int sceneCount, int setIndexActive) - { - yield return LoadFirstScene(manager); - - var task = transitionTask(); - yield return new WaitTask(task); - - Scene[] loadedScenes = task.Result; - Assert.AreEqual(sceneCount, loadedScenes.Length); - if (setIndexActive >= 0) - Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); - - yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); - } - [UnityTest] public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { @@ -349,7 +276,7 @@ void sceneUnloaded(Scene scene) } [UnityTest] - public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); @@ -364,6 +291,86 @@ public IEnumerator LoadByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviron Assert.Zero(manager.LoadedSceneCount); } + public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + { + var reportedScenes = new List(sceneCount); + manager.SceneLoaded += reportSceneLoaded; + + var task = loadTask(); + + Assert.AreEqual(0, progress.Value); + + yield return new WaitValueTask(task); + + manager.SceneLoaded -= reportSceneLoaded; + Scene[] loadedScenes = task.Result; + + Assert.AreEqual(1, progress.Value); + Assert.AreEqual(sceneCount, loadedScenes.Length); + Assert.AreEqual(sceneCount, reportedScenes.Count); + Assert.AreEqual(sceneCount, manager.LoadedSceneCount); + if (setIndexActive >= 0) + Assert.AreEqual(manager.GetActiveScene(), loadedScenes[setIndexActive]); + Assert.AreEqual(sceneCount, _scenesLoaded); + Assert.AreEqual(0, _scenesUnloaded); + Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); + + void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); + } + + public IEnumerator Transition_Template(ISceneManager manager, Func> transitionTask, int sceneCount, int setIndexActive) + { + yield return LoadFirstScene(manager); + + var task = transitionTask(); + yield return new WaitTask(task); + + Scene[] loadedScenes = task.Result; + Assert.AreEqual(sceneCount, loadedScenes.Length); + if (setIndexActive >= 0) + Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); + + yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); + } + + public IEnumerator Unload_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) + { + var load = loadTask(); + yield return new WaitValueTask(load); + var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); + + var reportedScenes = new List(sceneCount); + manager.SceneUnloaded += reportSceneUnloaded; + + var unload = unloadTask(); + yield return new WaitValueTask(unload); + + manager.SceneUnloaded -= reportSceneUnloaded; + Scene[] unloadedScenes = unload.Result; + + Assert.AreEqual(sceneCount, unloadedScenes.Length); + Assert.AreEqual(sceneCount, reportedScenes.Count); + Assert.AreEqual(0, manager.LoadedSceneCount); + Assert.AreEqual(sceneCount, _scenesLoaded); + Assert.AreEqual(sceneCount, _scenesUnloaded); + + for (int i = 0; i < sceneCount; i++) + Assert.True(hasReference(loadedSceneHandles[i], reportedScenes)); + + void reportSceneUnloaded(Scene loadedScene) => reportedScenes.Add(loadedScene); + + bool hasReference(int handle, List scenes) + { + foreach (var scene in scenes) + if (scene.handle == handle) + { + scenes.Remove(scene); + return true; + } + return false; + } + } + /// /// Required to test some transition scenarios. /// diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs index 3ea0377a..47d11328 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs @@ -38,13 +38,13 @@ public void AssetReferenceSetup() [UnityTest] public IEnumerator LoadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { - yield return LoadScenes(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); + yield return Load(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); } [UnityTest] public IEnumerator UnloadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return UnloadScenes(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); + yield return Unload(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); } } } From 867fe3fcadbb635dce06c1a8cc7e4b0775cde99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 29 Dec 2024 19:35:49 -0300 Subject: [PATCH 12/53] fix: add scene manager extension tests BREAKING CHANGE: bump to major 4 (pre-release) --- .../Runtime/AdvancedSceneManager.cs | 3 + .../Utilities/SceneManagerExtensions.cs | 66 +++---- .../Tests/Runtime/SceneManagerTests.cs | 9 +- .../SceneManager_AssetReferenceTests.cs | 8 +- .../Runtime/SceneManager_CancellationTests.cs | 37 +--- .../Runtime/SceneManager_DisposeTests.cs | 64 +------ .../Runtime/SceneManager_ExtensionTests.cs | 169 ++++++++++++++++++ .../SceneManager_ExtensionTests.cs.meta | 2 + .../Runtime/Utilities/SceneTestEnvironment.cs | 75 ++++---- .../Settings.json | 2 +- 10 files changed, 267 insertions(+), 168 deletions(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index b9044ff5..95c01b4f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -138,6 +138,9 @@ public Scene GetLoadedSceneByName(string name) public ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) { + if (!sceneParameters.ShouldSetActive()) + throw new ArgumentException($"[{GetType().Name}] You need to provide a SceneParameters object with a valid 'setIndexActive' value to perform scene transitions.", nameof(sceneParameters)); + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); return intermediateSceneReference == null ? TransitionDirectlyAsync(sceneParameters, linkedSource.Token).RunAndDisposeToken(linkedSource) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs index 5647f11e..26e7bbbd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -224,16 +224,16 @@ public static ValueTask LoadAddressableAsync(this ISceneManager sce /// /// An array of scenes by their names to transition to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, int setIndexActive = -1, string loadingSceneName = null, CancellationToken token = default) + public static ValueTask TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetSceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); @@ -255,19 +255,19 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// /// An array of scenes by their build index to transition to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int setIndexActive = -1, int? loadingBuildIndex = null, CancellationToken token = default) + public static ValueTask TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetBuildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(), setIndexActive); - ILoadSceneInfo loadingSceneInfo = loadingBuildIndex.HasValue ? new LoadSceneInfoIndex(loadingBuildIndex.Value) : null; + ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } @@ -286,18 +286,15 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// /// The target scene name to be transitioned to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, string targetSceneName, bool setActive = false, string loadingSceneName = null, CancellationToken token = default) + public static ValueTask TransitionAsync(this ISceneManager sceneManager, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) { - SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), setActive); + SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } @@ -317,19 +314,16 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// /// The target scene build index to be transitioned to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. + /// If -1, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, bool setActive = false, int? loadingBuildIndex = null, CancellationToken token = default) + public static ValueTask TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) { - SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), setActive); - ILoadSceneInfo loadingSceneInfo = loadingBuildIndex.HasValue ? new LoadSceneInfoIndex(loadingBuildIndex.Value) : null; + SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), true); + ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } @@ -349,16 +343,16 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// /// An array of scenes by their to transition to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, int setIndexActive = -1, AssetReference loadingAssetReference = null, CancellationToken token = default) + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAssetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; @@ -380,16 +374,16 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// /// An array of scenes by their addressable addresses to transition to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, int setIndexActive = -1, string loadingAddress = null, CancellationToken token = default) + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAddresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); @@ -411,18 +405,15 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// /// The target scene to be transitioned to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, bool setActive = false, AssetReference loadingAssetReference = null, CancellationToken token = default) + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) { - SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), setActive); + SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), true); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } @@ -442,18 +433,15 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// /// The target scene addressable address to be transitioned to. /// - /// - /// The index of the scene to be activated as the active scene. - /// /// /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, bool setActive = false, string loadingAddress = null, CancellationToken token = default) + public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, string loadingAddress = null, CancellationToken token = default) { - SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), setActive); + SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 6fd6be7e..c615783f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -20,6 +20,9 @@ public partial class SceneManagerTests : SceneTestBase new LoadSceneInfoName(SceneBuilder.SceneNames[0]), }; + static readonly bool[] _setActiveParameterValues = new[] { false, true }; + static readonly int[] _setIndexActiveParameterValues = new[] { -1, 1 }; + int _scenesActivated; int _scenesUnloaded; int _scenesLoaded; @@ -237,7 +240,8 @@ public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(S } [UnityTest] - public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. + TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene).AsTask(), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } @@ -327,8 +331,7 @@ public IEnumerator Transition_Template(ISceneManager manager, Func= 0) - Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); + Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs index 47d11328..b6a8e458 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs @@ -12,10 +12,9 @@ namespace MyGameDevTools.SceneLoading.Tests // Unity Editor sessions. So, we must test AssetReference load scene infos "manually". public partial class SceneManagerTests { + AssetReference[] _assetReferences; ILoadSceneInfo[] _assetReferenceLoadSceneInfos; - static readonly int[] _setIndexActiveParameterValues = new[] { -1, 1 }; - [OneTimeSetUp] public void AssetReferenceSetup() { @@ -23,6 +22,7 @@ public void AssetReferenceSetup() operationHandle.WaitForCompletion(); SceneReferenceData sceneReferenceData = operationHandle.Result; + _assetReferences = sceneReferenceData.sceneReferences.ToArray(); _assetReferenceLoadSceneInfos = new ILoadSceneInfo[] { @@ -36,13 +36,13 @@ public void AssetReferenceSetup() } [UnityTest] - public IEnumerator LoadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) + public IEnumerator Load_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { yield return Load(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); } [UnityTest] - public IEnumerator UnloadScenes_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public IEnumerator Unload_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { yield return Unload(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index 30d81eb4..3ff4905f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -8,36 +8,10 @@ namespace MyGameDevTools.SceneLoading.Tests public class SceneManager_CancellationTests : SceneTestBase { [UnityTest] - public IEnumerator Cancellation_DuringLoadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfo), token: tokenSource.Token).AsTask()); - tokenSource.Cancel(); - yield return waitTask; - Assert.That(waitTask.Task.IsCompleted); - tokenSource.Dispose(); - } - - [UnityTest] - public IEnumerator Cancellation_DuringLoadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) - { - CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfos), token: tokenSource.Token).AsTask()); - tokenSource.Cancel(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - tokenSource.Dispose(); - } - - [UnityTest] - public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) - { - CancellationTokenSource tokenSource = new(); - SceneParameters parameters = new SceneParameters(sceneInfo); - WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); - yield return waitTask; - - waitTask = new(manager.UnloadAsync(parameters, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -45,14 +19,13 @@ public IEnumerator Cancellation_DuringUnloadScene([ValueSource(typeof(SceneTestE } [UnityTest] - public IEnumerator Cancellation_DuringUnloadScenes([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) + public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - SceneParameters parameters = new SceneParameters(sceneInfos); - WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadAsync(parameters, token: tokenSource.Token).AsTask()); + waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token).AsTask()); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index 5a91433b..0fbc56ab 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -22,87 +22,37 @@ public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func< } [UnityTest] - public IEnumerator Dispose_DuringLoadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfo)).AsTask()); - manager.Dispose(); - yield return waitTask; - Assert.That(waitTask.Task.IsCompleted); - } - - [UnityTest] - public IEnumerator Dispose_DuringLoadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) - { - ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(new SceneParameters(sceneInfos)).AsTask()); - manager.Dispose(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - } - - [UnityTest] - public IEnumerator Dipose_DuringUnloadScene([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) - { - ISceneManager manager = managerCreateFunc(); - SceneParameters parameters = new SceneParameters(sceneInfo); - WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); - yield return waitTask; - - waitTask = new(manager.UnloadAsync(parameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); } [UnityTest] - public IEnumerator Dipose_DuringUnloadScenes([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] sceneInfos) + public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - SceneParameters parameters = new SceneParameters(sceneInfos); - WaitTask waitTask = new(manager.LoadAsync(parameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); yield return waitTask; - waitTask = new(manager.UnloadAsync(parameters).AsTask()); + waitTask = new(manager.UnloadAsync(sceneParameters).AsTask()); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); } [UnityTest] - public IEnumerator Dispose_DuringTransitionToSceneAsync([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - async Awaitable Test() - { - ISceneManager manager = managerCreateFunc(); - await SceneManagerTests.LoadFirstScene(manager).ValueTask; - - var task = manager.TransitionAsync(new SceneParameters(targetScene), loadingScene); - manager.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - } - return Test(); - } - - [UnityTest] - public IEnumerator Dispose_DuringTransitionToScenesAsync([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) { async Awaitable Test() { ISceneManager manager = managerCreateFunc(); await SceneManagerTests.LoadFirstScene(manager).ValueTask; - var task = manager.TransitionAsync(new SceneParameters(targetScenes, 0), loadingScene); + var task = manager.TransitionAsync(sceneParameters, loadingScene); manager.Dispose(); bool canceled = false; diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs new file mode 100644 index 00000000..199b3cb9 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs @@ -0,0 +1,169 @@ +using System.Collections; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Tests +{ + public partial class SceneManagerTests + { + int[] _buildIndexes = new[] { 0, 1, 2, 3 }; + + [UnityTest] + public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(1, true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); + } +#endif + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(1, 0).AsTask(), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 0).AsTask(), _buildIndexes.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]).AsTask(), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]).AsTask(), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]).AsTask(), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + } +#endif + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(1, true), () => manager.UnloadAsync(1), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(_buildIndexes, 0), () => manager.UnloadAsync(_buildIndexes), _buildIndexes.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true), () => manager.UnloadAddressableAsync(_assetReferences[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 0), () => manager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); + } +#endif + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta new file mode 100644 index 00000000..a9a1e3c2 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e7b3d6cfd812bb04c9b151cf3ebb4456 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index 1af21053..ef414855 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -22,34 +22,6 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup public const string ScenePathBase = "Assets/_test"; public const int DefaultTimeout = 3000; - public static readonly ILoadSceneInfo[][] MultipleLoadSceneInfoList = new ILoadSceneInfo[][] - { - new ILoadSceneInfo[] - { - new LoadSceneInfoName(SceneBuilder.SceneNames[0]), - new LoadSceneInfoIndex(1), -#if ENABLE_ADDRESSABLES - new LoadSceneInfoAddress(SceneBuilder.SceneNames[2]), - new LoadSceneInfoAddress(SceneBuilder.SceneNames[3]), -#endif - new LoadSceneInfoName(SceneBuilder.ScenePaths[3]) - }, - // This list of scenes expects two load scene infos that point to the same source scene, - // and validates whether that causes any issues when linking to the target loaded scene. - new ILoadSceneInfo[] - { - new LoadSceneInfoIndex(1), - new LoadSceneInfoName(SceneBuilder.SceneNames[1]), - new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), -#if ENABLE_ADDRESSABLES - // Since we can't test statically with AssetReference, we should at least validate - // that two AsyncOperations with the same addressable source do not cause issues. - new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), - new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), -#endif - } - }; - public static readonly ILoadSceneInfo[] SingleLoadSceneInfoList = new ILoadSceneInfo[] { new LoadSceneInfoName(SceneBuilder.SceneNames[1]), @@ -72,10 +44,21 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup new(SingleLoadSceneInfoList[3], false), new(SingleLoadSceneInfoList[3], true), #endif - new(MultipleLoadSceneInfoList[0], -1), - new(MultipleLoadSceneInfoList[0], 1), - new(MultipleLoadSceneInfoList[1], -1), - new(MultipleLoadSceneInfoList[1], 1), + new(_multipleLoadSceneInfoList[0], -1), + new(_multipleLoadSceneInfoList[0], 1), + new(_multipleLoadSceneInfoList[1], -1), + new(_multipleLoadSceneInfoList[1], 1), + }; + public static readonly SceneParameters[] TransitionSceneParametersList = new SceneParameters[] + { + new(SingleLoadSceneInfoList[0], true), + new(SingleLoadSceneInfoList[1], true), + new(SingleLoadSceneInfoList[2], true), +#if ENABLE_ADDRESSABLES + new(SingleLoadSceneInfoList[3], true), +#endif + new(_multipleLoadSceneInfoList[0], 1), + new(_multipleLoadSceneInfoList[1], 1), }; public static readonly ISceneManager[] SceneManagers = new ISceneManager[] @@ -83,6 +66,34 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup new AdvancedSceneManager(), }; + static readonly ILoadSceneInfo[][] _multipleLoadSceneInfoList = new ILoadSceneInfo[][] + { + new ILoadSceneInfo[] + { + new LoadSceneInfoName(SceneBuilder.SceneNames[0]), + new LoadSceneInfoIndex(1), +#if ENABLE_ADDRESSABLES + new LoadSceneInfoAddress(SceneBuilder.SceneNames[2]), + new LoadSceneInfoAddress(SceneBuilder.SceneNames[3]), +#endif + new LoadSceneInfoName(SceneBuilder.ScenePaths[3]) + }, + // This list of scenes expects two load scene infos that point to the same source scene, + // and validates whether that causes any issues when linking to the target loaded scene. + new ILoadSceneInfo[] + { + new LoadSceneInfoIndex(1), + new LoadSceneInfoName(SceneBuilder.SceneNames[1]), + new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), +#if ENABLE_ADDRESSABLES + // Since we can't test statically with AssetReference, we should at least validate + // that two AsyncOperations with the same addressable source do not cause issues. + new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), + new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), +#endif + } + }; + #if UNITY_EDITOR #if ENABLE_ADDRESSABLES const string _addressableScenePathBase = "Assets/_addressables-test"; diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json index 985a113a..e0fe6fa9 100644 --- a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -34,7 +34,7 @@ { "type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "GenerateTestReferences", - "value": "{\"m_Value\":true}" + "value": "{\"m_Value\":false}" } ] } From 74961037e31f80d3cb8da8326d1b4af567189002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 6 Jan 2025 22:20:02 -0300 Subject: [PATCH 13/53] update text mesh pro content, remove unused assembly references --- .../LiberationSans SDF - Fallback.asset | 16 +- .../Style Sheets/Default Style Sheet.asset | 23 +- .../TextMesh Pro/Resources/TMP Settings.asset | 17 +- Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl | 178 + .../Shaders/SDFFunctions.hlsl.meta | 10 + .../Shaders/TMP_Bitmap-Custom-Atlas.shader | 72 +- .../Shaders/TMP_Bitmap-Mobile.shader | 52 +- Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader | 62 +- .../Shaders/TMP_SDF Overlay.shader | 83 +- .../TextMesh Pro/Shaders/TMP_SDF SSD.shader | 95 +- .../Shaders/TMP_SDF-HDRP LIT.shadergraph | 12074 ++++++++++++++++ .../Shaders/TMP_SDF-HDRP LIT.shadergraph.meta | 10 + .../Shaders/TMP_SDF-HDRP UNLIT.shadergraph | 11759 +++++++++++++++ .../TMP_SDF-HDRP UNLIT.shadergraph.meta | 10 + .../Shaders/TMP_SDF-Mobile Masking.shader | 77 +- .../Shaders/TMP_SDF-Mobile Overlay.shader | 68 +- .../Shaders/TMP_SDF-Mobile SSD.shader | 6 +- .../Shaders/TMP_SDF-Mobile-2-Pass.shader | 389 + .../Shaders/TMP_SDF-Mobile-2-Pass.shader.meta | 9 + .../Shaders/TMP_SDF-Mobile.shader | 26 +- .../Shaders/TMP_SDF-Surface-Mobile.shader | 9 +- .../Shaders/TMP_SDF-Surface.shader | 11 +- .../Shaders/TMP_SDF-URP Lit.shadergraph | 11932 +++++++++++++++ .../Shaders/TMP_SDF-URP Lit.shadergraph.meta | 10 + .../Shaders/TMP_SDF-URP Unlit.shadergraph | 11629 +++++++++++++++ .../TMP_SDF-URP Unlit.shadergraph.meta | 10 + Assets/TextMesh Pro/Shaders/TMP_SDF.shader | 81 +- Assets/TextMesh Pro/Shaders/TMP_Sprite.shader | 77 +- Assets/TextMesh Pro/Shaders/TMPro.cginc.meta | 2 +- .../TextMesh Pro/Shaders/TMPro_Mobile.cginc | 32 +- .../Shaders/TMPro_Properties.cginc | 5 - .../TextMesh Pro/Shaders/TMPro_Surface.cginc | 10 +- .../MyGameDevTools.SceneLoading.asmdef | 16 +- .../MyGameDevTools.SceneLoading.Tests.asmdef | 15 +- Packages/manifest.json | 2 - Packages/packages-lock.json | 14 - 36 files changed, 48503 insertions(+), 388 deletions(-) create mode 100644 Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl create mode 100644 Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph create mode 100644 Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta diff --git a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset index e907cc73..70c5d616 100644 --- a/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset +++ b/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset @@ -160,16 +160,14 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3} m_Name: LiberationSans SDF - Fallback m_EditorClassIdentifier: - hashCode: -1699145518 - material: {fileID: 2180264} - materialHashCode: 462855346 m_Version: 1.1.0 + m_Material: {fileID: 2180264} m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 - m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, - type: 3} m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} m_AtlasPopulationMode: 1 + InternalDynamicOS: 0 m_FaceInfo: + m_FaceIndex: 0 m_FamilyName: Liberation Sans m_StyleName: Regular m_PointSize: 86 @@ -194,7 +192,7 @@ MonoBehaviour: m_AtlasTextures: - {fileID: 28268798066460806} m_AtlasTextureIndex: 0 - m_IsMultiAtlasTexturesEnabled: 0 + m_IsMultiAtlasTexturesEnabled: 1 m_ClearDynamicDataOnBuild: 1 m_UsedGlyphRects: [] m_FreeGlyphRects: @@ -233,15 +231,21 @@ MonoBehaviour: m_KerningTable: kerningPairs: [] m_FontFeatureTable: + m_MultipleSubstitutionRecords: [] + m_LigatureSubstitutionRecords: [] m_GlyphPairAdjustmentRecords: [] + m_MarkToBaseAdjustmentRecords: [] + m_MarkToMarkAdjustmentRecords: [] fallbackFontAssets: [] m_FallbackFontAssetTable: [] m_CreationSettings: sourceFontFileName: sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75 + faceIndex: 0 pointSizeSamplingMode: 0 pointSize: 86 padding: 9 + paddingMode: 0 packingMode: 4 atlasWidth: 512 atlasHeight: 512 diff --git a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset index ceb609b2..018d42f8 100644 --- a/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset +++ b/Assets/TextMesh Pro/Resources/Style Sheets/Default Style Sheet.asset @@ -3,8 +3,9 @@ --- !u!114 &11400000 MonoBehaviour: m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 @@ -12,6 +13,12 @@ MonoBehaviour: m_Name: Default Style Sheet m_EditorClassIdentifier: m_StyleList: + - m_Name: Normal + m_HashCode: -1183493901 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: + m_ClosingTagArray: - m_Name: H1 m_HashCode: 2425 m_OpeningDefinition: <#40ff80>* @@ -19,19 +26,25 @@ MonoBehaviour: m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000 m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 - m_Name: Quote - m_HashCode: 92254330 + m_HashCode: 93368250 m_OpeningDefinition: m_ClosingDefinition: m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000 m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000 + - m_Name: A + m_HashCode: 65 + m_OpeningDefinition: + m_ClosingDefinition: + m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003400000030000000610000003000000066000000660000003e0000003c000000750000003e000000 + m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000 - m_Name: Link - m_HashCode: 2687968 + m_HashCode: 2656128 m_OpeningDefinition: <#40a0ff> m_ClosingDefinition: m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000 m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000 - m_Name: Title - m_HashCode: 98732960 + m_HashCode: 97690656 m_OpeningDefinition: m_ClosingDefinition: m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e0000003c000000620000003e0000003c000000610000006c00000069000000670000006e0000003d00000063000000650000006e0000007400000065000000720000003e000000 diff --git a/Assets/TextMesh Pro/Resources/TMP Settings.asset b/Assets/TextMesh Pro/Resources/TMP Settings.asset index c09a92f1..edfa6c61 100644 --- a/Assets/TextMesh Pro/Resources/TMP Settings.asset +++ b/Assets/TextMesh Pro/Resources/TMP Settings.asset @@ -12,14 +12,17 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2705215ac5b84b70bacc50632be6e391, type: 3} m_Name: TMP Settings m_EditorClassIdentifier: - m_enableWordWrapping: 1 + assetVersion: 2 + m_TextWrappingMode: 1 m_enableKerning: 1 + m_ActiveFontFeatures: 00000000 m_enableExtraPadding: 0 m_enableTintAllSprites: 0 m_enableParseEscapeCharacters: 1 m_EnableRaycastTarget: 1 m_GetFontFeaturesAtRuntime: 1 m_missingGlyphCharacter: 0 + m_ClearDynamicDataOnBuild: 1 m_warningsDisabled: 0 m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_defaultFontAssetPath: Fonts & Materials/ @@ -29,18 +32,18 @@ MonoBehaviour: m_defaultTextMeshProTextContainerSize: {x: 20, y: 5} m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50} m_autoSizeTextContainer: 0 + m_IsTextObjectScaleStatic: 0 m_fallbackFontAssets: [] m_matchMaterialPreset: 1 - m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, - type: 2} + m_HideSubTextObjects: 1 + m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, type: 2} m_defaultSpriteAssetPath: Sprite Assets/ m_enableEmojiSupport: 1 m_MissingCharacterSpriteUnicode: 0 + m_EmojiFallbackTextAssets: [] m_defaultColorGradientPresetsPath: Color Gradient Presets/ - m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, - type: 2} + m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, type: 2} m_StyleSheetsResourcePath: m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3} - m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, - type: 3} + m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, type: 3} m_UseModernHangulLineBreakingRules: 0 diff --git a/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl new file mode 100644 index 00000000..b6119946 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl @@ -0,0 +1,178 @@ +float2 UnpackUV(float uv) +{ + float2 output; + output.x = floor(uv / 4096.0); + output.y = uv - 4096.0 * output.x; + + return output * 0.001953125; +} + +float4 BlendARGB(float4 overlying, float4 underlying) +{ + overlying.rgb *= overlying.a; + underlying.rgb *= underlying.a; + float3 blended = overlying.rgb + ((1 - overlying.a) * underlying.rgb); + float alpha = underlying.a + (1 - underlying.a) * overlying.a; + return float4(blended / alpha, alpha); +} + +float3 GetSpecular(float3 n, float3 l) +{ + float spec = pow(max(0.0, dot(n, l)), _Reflectivity); + return _SpecularColor.rgb * spec * _SpecularPower; +} + +void GetSurfaceNormal_float(texture2D atlas, float textureWidth, float textureHeight, float2 uv, bool isFront, out float3 nornmal) +{ + float3 delta = float3(1.0 / textureWidth, 1.0 / textureHeight, 0.0); + + // Read "height field" + float4 h = float4( + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv - delta.xz).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv + delta.xz).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv - delta.zy).a, + SAMPLE_TEXTURE2D(atlas, SamplerState_Linear_Clamp, uv + delta.zy).a); + + bool raisedBevel = _BevelType; + + h += _BevelOffset; + + float bevelWidth = max(.01, _BevelWidth); + + // Track outline + h -= .5; + h /= bevelWidth; + h = saturate(h + .5); + + if (raisedBevel) h = 1 - abs(h * 2.0 - 1.0); + h = lerp(h, sin(h * 3.141592 / 2.0), float4(_BevelRoundness, _BevelRoundness, _BevelRoundness, _BevelRoundness)); + h = min(h, 1.0 - float4(_BevelClamp, _BevelClamp, _BevelClamp, _BevelClamp)); + h *= _BevelAmount * bevelWidth * _GradientScale * -2.0; + + float3 va = normalize(float3(-1.0, 0.0, h.y - h.x)); + float3 vb = normalize(float3(0.0, 1.0, h.w - h.z)); + + float3 f = float3(1, 1, 1); + if (isFront) f = float3(1, 1, -1); + nornmal = cross(va, vb) * f; +} + +void EvaluateLight_float(float4 faceColor, float3 n, out float4 color) +{ + n.z = abs(n.z); + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), 1.0)); + + float3 col = max(faceColor.rgb, 0) + GetSpecular(n, light)* faceColor.a; + //faceColor.rgb += col * faceColor.a; + col *= 1 - (dot(n, light) * _Diffuse); + col *= lerp(_Ambient, 1, n.z * n.z); + + //fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + //faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + + color = float4(col, faceColor.a); +} + +// Add custom function to handle time in HDRP + + +// +void GenerateUV_float(float2 inUV, float4 transform, float2 animSpeed, out float2 outUV) +{ + outUV = inUV * transform.xy + transform.zw + (animSpeed * _Time.y); +} + +void ComputeUVOffset_float(float texWidth, float texHeight, float2 offset, float SDR, out float2 uvOffset) +{ + uvOffset = float2(-offset.x * SDR / texWidth, -offset.y * SDR / texHeight); +} + +void ScreenSpaceRatio2_float(float4x4 projection, float4 position, float2 objectScale, float screenWidth, float screenHeight, float fontScale, out float SSR) +{ + float2 pixelSize = position.w; + pixelSize /= (objectScale * mul((float2x2)projection, float2(screenWidth, screenHeight))); + SSR = rsqrt(dot(pixelSize, pixelSize)*2) * fontScale; +} + +// UV : Texture coordinate of the source distance field texture +// TextureSize : Size of the source distance field texture +// Filter : Enable perspective filter (soften) +void ScreenSpaceRatio_float(float2 UV, float TextureSize, bool Filter, out float SSR) +{ + if(Filter) + { + float2 a = float2(ddx(UV.x), ddy(UV.x)); + float2 b = float2(ddx(UV.y), ddy(UV.y)); + float s = lerp(dot(a,a), dot(b,b), 0.5); + SSR = rsqrt(s) / TextureSize; + } + else + { + float s = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))); + SSR = s / TextureSize; + } +} + +// SSR : Screen Space Ratio +// SD : Signed Distance (encoded : Distance / SDR + .5) +// SDR : Signed Distance Ratio +// +// IsoPerimeter : Dilate / Contract the shape +void ComputeSDF_float(float SSR, float SD, float SDR, float isoPerimeter, float softness, out float outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5) * SDR; // Signed distance to edge, in Texture space + outAlpha = saturate((d * 2.0 * SSR + 0.5 + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); // Screen pixel coverage (alpha) +} + +void ComputeSDF2_float(float SSR, float SD, float SDR, float2 isoPerimeter, float2 softness, out float2 outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5f) * SDR; + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void ComputeSDF4_float(float SSR, float SD, float SDR, float4 isoPerimeter, float4 softness, out float4 outAlpha) +{ + softness *= SSR * SDR; + float d = (SD - 0.5f) * SDR; + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void ComputeSDF44_float(float SSR, float4 SD, float SDR, float4 isoPerimeter, float4 softness, bool outline, out float4 outAlpha) +{ + softness *= SSR * SDR; + float4 d = (SD - 0.5f) * SDR; + if(outline) d.w = max(max(d.x, d.y), d.z); + outAlpha = saturate((d * 2.0f * SSR + 0.5f + isoPerimeter * SDR * SSR + softness * 0.5) / (1.0 + softness)); +} + +void Composite_float(float4 overlying, float4 underlying, out float4 outColor) +{ + outColor = BlendARGB(overlying, underlying); +} + +// Face only +void Layer1_float(float alpha, float4 color0, out float4 outColor) +{ + color0.a *= alpha; + outColor = color0; +} + +// Face + 1 Outline +void Layer2_float(float2 alpha, float4 color0, float4 color1, out float4 outColor) +{ + color1.a *= alpha.y; + color0.rgb *= color0.a; color1.rgb *= color1.a; + outColor = lerp(color1, color0, alpha.x); + outColor.rgb /= outColor.a; +} + +// Face + 3 Outline +void Layer4_float(float4 alpha, float4 color0, float4 color1, float4 color2, float4 color3, out float4 outColor) +{ + color3.a *= alpha.w; + color0.rgb *= color0.a; color1.rgb *= color1.a; color2.rgb *= color2.a; color3.rgb *= color3.a; + outColor = lerp(lerp(lerp(color3, color2, alpha.z), color1, alpha.y), color0, alpha.x); + outColor.rgb /= outColor.a; +} diff --git a/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta new file mode 100644 index 00000000..001b14e6 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/SDFFunctions.hlsl.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 96de908384869cd409c75efa351d5edf +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader index bab2b2c6..7e0f35c3 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Custom-Atlas.shader @@ -1,26 +1,26 @@ Shader "TextMeshPro/Bitmap Custom Atlas" { Properties { - _MainTex ("Font Atlas", 2D) = "white" {} - _FaceTex ("Font Texture", 2D) = "white" {} - [HDR]_FaceColor ("Text Color", Color) = (1,1,1,1) - - _VertexOffsetX ("Vertex OffsetX", float) = 0 - _VertexOffsetY ("Vertex OffsetY", float) = 0 - _MaskSoftnessX ("Mask SoftnessX", float) = 0 - _MaskSoftnessY ("Mask SoftnessY", float) = 0 - - _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) - _Padding ("Padding", float) = 0 - - _StencilComp("Stencil Comparison", Float) = 8 - _Stencil("Stencil ID", Float) = 0 - _StencilOp("Stencil Operation", Float) = 0 - _StencilWriteMask("Stencil Write Mask", Float) = 255 - _StencilReadMask("Stencil Read Mask", Float) = 255 - - _CullMode("Cull Mode", Float) = 0 - _ColorMask("Color Mask", Float) = 15 + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _Padding ("Padding", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 } SubShader{ @@ -55,15 +55,18 @@ SubShader{ #include "UnityCG.cginc" + #include "UnityUI.cginc" - struct appdata_t { + struct appdata_t + { float4 vertex : POSITION; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - struct v2f { + struct v2f + { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord0 : TEXCOORD0; @@ -81,15 +84,9 @@ SubShader{ uniform float4 _ClipRect; uniform float _MaskSoftnessX; uniform float _MaskSoftnessY; - - float2 UnpackUV(float uv) - { - float2 output; - output.x = floor(uv / 4096); - output.y = uv - 4096 * output.x; - - return output * 0.001953125; - } + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; v2f vert (appdata_t v) { @@ -101,6 +98,10 @@ SubShader{ float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } fixed4 faceColor = v.color; faceColor *= _FaceColor; @@ -108,13 +109,14 @@ SubShader{ OUT.vertex = vPosition; OUT.color = faceColor; OUT.texcoord0 = v.texcoord0; - OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + OUT.texcoord1 = TRANSFORM_TEX(v.texcoord1, _FaceTex); float2 pixelSize = vPosition.w; pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); // Clamp _ClipRect to 16bit. - float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); - OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); return OUT; } diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader index 006a271e..b89e2672 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader @@ -1,25 +1,25 @@ Shader "TextMeshPro/Mobile/Bitmap" { Properties { - _MainTex ("Font Atlas", 2D) = "white" {} - [HDR]_Color ("Text Color", Color) = (1,1,1,1) - _DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0 + _MainTex ("Font Atlas", 2D) = "white" {} + _Color ("Text Color", Color) = (1,1,1,1) + _DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0 - _VertexOffsetX("Vertex OffsetX", float) = 0 - _VertexOffsetY("Vertex OffsetY", float) = 0 - _MaskSoftnessX("Mask SoftnessX", float) = 0 - _MaskSoftnessY("Mask SoftnessY", float) = 0 + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 - _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) - _StencilComp("Stencil Comparison", Float) = 8 - _Stencil("Stencil ID", Float) = 0 - _StencilOp("Stencil Operation", Float) = 0 - _StencilWriteMask("Stencil Write Mask", Float) = 255 - _StencilReadMask("Stencil Read Mask", Float) = 255 + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 - _CullMode("Cull Mode", Float) = 0 - _ColorMask("Color Mask", Float) = 15 + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 } SubShader { @@ -55,15 +55,18 @@ SubShader { #include "UnityCG.cginc" + #include "UnityUI.cginc" - struct appdata_t { + struct appdata_t + { float4 vertex : POSITION; fixed4 color : COLOR; float2 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - struct v2f { + struct v2f + { float4 vertex : POSITION; fixed4 color : COLOR; float2 texcoord0 : TEXCOORD0; @@ -79,6 +82,9 @@ SubShader { uniform float4 _ClipRect; uniform float _MaskSoftnessX; uniform float _MaskSoftnessY; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; v2f vert (appdata_t v) { @@ -88,8 +94,11 @@ SubShader { vert.y += _VertexOffsetY; vert.xy += (vert.w * 0.5) / _ScreenParams.xy; - - OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert)); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } + OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert)); OUT.color = v.color; OUT.color *= _Color; OUT.color.rgb *= _DiffusePower; @@ -99,8 +108,9 @@ SubShader { //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); // Clamp _ClipRect to 16bit. - float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); - OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); return OUT; } diff --git a/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader index 8ce4937a..caa527f7 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader @@ -1,25 +1,25 @@ Shader "TextMeshPro/Bitmap" { Properties { - _MainTex ("Font Atlas", 2D) = "white" {} - _FaceTex ("Font Texture", 2D) = "white" {} - [HDR]_FaceColor ("Text Color", Color) = (1,1,1,1) + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + _FaceColor ("Text Color", Color) = (1,1,1,1) - _VertexOffsetX ("Vertex OffsetX", float) = 0 - _VertexOffsetY ("Vertex OffsetY", float) = 0 - _MaskSoftnessX ("Mask SoftnessX", float) = 0 - _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 - _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) - _StencilComp("Stencil Comparison", Float) = 8 - _Stencil("Stencil ID", Float) = 0 - _StencilOp("Stencil Operation", Float) = 0 - _StencilWriteMask("Stencil Write Mask", Float) = 255 - _StencilReadMask("Stencil Read Mask", Float) = 255 + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 - _CullMode("Cull Mode", Float) = 0 - _ColorMask("Color Mask", Float) = 15 + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 } SubShader{ @@ -54,15 +54,18 @@ SubShader{ #include "UnityCG.cginc" + #include "UnityUI.cginc" - struct appdata_t { + struct appdata_t + { float4 vertex : POSITION; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - struct v2f { + struct v2f + { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord0 : TEXCOORD0; @@ -80,15 +83,9 @@ SubShader{ uniform float4 _ClipRect; uniform float _MaskSoftnessX; uniform float _MaskSoftnessY; - - float2 UnpackUV(float uv) - { - float2 output; - output.x = floor(uv / 4096); - output.y = uv - 4096 * output.x; - - return output * 0.001953125; - } + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; v2f vert (appdata_t v) { @@ -100,6 +97,10 @@ SubShader{ float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } fixed4 faceColor = v.color; faceColor *= _FaceColor; @@ -107,13 +108,14 @@ SubShader{ OUT.vertex = vPosition; OUT.color = faceColor; OUT.texcoord0 = v.texcoord0; - OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + OUT.texcoord1 = TRANSFORM_TEX(v.texcoord1, _FaceTex); float2 pixelSize = vPosition.w; pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); // Clamp _ClipRect to 16bit. - float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); - OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); return OUT; } diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader index c50c5930..757a6173 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader @@ -4,10 +4,10 @@ Properties { _FaceTex ("Face Texture", 2D) = "white" {} _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineTex ("Outline Texture", 2D) = "white" {} _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 @@ -21,7 +21,7 @@ Properties { _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 - [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularColor ("Specular", Color) = (1,1,1,1) _SpecularPower ("Specular", Range(0,4)) = 2.0 _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 _Diffuse ("Diffuse", Range(0,1)) = 0.5 @@ -37,13 +37,13 @@ Properties { _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 - [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) _GlowOffset ("Offset", Range(-1,1)) = 0 _GlowInner ("Inner", Range(0,1)) = 0.05 _GlowOuter ("Outer", Range(0,1)) = 0.05 @@ -127,17 +127,18 @@ SubShader { #include "TMPro_Properties.cginc" #include "TMPro.cginc" - struct vertex_t { + struct vertex_t + { UNITY_VERTEX_INPUT_INSTANCE_ID float4 position : POSITION; float3 normal : NORMAL; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - - struct pixel_t { + struct pixel_t + { UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float4 position : SV_POSITION; @@ -147,16 +148,20 @@ SubShader { float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) float3 viewDir : TEXCOORD3; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float4 texcoord2 : TEXCOORD4; // u,v, scale, bias fixed4 underlayColor : COLOR1; - #endif + #endif + float4 textures : TEXCOORD5; }; // Used by Unity internally to handle Texture Tiling and Offset. - float4 _FaceTex_ST; - float4 _OutlineTex_ST; + uniform float4 _FaceTex_ST; + uniform float4 _OutlineTex_ST; + uniform float _UIMaskSoftnessX; + uniform float _UIMaskSoftnessY; + uniform int _UIVertexColorAlwaysGammaSpace; pixel_t VertShader(vertex_t input) { @@ -167,7 +172,7 @@ SubShader { UNITY_TRANSFER_INSTANCE_ID(input,output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.position; vert.x += _VertexOffsetX; @@ -178,7 +183,7 @@ SubShader { float2 pixelSize = vPosition.w; pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; @@ -188,13 +193,13 @@ SubShader { float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA); - #if GLOW_ON + #if GLOW_ON alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); - #endif + #endif alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float4 underlayColor = _UnderlayColor; underlayColor.rgb *= underlayColor.a; @@ -205,23 +210,28 @@ SubShader { float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 bOffset = float2(x, y); - #endif + #endif // Generate UV for the Masking Texture float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); // Support for texture tiling and offset - float2 textureUV = UnpackUV(input.texcoord1.x); + float2 textureUV = input.texcoord1; float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } output.position = vPosition; output.color = input.color; output.atlas = input.texcoord0; output.param = float4(alphaClip, scale, bias, weight); - output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); #if (UNDERLAY_ON || UNDERLAY_INNER) output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); @@ -239,9 +249,9 @@ SubShader { float c = tex2D(_MainTex, input.atlas).a; - #ifndef UNDERLAY_ON + #ifndef UNDERLAY_ON clip(c - input.param.x); - #endif + #endif float scale = input.param.y; float bias = input.param.z; @@ -261,7 +271,7 @@ SubShader { faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); - #if BEVEL_ON + #if BEVEL_ON float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); float3 n = GetSurfaceNormal(input.atlas, weight, dxy); @@ -278,36 +288,35 @@ SubShader { fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; - #endif + #endif - #if UNDERLAY_ON + #if UNDERLAY_ON float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); - #endif + #endif - #if UNDERLAY_INNER + #if UNDERLAY_INNER float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); - #endif + #endif - #if GLOW_ON + #if GLOW_ON float4 glowColor = GetGlowColor(sd, scale); faceColor.rgb += glowColor.rgb * glowColor.a; - #endif + #endif - // Alternative implementation to UnityGet2DClipping with support for softness. - #if UNITY_UI_CLIP_RECT + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); faceColor *= m.x * m.y; - #endif + #endif - #if UNITY_UI_ALPHACLIP + #if UNITY_UI_ALPHACLIP clip(faceColor.a - 0.001); - #endif + #endif return faceColor * input.color.a; } - ENDCG } } diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader index ed48574d..27c14bc6 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader @@ -4,10 +4,10 @@ Properties { _FaceTex ("Face Texture", 2D) = "white" {} _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineTex ("Outline Texture", 2D) = "white" {} _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 @@ -21,7 +21,7 @@ Properties { _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 - [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularColor ("Specular", Color) = (1,1,1,1) _SpecularPower ("Specular", Range(0,4)) = 2.0 _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 _Diffuse ("Diffuse", Range(0,1)) = 0.5 @@ -37,13 +37,13 @@ Properties { _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 - [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) _GlowOffset ("Offset", Range(-1,1)) = 0 _GlowInner ("Inner", Range(0,1)) = 0.05 _GlowOuter ("Outer", Range(0,1)) = 0.05 @@ -109,7 +109,8 @@ SubShader { Blend One OneMinusSrcAlpha ColorMask[_ColorMask] - Pass { + Pass + { CGPROGRAM #pragma target 3.0 #pragma vertex VertShader @@ -127,17 +128,18 @@ SubShader { #include "TMPro_Properties.cginc" #include "TMPro.cginc" - struct vertex_t { + struct vertex_t + { UNITY_VERTEX_INPUT_INSTANCE_ID float4 position : POSITION; float3 normal : NORMAL; float4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - - struct pixel_t { + struct pixel_t + { UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float4 position : SV_POSITION; @@ -147,18 +149,23 @@ SubShader { float2 mask : TEXCOORD2; // Position in object space(xy) float3 viewDir : TEXCOORD3; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float2 texcoord2 : TEXCOORD4; float4 underlayColor : COLOR1; - #endif + #endif + float4 textures : TEXCOORD5; }; // Used by Unity internally to handle Texture Tiling and Offset. float4 _FaceTex_ST; float4 _OutlineTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; - float4 SRGBToLinear(float4 rgba) { + float4 SRGBToLinear(float4 rgba) + { return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); } @@ -171,7 +178,7 @@ SubShader { UNITY_TRANSFER_INSTANCE_ID(input,output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.position; vert.x += _VertexOffsetX; @@ -182,27 +189,31 @@ SubShader { float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float4 underlayColor = _UnderlayColor; underlayColor.rgb *= underlayColor.a; float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 bOffset = float2(x, y); - #endif + #endif // Generate UV for the Masking Texture float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); // Support for texture tiling and offset - float2 textureUV = UnpackUV(input.texcoord1.x); + float2 textureUV = input.texcoord1; float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } float4 color = input.color; - #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) + #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) color = SRGBToLinear(input.color); - #endif + #endif output.position = vPosition; output.color = color; @@ -210,10 +221,10 @@ SubShader { output.weight = weight; output.mask = half2(vert.xy * 2 - clampedRect.xy - clampedRect.zw); output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) output.texcoord2 = input.texcoord0 + bOffset; output.underlayColor = underlayColor; - #endif + #endif output.textures = float4(faceUV, outlineUV); return output; @@ -226,9 +237,9 @@ SubShader { float c = tex2D(_MainTex, input.atlas).a; - float2 pixelSize = float2(ddx(input.atlas.y), ddy(input.atlas.y)); - pixelSize *= _TextureWidth * .75; - float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1); + float pixelSize = abs(ddx(input.atlas.y)) + abs(ddy(input.atlas.y)); + pixelSize *= _TextureHeight * 0.75; + float scale = 1 / pixelSize * _GradientScale * (_Sharpness + 1); float weight = input.weight; float bias = (.5 - weight) + (.5 / scale); @@ -247,7 +258,7 @@ SubShader { faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); - #if BEVEL_ON + #if BEVEL_ON float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); float3 n = GetSurfaceNormal(input.atlas, weight, dxy); @@ -264,45 +275,45 @@ SubShader { fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; - #endif + #endif - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float bScale = scale; bScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * bScale); float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); - #endif + #endif - #if UNDERLAY_ON + #if UNDERLAY_ON float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; faceColor += input.underlayColor * saturate(d - bBias) * (1 - faceColor.a); - #endif + #endif - #if UNDERLAY_INNER + #if UNDERLAY_INNER float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; faceColor += input.underlayColor * (1 - saturate(d - bBias)) * saturate(1 - sd) * (1 - faceColor.a); - #endif + #endif - #if GLOW_ON + #if GLOW_ON float4 glowColor = GetGlowColor(sd, scale); faceColor.rgb += glowColor.rgb * glowColor.a; - #endif + #endif // Alternative implementation to UnityGet2DClipping with support for softness. - #if UNITY_UI_CLIP_RECT - float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale)); + #if UNITY_UI_CLIP_RECT + half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + float2 maskZW = 0.25 / (0.25 * maskSoftness + 1 / scale); half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW); faceColor *= m.x * m.y; - #endif + #endif - #if UNITY_UI_ALPHACLIP + #if UNITY_UI_ALPHACLIP clip(faceColor.a - 0.001); - #endif + #endif return faceColor * input.color.a; - } - - ENDCG } + ENDCG + } } Fallback "TextMeshPro/Mobile/Distance Field" diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph new file mode 100644 index 00000000..4f7157ca --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph @@ -0,0 +1,12074 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "c417006ffa034c44b79da3dd323165ff" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "6b0cd1bfb339459ca967fa23df287ef0" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "bc782d8e80154073b48a687a07adf60a" + }, + { + "m_Id": "2786e48f93f54a82aee4303ce7b63c82" + }, + { + "m_Id": "7f7d8028b58d4227a4560891be6e7cda" + }, + { + "m_Id": "f5a8bfcec21a4dac9df63993ec53635e" + }, + { + "m_Id": "be58359e488f42e9b5121357d0fa526b" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "bc782d8e80154073b48a687a07adf60a" + }, + { + "m_Id": "2786e48f93f54a82aee4303ce7b63c82" + }, + { + "m_Id": "7f7d8028b58d4227a4560891be6e7cda" + }, + { + "m_Id": "f5a8bfcec21a4dac9df63993ec53635e" + }, + { + "m_Id": "be58359e488f42e9b5121357d0fa526b" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "7cf0e63037a74dc2a9f591225c678ff4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.BuiltinData", + "m_ObjectId": "00996039d61e400a9e854ce591ac35a0", + "m_Distortion": false, + "m_DistortionMode": 0, + "m_DistortionDepthTest": true, + "m_AddPrecomputedVelocity": false, + "m_TransparentWritesMotionVec": false, + "m_DepthOffset": false, + "m_ConservativeDepthOffset": false, + "m_TransparencyFog": true, + "m_AlphaTestShadow": false, + "m_BackThenFrontRendering": false, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_TransparentPerPixelSorting": false, + "m_SupportLodCrossFade": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4828.0, + "y": -2832.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4540.0, + "y": -2749.0, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceText_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "183118ca50814141b7bc3e0cee27fb9b", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.99951171875, + "y": -3197.0, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4311.0, + "y": -3221.0, + "width": 148.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "2786e48f93f54a82aee4303ce7b63c82", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Smoothness", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "9d0c47172bf840a0ac029980ba082af7" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Smoothness" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4177.0, + "y": -2422.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.25, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.0, + "y": -2405.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", + "m_ObjectId": "305e3be306674fcd8bb02273d27ee5b7", + "m_MaterialNeedsUpdateHash": 280372, + "m_SurfaceType": 1, + "m_RenderingPass": 4, + "m_BlendMode": 0, + "m_ZTest": 4, + "m_ZWrite": false, + "m_TransparentCullMode": 2, + "m_OpaqueCullMode": 2, + "m_SortPriority": 0, + "m_AlphaTest": true, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_SupportLodCrossFade": false, + "m_DoubleSidedMode": 0, + "m_DOTSInstancing": false, + "m_CustomVelocity": false, + "m_Tessellation": false, + "m_TessellationMode": 0, + "m_TessellationFactorMinDistance": 20.0, + "m_TessellationFactorMaxDistance": 50.0, + "m_TessellationFactorTriangleSize": 100.0, + "m_TessellationShapeFactor": 0.75, + "m_TessellationBackFaceCullEpsilon": -0.25, + "m_TessellationMaxDisplacement": 0.009999999776482582, + "m_DebugSymbols": false, + "m_Version": 2, + "inspectorFoldoutMask": 9 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 1.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4615.0, + "y": -2422.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4323.99951171875, + "y": -3498.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4309.0, + "y": -2773.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4007.0, + "y": -2395.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitData", + "m_ObjectId": "6238ae56182d404f8563cb88cb801549", + "m_RayTracing": false, + "m_MaterialType": 0, + "m_MaterialTypeMask": 2, + "m_RefractionModel": 0, + "m_SSSTransmission": true, + "m_EnergyConservingSpecular": true, + "m_ClearCoat": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitSubTarget", + "m_ObjectId": "67bc2306558f4f2fa807637aaebaeab4" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "6b0cd1bfb339459ca967fa23df287ef0", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "c417006ffa034c44b79da3dd323165ff" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "703396865b6e4990a0cf1189ea684e5c", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "7564379492aa4c5a927ff3501acdc70d", + "m_Id": 0, + "m_DisplayName": "Normal (Tangent Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalTS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "77991fa631724e0cb32eed66ff017b23", + "m_Id": 0, + "m_DisplayName": "Metallic", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Metallic", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDTarget", + "m_ObjectId": "7cf0e63037a74dc2a9f591225c678ff4", + "m_ActiveSubTarget": { + "m_Id": "67bc2306558f4f2fa807637aaebaeab4" + }, + "m_Datas": [ + { + "m_Id": "00996039d61e400a9e854ce591ac35a0" + }, + { + "m_Id": "305e3be306674fcd8bb02273d27ee5b7" + }, + { + "m_Id": "6238ae56182d404f8563cb88cb801549" + }, + { + "m_Id": "a8c49a47cb934f7e8e4d88fce06df6ff" + } + ], + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDF_HDRPLitShaderGUI", + "m_SupportVFX": false, + "m_SupportLineRendering": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4005.0, + "y": -2797.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f7d8028b58d4227a4560891be6e7cda", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Occlusion", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a00de0d572a84a08a23fe14c2ad5030d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Occlusion" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5800.99951171875, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4793.0, + "y": -2593.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4672.0, + "y": -2481.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9d0c47172bf840a0ac029980ba082af7", + "m_Id": 0, + "m_DisplayName": "Smoothness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Smoothness", + "m_StageCapability": 2, + "m_Value": 0.5, + "m_DefaultValue": 0.5, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4637.0, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4160.0, + "y": -2739.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a00de0d572a84a08a23fe14c2ad5030d", + "m_Id": 0, + "m_DisplayName": "Ambient Occlusion", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Occlusion", + "m_StageCapability": 2, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4611.0, + "y": -2691.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "ffb07af0bca546d8b9bc439d34aa68f5" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4647.0, + "y": -2283.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.LightingData", + "m_ObjectId": "a8c49a47cb934f7e8e4d88fce06df6ff", + "m_NormalDropOffSpace": 0, + "m_BlendPreserveSpecular": true, + "m_ReceiveDecals": true, + "m_ReceiveSSR": true, + "m_ReceiveSSRTransparent": false, + "m_SpecularAA": false, + "m_SpecularOcclusionMode": 0, + "m_OverrideBakedGI": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "e364823e158a407fb48dd7b630c79973" + }, + { + "m_Id": "703396865b6e4990a0cf1189ea684e5c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4146.0, + "y": -2833.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4373.0, + "y": -2715.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "b30617d78dec40a7b8aa7f72dca7f41d", + "m_Id": 0, + "m_DisplayName": "Bent Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BentNormal", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "b4c4676c68bb4752af59e21f896d9470", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "183118ca50814141b7bc3e0cee27fb9b" + }, + { + "m_Id": "f44e4374a48a4996aa60d23d3ae1e9f9" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b911c23b90124d15924551e2730501eb", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "bc782d8e80154073b48a687a07adf60a", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BentNormal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "b30617d78dec40a7b8aa7f72dca7f41d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BentNormal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "be58359e488f42e9b5121357d0fa526b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Metallic", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "77991fa631724e0cb32eed66ff017b23" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Metallic" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.000244140625, + "width": 222.00001525878907, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "b4c4676c68bb4752af59e21f896d9470" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "c417006ffa034c44b79da3dd323165ff", + "m_Guid": { + "m_GuidSerialized": "7a28a011-205c-4fa8-bf4f-8064aa2308b2" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c49cfb8bb96846dc87ee00c0c041a372", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4315.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4783.0, + "y": -2765.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e364823e158a407fb48dd7b630c79973", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4803.0, + "y": -2627.0, + "width": 165.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "b911c23b90124d15924551e2730501eb" + }, + { + "m_Id": "c49cfb8bb96846dc87ee00c0c041a372" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.99951171875, + "y": -3246.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f44e4374a48a4996aa60d23d3ae1e9f9", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f5a8bfcec21a4dac9df63993ec53635e", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalTS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "7564379492aa4c5a927ff3501acdc70d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalTS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ffb07af0bca546d8b9bc439d34aa68f5", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta new file mode 100644 index 00000000..a445e27d --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP LIT.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ca2ed216f98028c4dae6c5224a952b3c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph new file mode 100644 index 00000000..3118dd04 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph @@ -0,0 +1,11759 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "ced40c943add479a86f25f7fb5ed59da" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "469965f1c9284b7eb032d415d6295b2c" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "7cf0e63037a74dc2a9f591225c678ff4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.BuiltinData", + "m_ObjectId": "00996039d61e400a9e854ce591ac35a0", + "m_Distortion": false, + "m_DistortionMode": 0, + "m_DistortionDepthTest": true, + "m_AddPrecomputedVelocity": false, + "m_TransparentWritesMotionVec": false, + "m_DepthOffset": false, + "m_ConservativeDepthOffset": false, + "m_TransparencyFog": true, + "m_AlphaTestShadow": false, + "m_BackThenFrontRendering": false, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_TransparentPerPixelSorting": false, + "m_SupportLodCrossFade": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4824.0, + "y": -2949.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4534.0, + "y": -2747.0, + "width": 150.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.99951171875, + "y": -3197.0, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4311.0, + "y": -3221.0, + "width": 148.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4181.99951171875, + "y": -2415.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitSubTarget", + "m_ObjectId": "29b1a6d4abc94131be838c0bc77892fc" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.25, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.0, + "y": -2405.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", + "m_ObjectId": "305e3be306674fcd8bb02273d27ee5b7", + "m_MaterialNeedsUpdateHash": 1, + "m_SurfaceType": 1, + "m_RenderingPass": 4, + "m_BlendMode": 0, + "m_ZTest": 4, + "m_ZWrite": false, + "m_TransparentCullMode": 2, + "m_OpaqueCullMode": 2, + "m_SortPriority": 0, + "m_AlphaTest": true, + "m_TransparentDepthPrepass": false, + "m_TransparentDepthPostpass": false, + "m_SupportLodCrossFade": false, + "m_DoubleSidedMode": 0, + "m_DOTSInstancing": false, + "m_CustomVelocity": false, + "m_Tessellation": false, + "m_TessellationMode": 0, + "m_TessellationFactorMinDistance": 20.0, + "m_TessellationFactorMaxDistance": 50.0, + "m_TessellationFactorTriangleSize": 100.0, + "m_TessellationShapeFactor": 0.75, + "m_TessellationBackFaceCullEpsilon": -0.25, + "m_TessellationMaxDisplacement": 0.009999999776482582, + "m_DebugSymbols": false, + "m_Version": 2, + "inspectorFoldoutMask": 9 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 1.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4001.0, + "y": -4168.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4613.0, + "y": -2415.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "469965f1c9284b7eb032d415d6295b2c", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "ced40c943add479a86f25f7fb5ed59da" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4323.99951171875, + "y": -3498.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4310.0, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4005.999755859375, + "y": -2395.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitData", + "m_ObjectId": "77ebd01f5b3149ad810a5acbffc85921", + "m_EnableShadowMatte": false, + "m_DistortionOnly": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7b3b88c5975841d6b6d5c3c5515055a0", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDTarget", + "m_ObjectId": "7cf0e63037a74dc2a9f591225c678ff4", + "m_ActiveSubTarget": { + "m_Id": "29b1a6d4abc94131be838c0bc77892fc" + }, + "m_Datas": [ + { + "m_Id": "00996039d61e400a9e854ce591ac35a0" + }, + { + "m_Id": "305e3be306674fcd8bb02273d27ee5b7" + }, + { + "m_Id": "77ebd01f5b3149ad810a5acbffc85921" + } + ], + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDF_HDRPUnlitShaderGUI", + "m_SupportVFX": false, + "m_SupportLineRendering": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4006.000244140625, + "y": -2795.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5802.0, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8a39319405ad44cb8b7aae71c41dcd01", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9327cb5f5e6b46f1bd79f91ef9dca3b7", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4788.0, + "y": -2591.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4670.00048828125, + "y": -2474.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4635.0, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4160.0, + "y": -2771.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9f42c5a9bc2f45baa095a80e7b8b485a", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4606.99951171875, + "y": -2689.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "dcd51c93d3b64f05a938b3334f343654" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4645.00048828125, + "y": -2285.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "f1fb18f75405424884a776bfd24e79e9" + }, + { + "m_Id": "9f42c5a9bc2f45baa095a80e7b8b485a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4146.0, + "y": -2869.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4367.0, + "y": -2713.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "9327cb5f5e6b46f1bd79f91ef9dca3b7" + }, + { + "m_Id": "d804b5a6c657409196addf2b39199a4f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "f68d9dee5cbc43cdb355d8fadae602d3" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4315.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "ced40c943add479a86f25f7fb5ed59da", + "m_Guid": { + "m_GuidSerialized": "af17e4ab-54fe-4482-a9c5-4e4bc9076517" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d804b5a6c657409196addf2b39199a4f", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.0, + "y": -2771.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "dcd51c93d3b64f05a938b3334f343654", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4799.0, + "y": -2625.0, + "width": 165.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f1fb18f75405424884a776bfd24e79e9", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "7b3b88c5975841d6b6d5c3c5515055a0" + }, + { + "m_Id": "8a39319405ad44cb8b7aae71c41dcd01" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.99951171875, + "y": -3246.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "f68d9dee5cbc43cdb355d8fadae602d3", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta new file mode 100644 index 00000000..a2f732a3 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-HDRP UNLIT.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f63d574838ccfb44f84acc05fed0af48 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader index 7019aaf4..603df2c7 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Masking.shader @@ -6,14 +6,14 @@ Shader "TextMeshPro/Mobile/Distance Field - Masking" { Properties { - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 @@ -99,35 +99,41 @@ SubShader { #include "UnityUI.cginc" #include "TMPro_Properties.cginc" - struct vertex_t { + struct vertex_t + { float4 vertex : POSITION; float3 normal : NORMAL; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - struct pixel_t { + struct pixel_t + { float4 vertex : SV_POSITION; fixed4 faceColor : COLOR; fixed4 outlineColor : COLOR1; float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) - #if (UNDERLAY_ON | UNDERLAY_INNER) + + #if (UNDERLAY_ON | UNDERLAY_INNER) float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) - #endif + #endif }; float _MaskWipeControl; float _MaskEdgeSoftness; fixed4 _MaskEdgeColor; bool _MaskInverse; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; pixel_t VertShader(vertex_t input) { - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.vertex; vert.x += _VertexOffsetX; @@ -138,7 +144,7 @@ SubShader { pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; @@ -150,6 +156,10 @@ SubShader { float bias = (0.5 - weight) * scale - 0.5; float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } float opacity = input.color.a; #if (UNDERLAY_ON | UNDERLAY_INNER) opacity = 1.0; @@ -163,7 +173,7 @@ SubShader { outlineColor.rgb *= outlineColor.a; outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); - #if (UNDERLAY_ON | UNDERLAY_INNER) + #if (UNDERLAY_ON | UNDERLAY_INNER) layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); @@ -171,11 +181,12 @@ SubShader { float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 layerOffset = float2(x, y); - #endif + #endif // Generate UV for the Masking Texture float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); // Structure for pixel shader pixel_t output = { @@ -184,11 +195,11 @@ SubShader { outlineColor, float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), half4(scale, bias - outline, bias + outline, bias), - half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), - #if (UNDERLAY_ON | UNDERLAY_INNER) + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) float4(input.texcoord0 + layerOffset, input.color.a, 0), half2(layerScale, layerBias), - #endif + #endif }; return output; @@ -201,41 +212,41 @@ SubShader { half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; half4 c = input.faceColor * saturate(d - input.param.w); - #ifdef OUTLINE_ON + #ifdef OUTLINE_ON c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); c *= saturate(d - input.param.y); - #endif + #endif - #if UNDERLAY_ON + #if UNDERLAY_ON d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); - #endif + #endif - #if UNDERLAY_INNER + #if UNDERLAY_INNER half sd = saturate(d - input.param.z); d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); - #endif + #endif - // Alternative implementation to UnityGet2DClipping with support for softness. - //#if UNITY_UI_CLIP_RECT + // Alternative implementation to UnityGet2DClipping with support for softness. + //#if UNITY_UI_CLIP_RECT half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); c *= m.x * m.y; - //#endif + //#endif - float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); - float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; - a = saturate(t / _MaskEdgeSoftness); - c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a); - c *= a; + float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); + float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; + a = saturate(t / _MaskEdgeSoftness); + c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a); + c *= a; - #if (UNDERLAY_ON | UNDERLAY_INNER) + #if (UNDERLAY_ON | UNDERLAY_INNER) c *= input.texcoord1.z; - #endif + #endif - #if UNITY_UI_ALPHACLIP + #if UNITY_UI_ALPHACLIP clip(c.a - 0.001); - #endif + #endif return c; } diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader index ce82bed5..3edca76c 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile Overlay.shader @@ -6,14 +6,14 @@ Shader "TextMeshPro/Mobile/Distance Field Overlay" { Properties { - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 @@ -93,16 +93,18 @@ SubShader { #include "UnityUI.cginc" #include "TMPro_Properties.cginc" - struct vertex_t { + struct vertex_t + { UNITY_VERTEX_INPUT_INSTANCE_ID float4 vertex : POSITION; float3 normal : NORMAL; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - struct pixel_t { + struct pixel_t + { UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float4 vertex : SV_POSITION; @@ -111,12 +113,17 @@ SubShader { float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) - #if (UNDERLAY_ON | UNDERLAY_INNER) + + #if (UNDERLAY_ON | UNDERLAY_INNER) float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) - #endif + #endif }; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + pixel_t VertShader(vertex_t input) { @@ -127,7 +134,7 @@ SubShader { UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.vertex; vert.x += _VertexOffsetX; @@ -138,7 +145,7 @@ SubShader { pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; @@ -150,10 +157,14 @@ SubShader { float bias = (0.5 - weight) * scale - 0.5; float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } float opacity = input.color.a; - #if (UNDERLAY_ON | UNDERLAY_INNER) + #if (UNDERLAY_ON | UNDERLAY_INNER) opacity = 1.0; - #endif + #endif fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; faceColor.rgb *= faceColor.a; @@ -163,14 +174,14 @@ SubShader { outlineColor.rgb *= outlineColor.a; outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); - #if (UNDERLAY_ON | UNDERLAY_INNER) + #if (UNDERLAY_ON | UNDERLAY_INNER) layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 layerOffset = float2(x, y); - #endif + #endif // Generate UV for the Masking Texture float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); @@ -182,7 +193,8 @@ SubShader { output.outlineColor = outlineColor; output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); output.param = half4(scale, bias - outline, bias + outline, bias); - output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); #if (UNDERLAY_ON || UNDERLAY_INNER) output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); output.underlayParam = half2(layerScale, layerBias); @@ -200,35 +212,35 @@ SubShader { half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; half4 c = input.faceColor * saturate(d - input.param.w); - #ifdef OUTLINE_ON + #ifdef OUTLINE_ON c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); c *= saturate(d - input.param.y); - #endif + #endif - #if UNDERLAY_ON + #if UNDERLAY_ON d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); - #endif + #endif - #if UNDERLAY_INNER + #if UNDERLAY_INNER half sd = saturate(d - input.param.z); d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); - #endif + #endif - // Alternative implementation to UnityGet2DClipping with support for softness. - #if UNITY_UI_CLIP_RECT + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); c *= m.x * m.y; - #endif + #endif - #if (UNDERLAY_ON | UNDERLAY_INNER) + #if (UNDERLAY_ON | UNDERLAY_INNER) c *= input.texcoord1.z; - #endif + #endif - #if UNITY_UI_ALPHACLIP + #if UNITY_UI_ALPHACLIP clip(c.a - 0.001); - #endif + #endif return c; } diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader index df4d5b0b..43b317d3 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile SSD.shader @@ -6,14 +6,14 @@ Shader "TextMeshPro/Mobile/Distance Field SSD" { Properties { - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader new file mode 100644 index 00000000..2c8e8dad --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader @@ -0,0 +1,389 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field - 2 Pass" { + +Properties { + _FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + _OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + // Draw Outline and Underlay + Name "Outline" + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + const float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + const float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + //outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, outline * 2))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = half4(0, 0, 0, 0); + + #if OUTLINE_ON + c = input.outlineColor * saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } + + + // Draw face + Name "Face" + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float4 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half2 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + }; + + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; + + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + const float bold = step(input.texcoord0.w, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half2(scale, bias); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.y); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } + +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta new file mode 100644 index 00000000..75bd98d8 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile-2-Pass.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0178fcb869bafef4690d177d31d17db8 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader index d3f5866c..b899d6e9 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader @@ -6,14 +6,14 @@ Shader "TextMeshPro/Mobile/Distance Field" { Properties { - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayColor ("Border Color", Color) = (0,0,0,.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 @@ -81,6 +81,7 @@ SubShader { Pass { CGPROGRAM + #pragma enable_d3d11_debug_symbols #pragma vertex VertShader #pragma fragment PixShader #pragma shader_feature __ OUTLINE_ON @@ -98,7 +99,7 @@ SubShader { float4 vertex : POSITION; float3 normal : NORMAL; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; @@ -117,6 +118,9 @@ SubShader { #endif }; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; pixel_t VertShader(vertex_t input) { @@ -127,7 +131,7 @@ SubShader { UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.vertex; vert.x += _VertexOffsetX; @@ -138,7 +142,7 @@ SubShader { pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; @@ -150,7 +154,11 @@ SubShader { float bias = (0.5 - weight) * scale - 0.5; float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; - float opacity = input.color.a; + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } + float opacity = input.color.a; #if (UNDERLAY_ON | UNDERLAY_INNER) opacity = 1.0; #endif @@ -182,7 +190,9 @@ SubShader { output.outlineColor = outlineColor; output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); output.param = half4(scale, bias - outline, bias + outline, bias); - output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); #if (UNDERLAY_ON || UNDERLAY_INNER) output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); output.underlayParam = half2(layerScale, layerBias); diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader index be764aeb..68d0dfaa 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface-Mobile.shader @@ -7,15 +7,15 @@ Shader "TextMeshPro/Mobile/Distance Field (Surface)" { Properties { _FaceTex ("Fill Texture", 2D) = "white" {} - [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceColor ("Fill Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineTex ("Outline Texture", 2D) = "white" {} _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 - [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) _GlowOffset ("Offset", Range(-1,1)) = 0 _GlowInner ("Inner", Range(0,1)) = 0.05 _GlowOuter ("Outer", Range(0,1)) = 0.05 @@ -99,7 +99,8 @@ SubShader { #pragma multi_compile_shadowcaster #include "UnityCG.cginc" - struct v2f { + struct v2f + { V2F_SHADOW_CASTER; float2 uv : TEXCOORD1; float2 uv2 : TEXCOORD3; diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader index bcb2bb27..281e60db 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader @@ -4,10 +4,10 @@ Properties { _FaceTex ("Fill Texture", 2D) = "white" {} _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 - [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceColor ("Fill Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineTex ("Outline Texture", 2D) = "white" {} _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 @@ -28,12 +28,12 @@ Properties { _ReflectOutlineColor ("Outline Color", Color) = (0,0,0,1) _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) - [HDR]_SpecColor ("Specular Color", Color) = (0,0,0,1) + _SpecColor ("Specular Color", Color) = (0,0,0,1) _FaceShininess ("Face Shininess", Range(0,1)) = 0 _OutlineShininess ("Outline Shininess", Range(0,1)) = 0 - [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) _GlowOffset ("Offset", Range(-1,1)) = 0 _GlowInner ("Inner", Range(0,1)) = 0.05 _GlowOuter ("Outer", Range(0,1)) = 0.05 @@ -118,7 +118,8 @@ SubShader { #pragma multi_compile_shadowcaster #include "UnityCG.cginc" - struct v2f { + struct v2f + { V2F_SHADOW_CASTER; float2 uv : TEXCOORD1; float2 uv2 : TEXCOORD3; diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph new file mode 100644 index 00000000..7922d393 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph @@ -0,0 +1,11932 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "59a09f50a7ca4cd3a0d248a0f3730b6a" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "7c73ccc923e744b98f19148b971a6090" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + { + "m_Id": "86e21b7b6b7a44238607e41b8a9fb9a4" + }, + { + "m_Id": "0c10df95ee1d4b0a8a00558af49ec45f" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "83c51d5b2f7b4eb785248f419181cb87" + }, + { + "m_Id": "ad3e1d26f4404555a8dd29223caaf1ef" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3749.0 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2506.000244140625, + "y": -3480.0 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "86e21b7b6b7a44238607e41b8a9fb9a4" + }, + { + "m_Id": "0c10df95ee1d4b0a8a00558af49ec45f" + }, + { + "m_Id": "e591df3a1eb94e259b762f2830b407e2" + }, + { + "m_Id": "83c51d5b2f7b4eb785248f419181cb87" + }, + { + "m_Id": "ad3e1d26f4404555a8dd29223caaf1ef" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "94300469581b4924ac7dda496811d45d" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5722.99951171875, + "y": -3827.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4813.0, + "y": -2949.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4536.00048828125, + "y": -2723.000244140625, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0801f576ce79452483b42e485405244d", + "m_Id": 0, + "m_DisplayName": "Smoothness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Smoothness", + "m_StageCapability": 2, + "m_Value": 0.5, + "m_DefaultValue": 0.5, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "0c10df95ee1d4b0a8a00558af49ec45f", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalTS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a0206f980dc6455f84f5a8442838c726" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalTS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5098.99951171875, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "129f271ebc77450994e18f0a30579bf5", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4955.0, + "y": -3487.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3284.0, + "y": -3516.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4292.0, + "y": -3213.000244140625, + "width": 124.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4316.0, + "y": -3247.000244140625, + "width": 148.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4181.99951171875, + "y": -2415.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3350.0, + "y": -3810.0, + "width": 213.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4387.00048828125, + "y": -2381.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6008.99951171875, + "y": -3341.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3423.000244140625, + "y": -3516.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2803.000244140625, + "y": -3520.0, + "width": 140.0, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3ffa095f304e42d2827aa230e2ae3887", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5468.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "4590bfa2a0664b65b6f073bae33a071f", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_ColorMode": 1, + "m_DefaultColor": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4615.00048828125, + "y": -2415.000244140625, + "width": 145.0, + "height": 130.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4308.0, + "y": -3498.000244140625, + "width": 140.0, + "height": 166.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4303.00048828125, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6154.99951171875, + "y": -3169.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "55a3403c16184e63b4e78607a6a20cd8", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5102.99951171875, + "y": -3427.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "59a09f50a7ca4cd3a0d248a0f3730b6a", + "m_Guid": { + "m_GuidSerialized": "3f9e6596-fd53-48cc-96a5-4c4f0cfbb2ba" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4008.999755859375, + "y": -2394.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.5, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5266.99951171875, + "y": -3387.0, + "width": 156.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4791.0, + "y": -3499.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5101.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "7027aaab25924266a063a05df0aa39b3", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3113.000244140625, + "y": -3468.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4961.99951171875, + "y": -3452.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7b144a976914480baf430c0f6f7f4def", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "7c73ccc923e744b98f19148b971a6090", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "59a09f50a7ca4cd3a0d248a0f3730b6a" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4959.0, + "y": -3326.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4006.999755859375, + "y": -2796.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3140.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "836f639bd89d42f9b3a0470c3094815e", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "83c51d5b2f7b4eb785248f419181cb87", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Occlusion", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "944ebbc49c8a4cddb5834e3beab965a2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Occlusion" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5800.99951171875, + "y": -3363.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4081.999755859375, + "y": -3096.0, + "width": 156.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "86e21b7b6b7a44238607e41b8a9fb9a4", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Smoothness", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "0801f576ce79452483b42e485405244d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Smoothness" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6aee1173864e58be589084897a3f35", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5421.99951171875, + "y": -3902.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2983.000244140625, + "y": -3468.0, + "width": 119.99999237060547, + "height": 149.0 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "94300469581b4924ac7dda496811d45d", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "a0b9274619da48a59f26fe58997479ee" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 1, + "m_ZTestMode": 4, + "m_ZWriteControl": 0, + "m_AlphaMode": 0, + "m_RenderFace": 0, + "m_AlphaClip": true, + "m_CastShadows": true, + "m_ReceiveShadows": true, + "m_AdditionalMotionVectorMode": 0, + "m_AlembicMotionVectors": false, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDFShaderGUI", + "m_SupportVFX": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "944ebbc49c8a4cddb5834e3beab965a2", + "m_Id": 0, + "m_DisplayName": "Ambient Occlusion", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Occlusion", + "m_StageCapability": 2, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.00048828125, + "y": -2581.000244140625, + "width": 155.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4670.00048828125, + "y": -2474.000244140625 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3498.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5443.0, + "y": -3315.0, + "width": 144.99998474121095, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4635.00048828125, + "y": -2239.0, + "width": 167.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4152.0, + "y": -2771.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a0206f980dc6455f84f5a8442838c726", + "m_Id": 0, + "m_DisplayName": "Normal (Tangent Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalTS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [], + "m_Space": 3 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalLitSubTarget", + "m_ObjectId": "a0b9274619da48a59f26fe58997479ee", + "m_WorkflowMode": 1, + "m_NormalDropOffSpace": 0, + "m_ClearCoat": false, + "m_BlendModePreserveSpecular": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4606.99951171875, + "y": -2689.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "7027aaab25924266a063a05df0aa39b3" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4628.00048828125, + "y": -2283.0, + "width": 157.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3631.0, + "y": -3810.0, + "width": 230.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "129f271ebc77450994e18f0a30579bf5" + }, + { + "m_Id": "3ffa095f304e42d2827aa230e2ae3887" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "ad3e1d26f4404555a8dd29223caaf1ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Metallic", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "b46afdad84944599b00e887d2ce29cc3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Metallic" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5264.99951171875, + "y": -3142.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4142.0, + "y": -2890.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4367.0, + "y": -2713.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b467be738d0e454995e380cbf526efe3", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b46afdad84944599b00e887d2ce29cc3", + "m_Id": 0, + "m_DisplayName": "Metallic", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Metallic", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5581.99951171875, + "y": -3867.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "7b144a976914480baf430c0f6f7f4def" + }, + { + "m_Id": "836f639bd89d42f9b3a0470c3094815e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5392.0, + "y": -3867.0, + "width": 125.99999237060547, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4446.0, + "y": -2347.0, + "width": 221.99998474121095, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "8e6aee1173864e58be589084897a3f35" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4312.0, + "y": -3179.000244140625, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6179.99951171875, + "y": -3422.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5268.0, + "y": -3261.0, + "width": 159.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5747.99951171875, + "y": -3961.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4776.00048828125, + "y": -2757.000244140625, + "width": 145.0, + "height": 130.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "e591df3a1eb94e259b762f2830b407e2", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Emission", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "4590bfa2a0664b65b6f073bae33a071f" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Emission" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4144.0, + "y": -3369.0, + "width": 244.0, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4778.00048828125, + "y": -2626.0, + "width": 145.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4957.99951171875, + "y": -3204.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3448.000244140625, + "y": -3579.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3849.999755859375, + "y": -3286.0, + "width": 193.0, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6012.99951171875, + "y": -3209.0, + "width": 183.99998474121095, + "height": 100.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "55a3403c16184e63b4e78607a6a20cd8" + }, + { + "m_Id": "b467be738d0e454995e380cbf526efe3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4321.0, + "y": -3281.000244140625, + "width": 153.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4600.0, + "y": -3245.0, + "width": 183.99998474121095, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5254.99951171875, + "y": -3891.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4208.0, + "y": -2371.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta new file mode 100644 index 00000000..54c945eb --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Lit.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a3d800b099a06e0478fb790c5e79057a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph new file mode 100644 index 00000000..d7d31de8 --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph @@ -0,0 +1,11629 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "386c36a1c4c34ea29deb680fb82cfe8b", + "m_Properties": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "4a0041116f73406db7a62ae80ff54ef4" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "bafc3d388c1e444e820897b9a3d6029a" + } + ], + "m_Nodes": [ + { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + }, + { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + }, + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + } + ], + "m_GroupDatas": [ + { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "007c75c776ac4f1babe9cd7ae1fc4f14" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "04dc152dd2ba4d519391577eb1156235" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "105b1ed1aa714e41bbe1ef5472bdb11f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "150533bad8e2424aaa2c74e253af8592" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "19075add867e4757b9520d18fe8de1d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1c4df61c2fea404eb3b87b270d7c59bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e12726617b24675958e942eb62e4b09" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "285f6a9863d54ed2a8150727ad749456" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2a552a0b828f457c911aa19561e410ae" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "2db15d90c2204143b225ec4ef08d0755" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "36f1b4d96f2941c39e5cd95d9c1d2ce6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "39f2f84f30304d859fb07569e2695f60" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "163beb4431c34f538340bc0af0991e6f" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 5 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "42a586e4f6ec40eeaba891b7fd133864" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4488af8ff6a7421298a7e827f567263b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4648b46ad29a4008a80de4f8a5a5b813" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "4f194ff591484e908fc2bcdacbcf2570" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "52798bdb86f6400e86489a7a368e9f8b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "63c7cd57fc3c45a9a97b514fdae32693" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "67a519f507384ff1861df5d8d5b486be" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7444469eb9884253819add9ef96baa25" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7984fd094e1147bdabb4e26fbd3d31c8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "65c8e64a7535466e933eed08a2f77532" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "319916a5921343f7b7eef0e50dc93def" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "7e0fadb2533f496192c1ad3e78642010" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "8135ca333f8f4ea78163743e6ec1f55c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "85b5940eb77e4625812ded7215bab8d7" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "44317f2e371447e2a8d894f8a021a235" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9147636b0cfa466a9b37a013d8f693bf" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3e231021af7b47ba97f2871e7f25d0fe" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "91890fe48ebe4717aea61ecaf3ad4861" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "95928bcb6a284b8d88105a84c2e1d3ce" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9c228fac287d446296b91a4acf5cec59" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7a80e8839f0e4a1d9a6c0814f8793ee6" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d7696aa6d184b4fb9c316a9dec37aee" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9d3c3383d5934a17bf9efbb7fd9e9043" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e6e50a71d9843b49b62ebe1cf7d3d59" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9e87ce9607e14015a3790c528ca5dfda" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "a535f3bcbeb14622bb177eb6f46e76f4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "2ac79705aa9e415dbb74ec215233fd1b" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aa87c72ac0e64469acc34f936f00b3d0" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 4 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 5 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "acd0cd5a177f4a97bf23db7219305e3f" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "51378bae98a94c309785d14cd5cbb453" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "aef5c44f84e04c3185e0b93e95e34204" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b1188549725543d485436c2e921ffbb2" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "7d78a616c2754cc28d1f32cf66ade611" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b163c9f1666644b0bba62cf0e12df7bc" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "9f0de188085746d5a19073da1de85ddb" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b571db753a1948d5a6f1de4e7d0c7238" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bc9afcb18afa4ccc82d2cdc34d3f4641" + }, + "m_SlotId": 6 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c234e5216678436195ee1a5914bc79da" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c7ddee91dc5b48dc828309c77fdb0b88" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c9d7f0dbae7d422985a1cc87c025e76b" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "88253223d2c34ecfab92b0c344048f94" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "d4df208fc23b42f2b52364124f1b661c" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dbcb748279484a4590e53518c49122b8" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "dff7a66b353a4023b29c9d937da77960" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "cdddee3a537c464697357f11b966f9b8" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec184d6d9fb2494897774c9e7d279e6d" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "a455bd79094c4413a7b7dd80ca8b9368" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "ec1f2e8bc9fd4ae38b133c60ee6c49b8" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f23a8b2b7c85478388ff7a8c8a6de740" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "aa3e347d733e48f7b65d8a8847370eec" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f383b24f0bc6434dafe44b3e3d338a63" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "85a1ad8e741e41759002e8cdc8cd0b96" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f3d31c1f18d8491a8ecf5cbc37e4b7db" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "e818605f8f5a4f01bf61caaa33693581" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "f814deb543c24fbbafbcdb5071d96022" + }, + "m_SlotId": 7 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "4abff6ff92fa4a05b203f10580988335" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "109f638d1f9b49d4991d6d21a86d4eb7" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "56c25395796e4d2fbe5c892d428d1620" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "6b2f65c1463f4f7bad16c54a95d2fe75" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "faace8101df943d8956faa31728cb004" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "b4a40cb6acd441acb83cfe0240bf910d" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "fdb77c3e92ee497b88ca5dc46dc45350" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "59bd90a849624124bae6464ee3669aa6" + }, + "m_SlotId": 1 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": -2624.000244140625, + "y": -3709.000244140625 + }, + "m_Blocks": [ + { + "m_Id": "48390d02257d41bf98eace1deaa4c539" + }, + { + "m_Id": "f4ecc442a2d246759f7c2c0412953d28" + }, + { + "m_Id": "7f2e6b5f15364ed9835d67d0cf4f8f65" + } + ] + }, + "m_FragmentContext": { + "m_Position": { + "x": -2624.000244140625, + "y": -3424.000244140625 + }, + "m_Blocks": [ + { + "m_Id": "aca823a8188948c782eddaf0f45e1868" + }, + { + "m_Id": "6e8946a245e842b38231d4a241bfb3ef" + }, + { + "m_Id": "cb7117ecb1d047a8b2cb00ed552cb181" + }, + { + "m_Id": "3c50439118b2496f9e390021b0964606" + } + ] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"fileID\":10210,\"guid\":\"0000000000000000e000000000000000\",\"type\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "TextMeshPro/SRP", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "" + }, + "m_ActiveTargets": [ + { + "m_Id": "94300469581b4924ac7dda496811d45d" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "007c75c776ac4f1babe9cd7ae1fc4f14", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5868.0, + "y": -3787.000244140625, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "1356dc7cbdfa4199a6535d3bbf4cd536" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "013228b0fdf1424097798f0973a9a4fb", + "m_Title": "Face Texture", + "m_Position": { + "x": -4779.494140625, + "y": -2948.97265625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "02559cbe5ad441a3904ccb75ded2b2c5", + "m_Id": 5, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "03182b3263304258b265266325c21f65", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "045c4f6b050549c7a0efb208e6349779", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "04dc152dd2ba4d519391577eb1156235", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4500.0, + "y": -2747.0, + "width": 151.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "3d04f5ba6e7b40d281f22eb424145acd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "04dfcc9ff13a4bf282ed46faec39d15c", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "05805bc6fcc941fd889922555c6c86d7", + "m_Guid": { + "m_GuidSerialized": "fe84e680-4cee-4ca5-be86-2e293a9ba093" + }, + "m_Name": "Ambient Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_05805bc6fcc941fd889922555c6c86d7", + "m_OverrideReferenceName": "_Ambient", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "0580d4b7e3a049049569f4508643a724", + "m_Guid": { + "m_GuidSerialized": "eefb88c5-7665-45dc-b3c2-7cf98b9990d6" + }, + "m_Name": "Softness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_D64EC33D", + "m_OverrideReferenceName": "_Softness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "068ae649e00b40e198ec5a30ad741fab", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0699eea947fc426cbfeb8744cf120222", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "07946387933e416db576b677f0711e5f", + "m_Guid": { + "m_GuidSerialized": "21d612fb-8153-41f8-9e2f-9de044c19fbf" + }, + "m_Name": "_FaceTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1A08AD4A", + "m_OverrideReferenceName": "_FaceTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "082e9706dffc4c188270980d4e44ce0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0848ba750e0341198cf0bbd413e0efe4", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "09b1b86c1c074337a4c439d3a308dd2e", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0a67ca5280214bd794dc0ad66b5710a9", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0b57f2d35157477ab2b29a5aac14ae8b", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "0ba4932e164847878ddb7b7bcff96985", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0c4dc51f26484c26ad88a3fe4002abcd", + "m_Id": 2, + "m_DisplayName": "Color (1)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "0d6a57754b824f6db9cefa6953bc06a9", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "0d7878dd226d4cfb81a991dc312309fc", + "m_Id": 0, + "m_DisplayName": "Underlay Dilate", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget", + "m_ObjectId": "0eeb5490760e492f8c9691086fa00929" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "0f7ffb6d2de4447f9736780cbcee8e07", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "0fac35636fca4474a6afaefc3c757775", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "105b1ed1aa714e41bbe1ef5472bdb11f", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -4233.0, + "width": 158.99998474121095, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "8a08179f99d649d289b8053d5fa0ad22" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "109f638d1f9b49d4991d6d21a86d4eb7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5068.0, + "y": -3182.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "880bb02c6c6b49b18aa6ebc66dc566a0" + }, + { + "m_Id": "1b9cd8f5f4004e2eaf8afbaab803bc04" + }, + { + "m_Id": "b224a1cf80604103ad085c799995f3c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "10a99c07aad742349d258db16838c129", + "m_Id": 1, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1196ae398cc348349ab0c1a23fdab4bd", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1356dc7cbdfa4199a6535d3bbf4cd536", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "14ad19bf20a140dd88d58452d7df688b", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 1.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "150533bad8e2424aaa2c74e253af8592", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4923.99951171875, + "y": -3486.666259765625, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "72fb5a0d7796446b9e2b929cb32facdc" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "163beb4431c34f538340bc0af0991e6f", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3415.000244140625, + "y": -3462.0, + "width": 120.00000762939453, + "height": 149.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "4c334de01ecd429baa7652fc6002536b" + }, + { + "m_Id": "e2d28f29bbac4983a401574480b5ca28" + }, + { + "m_Id": "6a7af6143e114a538663e71f56731a21" + }, + { + "m_Id": "3e25be96bb3747738c238cf3a741d5df" + }, + { + "m_Id": "4907352322c644ebacdf2ca30f2994fd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "19075add867e4757b9520d18fe8de1d0", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4261.33349609375, + "y": -3197.33349609375, + "width": 124.66650390625, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "4c28ee9109014fa086e5de7a3993341d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0580d4b7e3a049049569f4508643a724" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1b9cd8f5f4004e2eaf8afbaab803bc04", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1bdde3efd3b7464b8934c555be0f8a48", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "1be90d4f96a841748b0c95219b12ad27", + "m_Guid": { + "m_GuidSerialized": "4c91c146-43bb-4de8-948a-fbf8b1da10e1" + }, + "m_Name": "Bevel Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_97690701", + "m_OverrideReferenceName": "_BevelOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": -0.5, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "1c4df61c2fea404eb3b87b270d7c59bc", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4280.0, + "y": -3221.33349609375, + "width": 145.3330078125, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "f864c900600e427ba7793f00c715e971" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "1d35fa1fb5004f96a65ace54fbe4f1ad", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1d7d96a5770b4f8ebb162bdbde020bca", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1db37082bf844442804487b4944352de", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "1df58cfa4dad4c449d01ee1c5ea05f2e", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "1e12726617b24675958e942eb62e4b09", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4772.0, + "y": -4404.0, + "width": 145.00001525878907, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "0848ba750e0341198cf0bbd413e0efe4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "1f247658c7ba45fb93c41f51e21acb0d", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "1f46181633594ae0a1fb2adb76b42981", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "200245fc8bbe4826b209ab5f7ffe074c", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "204dacb5a95b424facf11cb6f65bd188", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "215a82c127204988b751de7d3a39b955", + "m_Id": 6, + "m_DisplayName": "Outline", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Outline", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "215b30ae27784ec3a13360a9029af283", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "21a7a380e66d42e780e2a2a1baa630d5", + "m_Guid": { + "m_GuidSerialized": "b2d0099f-e605-49f5-9959-e7cacae37aa3" + }, + "m_Name": "Bevel Type", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_21a7a380e66d42e780e2a2a1baa630d5", + "m_OverrideReferenceName": "_BevelType", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e", + "m_Guid": { + "m_GuidSerialized": "cd167d3a-7465-4d5a-86fc-0f22dc0ef908" + }, + "m_Name": "Outline Color 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5550EB71", + "m_OverrideReferenceName": "_OutlineColor1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "232b1aa09e67479abae141d3c76d3c5b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "256d41e89a204d22951450de1c38051d", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "26e48352a08441bfa694dcea54c06e36", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "281bcee4777040f8a31ee0e10344e98d", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "285f6a9863d54ed2a8150727ad749456", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4145.0, + "y": -2406.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "b42e6dbfbc864097af182cbff5c0c1fb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.IsFrontFaceNode", + "m_ObjectId": "2a552a0b828f457c911aa19561e410ae", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Is Front Face", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4282.0, + "y": -3681.3330078125, + "width": 121.99999237060547, + "height": 77.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "2ef1d888dc9d49e59d6a6950897ddc93" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "2ac79705aa9e415dbb74ec215233fd1b", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Composite (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3277.3330078125, + "y": -3841.33349609375, + "width": 218.666748046875, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "a75f7ac601c446469802fe7754c1f279" + }, + { + "m_Id": "8c38a5d8327f456e9783740c05382619" + }, + { + "m_Id": "facc84930f544fd7a0205a6176b18ac0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Composite", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2b01ea3023e34c94af1754e4dcea8f2e", + "m_Id": 0, + "m_DisplayName": "Face Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2bf5f2fdd2984599b7323d10cfb1d240", + "m_Id": 1, + "m_DisplayName": "Filter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Filter", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "2c10b97b92c947ceb307a93759c0228b", + "m_Guid": { + "m_GuidSerialized": "6be0b8ff-a766-4c6b-a6e4-3a72758ac95f" + }, + "m_Name": "Bevel Amount", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B01DD93E", + "m_OverrideReferenceName": "_BevelAmount", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "2c7a9460724b47daad8df1be144de7c6", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "2d0a269511e34bd1ba9056d2c939dff2", + "m_Guid": { + "m_GuidSerialized": "edbe73dc-53ab-4bc1-9d64-ab36e0e05f03" + }, + "m_Name": "_FaceUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_3A8E0F13", + "m_OverrideReferenceName": "_FaceUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "2db15d90c2204143b225ec4ef08d0755", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4350.0, + "y": -2396.0, + "width": 163.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "def8e0b9d8384982bc5b4c32d877e458" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "2e4eb1ef08bb44178c82e53872485e0f", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "2ef1d888dc9d49e59d6a6950897ddc93", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 2, + "m_Value": true, + "m_DefaultValue": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "30ca940fe2794c949f2a1d4d2caaa446", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "319916a5921343f7b7eef0e50dc93def", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4760.0, + "y": -3245.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "d219977210094c0082c517d8dc00c8bb" + }, + { + "m_Id": "f48f04ad45d046a8b88e71731ed506e7" + }, + { + "m_Id": "e6e80c6b0db545cda26b079a9a78fbb3" + }, + { + "m_Id": "c6bdb985bc16435fa72f5a3c81bb633c" + }, + { + "m_Id": "d1a17e42e7a04dc38984e3c01149445b" + }, + { + "m_Id": "fb15d0ba56d54a6192f11e107aeb5fa8" + }, + { + "m_Id": "c35312edaa2344788b1964ee2f63a236" + }, + { + "m_Id": "c88fcbaeea954a5f9c68c339fa8b604d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "34a67e0fef884f9399e674d9eeaf720c", + "m_Id": 6, + "m_DisplayName": "Color3", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color3", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "34a72a5ebb04402384a4fd3748111a37", + "m_Id": 0, + "m_DisplayName": "Alpha Clip Threshold", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AlphaClipThreshold", + "m_StageCapability": 2, + "m_Value": 0.0010000000474974514, + "m_DefaultValue": 0.5, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3535ae87c6dd4769b52b20d9eca61069", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "35cbea6373dd4e4f8d0fea36e8add392", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "36a0c473c4c04c3a930dd38f3920d410", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "36f1b4d96f2941c39e5cd95d9c1d2ce6", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6314.6669921875, + "y": -3285.3330078125, + "width": 144.6669921875, + "height": 129.33348083496095 + } + }, + "m_Slots": [ + { + "m_Id": "65b3dc13b2b6484283ffe5abfe87a06a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "373f1de8db6c429c9d46c781f741d7a4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3802c81c3be24823aa1d7c9997a33c29", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "3915c1927ffe49f8967304321cfbe497", + "m_Id": 4, + "m_DisplayName": "Atlas", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Atlas", + "m_StageCapability": 3, + "m_BareResource": true, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "39a382d661e2484da71f04c43f48e55f", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "39f2f84f30304d859fb07569e2695f60", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3554.000244140625, + "y": -3462.0, + "width": 116.00000762939453, + "height": 94.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "4b2d9ea03bf64fa19dcae1511d2581da" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "3c50439118b2496f9e390021b0964606", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.AlphaClipThreshold", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3028.0, + "y": -3054.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "34a72a5ebb04402384a4fd3748111a37" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.AlphaClipThreshold" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "3d04f5ba6e7b40d281f22eb424145acd", + "m_Id": 0, + "m_DisplayName": "Face Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3db1608e927e4102a3c3a88e9fcab39a", + "m_Id": 3, + "m_DisplayName": "Transform", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Transform", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3dccd64e7f324bc1a75c1479d7a67c51", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "3e231021af7b47ba97f2871e7f25d0fe", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2934.000244140625, + "y": -3466.0, + "width": 141.33349609375, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "6ccaced3889e4503a9414d808ec33981" + }, + { + "m_Id": "7f3d71a6c96847c099da45f95aafbecb" + }, + { + "m_Id": "d8edec16956c4f15b7d51d6ec10753f4" + }, + { + "m_Id": "39a382d661e2484da71f04c43f48e55f" + }, + { + "m_Id": "8764669016f6442f8152593c18a649d7" + }, + { + "m_Id": "26e48352a08441bfa694dcea54c06e36" + }, + { + "m_Id": "3e94a0d106064bdb864c960512ef4026" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3e25be96bb3747738c238cf3a741d5df", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "3e372195f4bd4845852a37839e5b602d", + "m_Guid": { + "m_GuidSerialized": "60abd046-2a1a-48cd-a0af-2f702f7f53ab" + }, + "m_Name": "_MainTex", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_90CBF488", + "m_OverrideReferenceName": "_MainTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":28684132378477856,\"guid\":\"8f586378b4e144a9851e7b34d9b748ee\",\"type\":2}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "3e94a0d106064bdb864c960512ef4026", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "3ec4797e381747829ef4712c85fcf7a1", + "m_Guid": { + "m_GuidSerialized": "020d65cc-50a8-4b8a-a624-90d7b489f549" + }, + "m_Name": "Specular Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_3ec4797e381747829ef4712c85fcf7a1", + "m_OverrideReferenceName": "_SpecularPower", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 4.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "3fdf4b7bc5d4426492dcc057603ef4a6", + "m_Guid": { + "m_GuidSerialized": "675d2567-3fca-4da6-9462-dfa4924950f1" + }, + "m_Name": "_OutlineUVSpeed", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_D66D89E6", + "m_OverrideReferenceName": "_OutlineUVSpeed", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "400d0b6c95dd4540ad3da3e8cb7e50b2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "41986ac6400d46709d0ef043a67f6b34", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "41b9b79b3859472882bcea393703eec0", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "424dbeeb009344efa29c304c4979e3d6", + "m_Guid": { + "m_GuidSerialized": "314c37de-c6f2-4463-866d-8588f6fc119e" + }, + "m_Name": "Diffuse Shadow", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_424dbeeb009344efa29c304c4979e3d6", + "m_OverrideReferenceName": "_Diffuse", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.30000001192092898, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "42a586e4f6ec40eeaba891b7fd133864", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4934.0, + "y": -4442.99951171875, + "width": 133.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "da7a06d393a44089842070d51d2aa0a6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "42cadae0923e4969b50bbc3f78185934", + "m_Title": "Face + 3 Outlines + Underlay", + "m_Position": { + "x": -5437.0, + "y": -3558.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4328cdbf78b94c038fd614c59bfe1cac", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "44317f2e371447e2a8d894f8a021a235", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Layer1 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4004.999755859375, + "y": -4173.0, + "width": 191.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "10a99c07aad742349d258db16838c129" + }, + { + "m_Id": "b85d677872b44421bf5536f42ba0267c" + }, + { + "m_Id": "75aba700d74d4b2687bf3166cf1da3e2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer1", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "44806230fa384c1e95f9c5918a14f056", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4488af8ff6a7421298a7e827f567263b", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4109.0, + "width": 158.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "66f69ef16eac4eb48357bde804cf3c39" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "4648b46ad29a4008a80de4f8a5a5b813", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4576.0, + "y": -2437.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "b2baf44eae52473cb6cda7b1debece01" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "46fbf3eeb0ea4470869cba7443249295", + "m_Guid": { + "m_GuidSerialized": "be87c5a3-e361-4b95-89c8-911c39a51c0d" + }, + "m_Name": "Outline Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_A0B54237", + "m_OverrideReferenceName": "_OutlineTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "47d020251e9841a5b1f0fd64396026a1", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "48390d02257d41bf98eace1deaa4c539", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "8036d0e6090b456e9b4ea87227868236" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Position" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "484b51c50485473b819c4f05087b32d7", + "m_Title": "Underlay", + "m_Position": { + "x": -5253.0, + "y": -4542.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4907352322c644ebacdf2ca30f2994fd", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "49dabfd48a78475882e664526b483ce1", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "49e7c3ad55ce458797f0e60c950cb965", + "m_Guid": { + "m_GuidSerialized": "31b55db9-0da1-4ec4-af2b-d83747ed5bc4" + }, + "m_Name": "Underlay Offset", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_CE9DEDB3", + "m_OverrideReferenceName": "_UnderlayOffset", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "4a0041116f73406db7a62ae80ff54ef4", + "m_Guid": { + "m_GuidSerialized": "a2d96028-f92f-4076-8376-42249ca40935" + }, + "m_Name": "_ScaleRatioA", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "_ScaleRatioA", + "m_DefaultReferenceName": "_ScaleRatioA", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4a66dcbe712a4d40bd8f355b834594b5", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "4abff6ff92fa4a05b203f10580988335", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4293.3330078125, + "y": -3497.99951171875, + "width": 140.66648864746095, + "height": 166.0 + } + }, + "m_Slots": [ + { + "m_Id": "b015d1b7e4134c59baf6851e7649802c" + }, + { + "m_Id": "d9dc4839ee2847999110bdb234d6041a" + }, + { + "m_Id": "91d6a9a5fbc04ea49075cb51835e7264" + }, + { + "m_Id": "f42ad06b3c6a45d3ab33de904c063412" + }, + { + "m_Id": "ed6c215a65584deeaefad1d2c7743044" + }, + { + "m_Id": "edbee7a8952b46529ac5ad0365775774" + }, + { + "m_Id": "70337a74f6ad4b7bb6befc825219bab1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4b2d9ea03bf64fa19dcae1511d2581da", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4bda5c294e1949138d033640e1d385b4", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4c28ee9109014fa086e5de7a3993341d", + "m_Id": 0, + "m_DisplayName": "Softness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4c334de01ecd429baa7652fc6002536b", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4d1cb1a475df49f9a148195a65f5453a", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "4d9ce48719d143748f9f8e22da6f9ddc", + "m_Id": 5, + "m_DisplayName": "TextureWidth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureWidth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4e64dac49ddc47c3b5b1e27b17a08304", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "4e90ca54c0cc46a18ea600be7c80413a", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "4eb3c00a1ca44e10be833b7ca61ff059", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "4f194ff591484e908fc2bcdacbcf2570", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4255.0, + "y": -2771.0, + "width": 134.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "2b01ea3023e34c94af1754e4dcea8f2e" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "509e6f38505b4b0695b263706a55028f", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "51378bae98a94c309785d14cd5cbb453", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "GetSurfaceNormal (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4067.333251953125, + "y": -3881.99951171875, + "width": 263.9999694824219, + "height": 189.99998474121095 + } + }, + "m_Slots": [ + { + "m_Id": "5b0077c23eae443887872f84227deccc" + }, + { + "m_Id": "3915c1927ffe49f8967304321cfbe497" + }, + { + "m_Id": "4d9ce48719d143748f9f8e22da6f9ddc" + }, + { + "m_Id": "ebd6d75abcb84108bcadbfe7ee5f6244" + }, + { + "m_Id": "ef9738ec7e894772a14e9dce441c16c6" + }, + { + "m_Id": "9eeec1a9713045af8845cea263d5ea48" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GetSurfaceNormal", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "51f76f8a53ad43a4ad028426548ce9ba", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "52798bdb86f6400e86489a7a368e9f8b", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6460.6669921875, + "y": -3113.333251953125, + "width": 135.33349609375, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "1df58cfa4dad4c449d01ee1c5ea05f2e" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "53073e5ea924459fa6681a4943e9f947", + "m_Guid": { + "m_GuidSerialized": "5fdac24e-2d58-4471-80ce-79c3ab9a2564" + }, + "m_Name": "Outline Color 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_DBAB5AEC", + "m_OverrideReferenceName": "_OutlineColor2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.009433984756469727, + "g": 0.02534518577158451, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "54d7a93ffec5490aa4591da23a21b693", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "55ffa45ec3654d5e88089fb40d2b0465", + "m_Id": 4, + "m_DisplayName": "AnimSpeed", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "AnimSpeed", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "56c25395796e4d2fbe5c892d428d1620", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5071.99951171875, + "y": -3427.0, + "width": 129.99998474121095, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "9eb8137a6c2e41bbafdc8b0732dd47a3" + }, + { + "m_Id": "36a0c473c4c04c3a930dd38f3920d410" + }, + { + "m_Id": "068ae649e00b40e198ec5a30ad741fab" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "57abc172afd449e2a4d567f93432507b", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "582d6e289dbe4fdca7cf0307273eaa2f", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "59bd90a849624124bae6464ee3669aa6", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3972.0, + "y": -2385.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "2e4eb1ef08bb44178c82e53872485e0f" + }, + { + "m_Id": "8695190a5e614f2d90081871a8a06fc2" + }, + { + "m_Id": "81bdb47901ef48e5a588c6724b1b0142" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "59cea37675824d99995b370f09cef20a", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "5b0077c23eae443887872f84227deccc", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5b3ff4ee364f4d7a923b530ad60d8762", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5bd258837c514ff7ab0bf7027e762c18", + "m_Guid": { + "m_GuidSerialized": "2d8f3ee9-1307-4b58-a60d-526e86b07109" + }, + "m_Name": "Bevel Roundness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_AB6A015F", + "m_OverrideReferenceName": "_BevelRoundness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5da82bf481f8489ebd05e997f617f51b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": 4.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "5e42524569844befad16fda5a94eb9cb", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "5fbe253f3e444f2aa8ac717f9c856619", + "m_Guid": { + "m_GuidSerialized": "0a61c93f-6430-4aa6-af07-79bc3b411ccd" + }, + "m_Name": "Bevel Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_B50BBFCC", + "m_OverrideReferenceName": "_BevelWidth", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 0.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61133d79a89048c195f54939b2a1d30a", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "61a6ac5f29344d109411f26850ab0a96", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6271438664e74b3fbf723bd6a1f50f8b", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "62bc551cea604e88b7858cc37d96a98a", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "636180f6e0504f2baaa5cc086980cb47", + "m_Guid": { + "m_GuidSerialized": "c1223e37-093d-4d5a-b2b0-cd9cc3e4f88e" + }, + "m_Name": "Outline Offset 1", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector2_636180f6e0504f2baaa5cc086980cb47", + "m_OverrideReferenceName": "_OutlineOffset1", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "63c7cd57fc3c45a9a97b514fdae32693", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5235.99951171875, + "y": -3386.999755859375, + "width": 141.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c422a9a9ff824176aad2241f58c44d0b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "641eda269d7b4da9acb65f8d50035ea9", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "65b3dc13b2b6484283ffe5abfe87a06a", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "65c8e64a7535466e933eed08a2f77532", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4759.99951171875, + "y": -3498.666259765625, + "width": 186.0, + "height": 251.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "256d41e89a204d22951450de1c38051d" + }, + { + "m_Id": "0a67ca5280214bd794dc0ad66b5710a9" + }, + { + "m_Id": "ebbd94a7102a4457a48ac492de3bff14" + }, + { + "m_Id": "6271438664e74b3fbf723bd6a1f50f8b" + }, + { + "m_Id": "c9b722d107ce4cd6a748c883472b9b0f" + }, + { + "m_Id": "74cf69e61bef44589521f1bf2bf3c59a" + }, + { + "m_Id": "6e532f83d1c44e839bcfc5845d3b01d6" + }, + { + "m_Id": "cb5e9f9567e84f8fa5463efc0e256e19" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "66f69ef16eac4eb48357bde804cf3c39", + "m_Id": 0, + "m_DisplayName": "_UnderlayColor", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "67a519f507384ff1861df5d8d5b486be", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4278.0, + "y": -3939.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "c3e6d7c20c184bf39fd8822130e693e7" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "68ec7c31365549d6a8ce883edfc02de2", + "m_Id": 4, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6a7af6143e114a538663e71f56731a21", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "6b2f65c1463f4f7bad16c54a95d2fe75", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5070.0, + "y": -3301.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "1d35fa1fb5004f96a65ace54fbe4f1ad" + }, + { + "m_Id": "fa6de3be9f5b4411b5081b49e645f424" + }, + { + "m_Id": "400d0b6c95dd4540ad3da3e8cb7e50b2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6ccaced3889e4503a9414d808ec33981", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6dfc1177dd0541a7a780fbf911ad1956", + "m_Id": 0, + "m_DisplayName": "_OutlineTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e13f3cd573c467a94379f45d96cb690", + "m_Id": 2, + "m_DisplayName": "SSR", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "6e532f83d1c44e839bcfc5845d3b01d6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "6e8946a245e842b38231d4a241bfb3ef", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.BaseColor", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3026.0, + "y": -3110.0, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "ef0b93f78372439696f50711eaf57d90" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.BaseColor" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "6fbdcc5a972b4fa883dc5f21e525a376", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "70337a74f6ad4b7bb6befc825219bab1", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "712da461f71a454db59d349f752d41ee", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "71dd947935b64ce38f0d25406dde447b", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "724e17584e97443e9e285dfa7253c8e3", + "m_Id": 0, + "m_DisplayName": "Alpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 2, + "m_Value": 0.15000000596046449, + "m_DefaultValue": 1.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "72fb5a0d7796446b9e2b929cb32facdc", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "7444469eb9884253819add9ef96baa25", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4298.0, + "y": -3809.99951171875, + "width": 144.66648864746095, + "height": 129.33323669433595 + } + }, + "m_Slots": [ + { + "m_Id": "03182b3263304258b265266325c21f65" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "748c31bbcecc4b30bec2e42c0612175b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "74b41464cbed4e9e8e23af5ab9be40cf", + "m_Guid": { + "m_GuidSerialized": "41afbdcb-f3ae-4340-8973-1c1998c992a2" + }, + "m_Name": "Outline Offset 2", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset2", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "74cf69e61bef44589521f1bf2bf3c59a", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "757174b6f25040fdbb20355a21752222", + "m_Id": 0, + "m_DisplayName": "Outline Offset 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "75aba700d74d4b2687bf3166cf1da3e2", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "75c5657544c648058b20cea090f48dbf", + "m_Id": 0, + "m_DisplayName": "_OutlineUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "767769f736d5478cba5f10a415e28e7f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "773b90134e894e429203c0c83e80b9de", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "77e28f3e930b4c249145630ec961af95", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "79147f6986644769b58d9ed64fe771e1", + "m_Id": 0, + "m_DisplayName": "OutlineMode", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7984fd094e1147bdabb4e26fbd3d31c8", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3244.000244140625, + "y": -3414.0, + "width": 130.0, + "height": 118.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "082e9706dffc4c188270980d4e44ce0f" + }, + { + "m_Id": "f2a351a5375c441b8d9ab7e2c9545a77" + }, + { + "m_Id": "41986ac6400d46709d0ef043a67f6b34" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "7a046f410ce64aa88438b0bfd412c045", + "m_Guid": { + "m_GuidSerialized": "d47271f5-5a84-47bf-a09e-c825d2aeb013" + }, + "m_Name": "Outline Color 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_551702C5", + "m_OverrideReferenceName": "_OutlineColor3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "7a0f504e4175406dbd8134250f4e350b", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7a80e8839f0e4a1d9a6c0814f8793ee6", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4931.0, + "y": -3452.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "6fbdcc5a972b4fa883dc5f21e525a376" + }, + { + "m_Id": "0ba4932e164847878ddb7b7bcff96985" + }, + { + "m_Id": "9178663316db43d582f1c4a127d307c6" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7acfafd73b8c4dfab8c55c18a887e087", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "7b8a19bd115e4167a25b59cb3218a817", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 1.0, + "w": 1.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "7c27ccb2c2dc4ca59c5438c3358630ca", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "7d7696aa6d184b4fb9c316a9dec37aee", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4928.0, + "y": -3326.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "4d1cb1a475df49f9a148195a65f5453a" + }, + { + "m_Id": "47d020251e9841a5b1f0fd64396026a1" + }, + { + "m_Id": "62bc551cea604e88b7858cc37d96a98a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "7d78a616c2754cc28d1f32cf66ade611", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3973.0, + "y": -2796.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "d9bcb754db834583b6518c5ed5152114" + }, + { + "m_Id": "861d4258049a4a3e8164f7297090f88e" + }, + { + "m_Id": "a7c06457d7454693a8bc3dc95257b2c2" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "7e0fadb2533f496192c1ad3e78642010", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4188.0, + "width": 173.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d48c3871e3064027a10ae9f4babd3be0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "7f2e6b5f15364ed9835d67d0cf4f8f65", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Tangent", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2586.0, + "y": -3592.0, + "width": 200.0, + "height": 41.0 + } + }, + "m_Slots": [ + { + "m_Id": "85ff8667d72947edada4e9fb4ff60559" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Tangent" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "7f3d71a6c96847c099da45f95aafbecb", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PositionMaterialSlot", + "m_ObjectId": "8036d0e6090b456e9b4ea87227868236", + "m_Id": 0, + "m_DisplayName": "Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Position", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "80e665a5eeb64730a51742f698bf0d48", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "8135ca333f8f4ea78163743e6ec1f55c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4050.666259765625, + "y": -3139.99951171875, + "width": 121.99999237060547, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "d6a6a119394e4082a11bc024a6e42ef8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "81bdb47901ef48e5a588c6724b1b0142", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "81e8ed0534534674a74263e6161a2a1a", + "m_Guid": { + "m_GuidSerialized": "78aab961-c4a8-41f3-b203-1239c3b33b13" + }, + "m_Name": "Underlay Dilate", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_D48690B9", + "m_OverrideReferenceName": "_UnderlayDilate", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "82af2db1018543d7832af96c1cfc981f", + "m_Guid": { + "m_GuidSerialized": "37906c7b-9a3a-454b-a62a-9aa097e64bde" + }, + "m_Name": "Light Angle", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_82af2db1018543d7832af96c1cfc981f", + "m_OverrideReferenceName": "_LightAngle", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 6.28000020980835 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "82d5443fe54d4a3b9420f8745d00a632", + "m_Id": 5, + "m_DisplayName": "Softness", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Softness", + "m_StageCapability": 3, + "m_Value": 8.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "849275cac05e4ca8bd0b38ab7ae43bf8", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "84dc74cdbd8c45e1b189e4fd9a69942d", + "m_Id": 0, + "m_DisplayName": "Outline Offset 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "85a1ad8e741e41759002e8cdc8cd0b96", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "ScreenSpaceRatio (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6112.0, + "y": -3308.0, + "width": 258.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e13f3cd573c467a94379f45d96cb690" + }, + { + "m_Id": "8e6ed600f6504f4083092f5b511e44c4" + }, + { + "m_Id": "93b161cce4504cb79c97b6d8db178de7" + }, + { + "m_Id": "2bf5f2fdd2984599b7323d10cfb1d240" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ScreenSpaceRatio", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "85b5940eb77e4625812ded7215bab8d7", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4050.666259765625, + "y": -3095.99951171875, + "width": 121.99999237060547, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "ada023d617104472b8ab75a81558c0a1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.TangentMaterialSlot", + "m_ObjectId": "85ff8667d72947edada4e9fb4ff60559", + "m_Id": 0, + "m_DisplayName": "Tangent", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Tangent", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "861d4258049a4a3e8164f7297090f88e", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "867a4ae13c0d4a028c71bc1063824c14", + "m_Guid": { + "m_GuidSerialized": "d483c212-0a30-4f6d-b94d-9abbc83a6522" + }, + "m_Name": "Outline Width", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_C68C9E14", + "m_OverrideReferenceName": "_IsoPerimeter", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 2, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "8695190a5e614f2d90081871a8a06fc2", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8764669016f6442f8152593c18a649d7", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "880bb02c6c6b49b18aa6ebc66dc566a0", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "88253223d2c34ecfab92b0c344048f94", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "ComputeSDF (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4226.0, + "y": -4323.0, + "width": 227.99998474121095, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "c52a1744a9a14989b0ae452ad6de6061" + }, + { + "m_Id": "a03db80c558b4f87a330c5ae0a9443a5" + }, + { + "m_Id": "8f1b1d1e8ff24b3284993e52354e54fa" + }, + { + "m_Id": "5da82bf481f8489ebd05e997f617f51b" + }, + { + "m_Id": "82d5443fe54d4a3b9420f8745d00a632" + }, + { + "m_Id": "61133d79a89048c195f54939b2a1d30a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8902cb30b1684db8b996562e0140cb18", + "m_Id": 0, + "m_DisplayName": "UV_1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV_1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8a08179f99d649d289b8053d5fa0ad22", + "m_Id": 0, + "m_DisplayName": "Underlay Offset", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8a5d204e1abd4f6894607d1a497f6e69", + "m_Id": 3, + "m_DisplayName": "Texel Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8b66f4e6bc9d4662b3218ac33a69839f", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "8c38a5d8327f456e9783740c05382619", + "m_Id": 3, + "m_DisplayName": "Color2", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color2", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8cbd81814903479ea1d3151c1f38183e", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "8cf8aae64c1d443f9303126886b40f17", + "m_Guid": { + "m_GuidSerialized": "8d78c9a5-aaef-41fb-af68-2358e401d7ac" + }, + "m_Name": "_UnderlayColor", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_2F5FE804", + "m_OverrideReferenceName": "_UnderlayColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "8e6ed600f6504f4083092f5b511e44c4", + "m_Id": 0, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector2ShaderProperty", + "m_ObjectId": "8ed907a2cc7949b68a283ae243ea1977", + "m_Guid": { + "m_GuidSerialized": "36803443-a9bc-4f3c-a4f2-7d66a5417ac1" + }, + "m_Name": "Outline Offset 3", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "", + "m_OverrideReferenceName": "_OutlineOffset3", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "8f1b1d1e8ff24b3284993e52354e54fa", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9147636b0cfa466a9b37a013d8f693bf", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5567.0, + "y": -3862.000244140625, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a4f471e3221c4134b291bd9d2ba22db6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "9178663316db43d582f1c4a127d307c6", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "91890fe48ebe4717aea61ecaf3ad4861", + "m_Group": { + "m_Id": "ecf16c34d46f4502ac601f0c38c7576b" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3114.000244140625, + "y": -3414.0, + "width": 120.00000762939453, + "height": 149.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "3dccd64e7f324bc1a75c1479d7a67c51" + }, + { + "m_Id": "e444f2c81d1e48329fa2c91005277e8d" + }, + { + "m_Id": "b2c26292b7434733878a9b042f44de89" + }, + { + "m_Id": "964fea1fd4b24f4daf5bef84c4b45118" + }, + { + "m_Id": "deac82280a2b43078e0e40863e2d974c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "91d6a9a5fbc04ea49075cb51835e7264", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "928621a3ca2d41c89a10336bbbc81ddc", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "93b161cce4504cb79c97b6d8db178de7", + "m_Id": 3, + "m_DisplayName": "TextureSize", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureSize", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "94300469581b4924ac7dda496811d45d", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "0eeb5490760e492f8c9691086fa00929" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 1, + "m_ZTestMode": 4, + "m_ZWriteControl": 0, + "m_AlphaMode": 0, + "m_RenderFace": 0, + "m_AlphaClip": true, + "m_CastShadows": true, + "m_ReceiveShadows": true, + "m_AdditionalMotionVectorMode": 0, + "m_AlembicMotionVectors": false, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "TMPro.EditorUtilities.TMP_SDFShaderGUI", + "m_SupportVFX": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "945b45993dd84a979755b98c48138f72", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "952d0fa5cd744df0b434cd38e9a90b93", + "m_Guid": { + "m_GuidSerialized": "ce395871-ddeb-47c3-a31d-07855800c197" + }, + "m_Name": "_UnderlaySoftness", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_F2B9E3EF", + "m_OverrideReferenceName": "_UnderlaySoftness", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "95928bcb6a284b8d88105a84c2e1d3ce", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4744.0, + "y": -2591.0, + "width": 155.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "d880558893fb442b9320cf55885d1117" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "964fea1fd4b24f4daf5bef84c4b45118", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "98934a69591249d5b8b92b39045359a3", + "m_Title": "Outline1 Texture", + "m_Position": { + "x": -4746.0, + "y": -2497.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "998db5e5901e45b29040eb2099370071", + "m_Guid": { + "m_GuidSerialized": "6f383614-f2ad-4269-be8f-87b0ecb03cf0" + }, + "m_Name": "Bevel Clamp", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_5BD7E808", + "m_OverrideReferenceName": "_BevelClamp", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 0.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "9c228fac287d446296b91a4acf5cec59", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4569.0, + "y": -3498.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "582d6e289dbe4fdca7cf0307273eaa2f" + }, + { + "m_Id": "1db37082bf844442804487b4944352de" + }, + { + "m_Id": "8b66f4e6bc9d4662b3218ac33a69839f" + }, + { + "m_Id": "4a66dcbe712a4d40bd8f355b834594b5" + }, + { + "m_Id": "a0285c9c381a49cba194709efa0a7c85" + }, + { + "m_Id": "b2728d0dd3ce40678867c94a7d977916" + }, + { + "m_Id": "e141833aa78b4fd59ecad949beb43a78" + }, + { + "m_Id": "51f76f8a53ad43a4ad028426548ce9ba" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "9c26fdddba244d36a854298c00473247", + "m_Id": 3, + "m_DisplayName": "SDR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SDR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "9d3c3383d5934a17bf9efbb7fd9e9043", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5412.0, + "y": -3315.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "232b1aa09e67479abae141d3c76d3c5b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e6e50a71d9843b49b62ebe1cf7d3d59", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4486.0, + "y": -3865.99951171875, + "width": 135.3330078125, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "3535ae87c6dd4769b52b20d9eca61069" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "9e87ce9607e14015a3790c528ca5dfda", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4598.0, + "y": -2251.0, + "width": 167.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "75c5657544c648058b20cea090f48dbf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "9eb8137a6c2e41bbafdc8b0732dd47a3", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", + "m_ObjectId": "9eeec1a9713045af8845cea263d5ea48", + "m_Id": 6, + "m_DisplayName": "IsFront", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "IsFront", + "m_StageCapability": 3, + "m_Value": false, + "m_DefaultValue": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "9f0de188085746d5a19073da1de85ddb", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4118.0, + "y": -2771.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "7c27ccb2c2dc4ca59c5438c3358630ca" + }, + { + "m_Id": "373f1de8db6c429c9d46c781f741d7a4" + }, + { + "m_Id": "fd0b096ed5b74f9e9ec51327be200731" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a0285c9c381a49cba194709efa0a7c85", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a03db80c558b4f87a330c5ae0a9443a5", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a161b772c7564eee804e3d58f6cb9944", + "m_Id": 4, + "m_DisplayName": "Texel Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Texel Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "a3f8b6e8ae7f48e2989a029904401502", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 1, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "a455bd79094c4413a7b7dd80ca8b9368", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4573.0, + "y": -2689.0, + "width": 222.0, + "height": 142.0 + } + }, + "m_Slots": [ + { + "m_Id": "4e90ca54c0cc46a18ea600be7c80413a" + }, + { + "m_Id": "2c7a9460724b47daad8df1be144de7c6" + }, + { + "m_Id": "55ffa45ec3654d5e88089fb40d2b0465" + }, + { + "m_Id": "e495a9f7a11f4eb89334e83be154ceb9" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateShaderProperty", + "m_ObjectId": "a4ad98d8828c424384229c344ebe2ed0", + "m_Guid": { + "m_GuidSerialized": "f98fc1a2-bb81-4bd1-a207-23d3a90d518e" + }, + "m_Name": "SamplerState", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "SamplerState_a4ad98d8828c424384229c344ebe2ed0", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": false, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_filter": 0, + "m_wrap": 1, + "m_anisotropic": 0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a4f471e3221c4134b291bd9d2ba22db6", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "a535f3bcbeb14622bb177eb6f46e76f4", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4608.0, + "y": -2293.0, + "width": 177.00001525878907, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "6dfc1177dd0541a7a780fbf911ad1956" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "a6bbb32e8d884be9bb36db91fe4b81b1", + "m_Guid": { + "m_GuidSerialized": "6aa76edf-7b80-46ac-add4-406cf1d85493" + }, + "m_Name": "_GradientScale", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_EAE27356", + "m_OverrideReferenceName": "_GradientScale", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 1, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 10.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "a6c38edd2e8743a9b057ba8452b9f129", + "m_Guid": { + "m_GuidSerialized": "9fc942ee-4a1d-4ced-a5a6-81893e3ddb63" + }, + "m_Name": "Light Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_a6c38edd2e8743a9b057ba8452b9f129", + "m_OverrideReferenceName": "_SpecularColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "a75f7ac601c446469802fe7754c1f279", + "m_Id": 0, + "m_DisplayName": "Color1", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color1", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "a7942746b5564dc7bbbae1deb2403022", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "a7c06457d7454693a8bc3dc95257b2c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa2794b8f0e24bf281d22e0fef0647be", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "aa3e347d733e48f7b65d8a8847370eec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "EvaluateLight (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3633.000244140625, + "y": -3805.000244140625, + "width": 179.00001525878907, + "height": 118.00000762939453 + } + }, + "m_Slots": [ + { + "m_Id": "0699eea947fc426cbfeb8744cf120222" + }, + { + "m_Id": "0c4dc51f26484c26ad88a3fe4002abcd" + }, + { + "m_Id": "d5173cc3c6cd4f1998550f3187a3e9c8" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "EvaluateLight", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aa87c72ac0e64469acc34f936f00b3d0", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4225.0, + "width": 193.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "0d7878dd226d4cfb81a991dc312309fc" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "abd59150589b436cadf8c9e6f43ccb8e", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "aca823a8188948c782eddaf0f45e1868", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.NormalOS", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -2542.0, + "y": -3404.000244140625, + "width": 200.0, + "height": 40.66650390625 + } + }, + "m_Slots": [ + { + "m_Id": "e386b183a18245a796b024022f7f3074" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.NormalOS" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "acd0cd5a177f4a97bf23db7219305e3f", + "m_Group": { + "m_Id": "d258902c6ec74942afdb9ebf8c1d07f8" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4348.0, + "y": -3905.99951171875, + "width": 185.33299255371095, + "height": 101.33324432373047 + } + }, + "m_Slots": [ + { + "m_Id": "945b45993dd84a979755b98c48138f72" + }, + { + "m_Id": "e51a636b2621440eb94cc802c1cf4bfc" + }, + { + "m_Id": "1bdde3efd3b7464b8934c555be0f8a48" + }, + { + "m_Id": "8a5d204e1abd4f6894607d1a497f6e69" + }, + { + "m_Id": "a161b772c7564eee804e3d58f6cb9944" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ada023d617104472b8ab75a81558c0a1", + "m_Id": 0, + "m_DisplayName": "Outline Color 3", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "aef5c44f84e04c3185e0b93e95e34204", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5233.99951171875, + "y": -3141.999755859375, + "width": 143.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "84dc74cdbd8c45e1b189e4fd9a69942d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b000f852aa984e9dae25b125a4607f4e", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b015d1b7e4134c59baf6851e7649802c", + "m_Id": 0, + "m_DisplayName": "R", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "b0b352c4503a43d083a64e57352b29a0", + "m_Guid": { + "m_GuidSerialized": "01cfcc78-60aa-4f71-a1e3-8d8df6dae253" + }, + "m_Name": "Reflectivity Power", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_b0b352c4503a43d083a64e57352b29a0", + "m_OverrideReferenceName": "_Reflectivity", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 5.0, + "m_FloatType": 1, + "m_RangeValues": { + "x": 5.0, + "y": 15.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.VertexColorNode", + "m_ObjectId": "b1188549725543d485436c2e921ffbb2", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Vertex Color", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4108.0, + "y": -2890.0, + "width": 116.0, + "height": 94.0 + } + }, + "m_Slots": [ + { + "m_Id": "281bcee4777040f8a31ee0e10344e98d" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "b163c9f1666644b0bba62cf0e12df7bc", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4333.0, + "y": -2713.0, + "width": 180.0, + "height": 180.0 + } + }, + "m_Slots": [ + { + "m_Id": "cce40479b6284b6fa3174db9f09d0ac9" + }, + { + "m_Id": "80e665a5eeb64730a51742f698bf0d48" + }, + { + "m_Id": "1f46181633594ae0a1fb2adb76b42981" + }, + { + "m_Id": "8cbd81814903479ea1d3151c1f38183e" + }, + { + "m_Id": "cfaf3f3a5a1146e194cddad30c95aada" + }, + { + "m_Id": "b43489e37a5c4df88f15844292a55ec7" + }, + { + "m_Id": "cd7281fb41aa4e61ac0fdf71d4f4bd46" + }, + { + "m_Id": "f01d52cdcb1647aab35782b4af535efd" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 1, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "b224a1cf80604103ad085c799995f3c2", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b2728d0dd3ce40678867c94a7d977916", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b2baf44eae52473cb6cda7b1debece01", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b2c26292b7434733878a9b042f44de89", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b42e6dbfbc864097af182cbff5c0c1fb", + "m_Id": 0, + "m_DisplayName": "Outline Color 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "b43489e37a5c4df88f15844292a55ec7", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"fileID\":-2362172177983852347,\"guid\":\"dda5bcb0d1e9515498f6e4e038bbefe6\",\"type\":2}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.MultiplyNode", + "m_ObjectId": "b4a40cb6acd441acb83cfe0240bf910d", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Multiply", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4750.99951171875, + "y": -4274.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "d0b10e52e21941b183f5f635894c76c8" + }, + { + "m_Id": "0d6a57754b824f6db9cefa6953bc06a9" + }, + { + "m_Id": "773b90134e894e429203c0c83e80b9de" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "b571db753a1948d5a6f1de4e7d0c7238", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5727.0, + "y": -3827.000244140625, + "width": 184.0, + "height": 101.0 + } + }, + "m_Slots": [ + { + "m_Id": "5b3ff4ee364f4d7a923b530ad60d8762" + }, + { + "m_Id": "c183b5bd9bbe45089f93996e73110918" + }, + { + "m_Id": "1196ae398cc348349ab0c1a23fdab4bd" + }, + { + "m_Id": "1d7d96a5770b4f8ebb162bdbde020bca" + }, + { + "m_Id": "49dabfd48a78475882e664526b483ce1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b691728a389a417d9b4f2d02541209c2", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "b7f9ac55517141868bfb9d2ad6429792", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "b85d677872b44421bf5536f42ba0267c", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "bafc3d388c1e444e820897b9a3d6029a", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "dc75c4e3a1bc4bb0a128086c2b0679a5" + }, + { + "m_Id": "867a4ae13c0d4a028c71bc1063824c14" + }, + { + "m_Id": "22b7f3c2bb7b48c0a7fdeb50e33e7d5e" + }, + { + "m_Id": "53073e5ea924459fa6681a4943e9f947" + }, + { + "m_Id": "7a046f410ce64aa88438b0bfd412c045" + }, + { + "m_Id": "636180f6e0504f2baaa5cc086980cb47" + }, + { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + }, + { + "m_Id": "8ed907a2cc7949b68a283ae243ea1977" + }, + { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + }, + { + "m_Id": "0580d4b7e3a049049569f4508643a724" + }, + { + "m_Id": "c9ec735d1a1046769e5601b2c97c849a" + }, + { + "m_Id": "2d0a269511e34bd1ba9056d2c939dff2" + }, + { + "m_Id": "07946387933e416db576b677f0711e5f" + }, + { + "m_Id": "46fbf3eeb0ea4470869cba7443249295" + }, + { + "m_Id": "ec79eb447dfd47a9b3380344c6a60f43" + }, + { + "m_Id": "3fdf4b7bc5d4426492dcc057603ef4a6" + }, + { + "m_Id": "8cf8aae64c1d443f9303126886b40f17" + }, + { + "m_Id": "49e7c3ad55ce458797f0e60c950cb965" + }, + { + "m_Id": "81e8ed0534534674a74263e6161a2a1a" + }, + { + "m_Id": "952d0fa5cd744df0b434cd38e9a90b93" + }, + { + "m_Id": "21a7a380e66d42e780e2a2a1baa630d5" + }, + { + "m_Id": "2c10b97b92c947ceb307a93759c0228b" + }, + { + "m_Id": "1be90d4f96a841748b0c95219b12ad27" + }, + { + "m_Id": "5fbe253f3e444f2aa8ac717f9c856619" + }, + { + "m_Id": "5bd258837c514ff7ab0bf7027e762c18" + }, + { + "m_Id": "998db5e5901e45b29040eb2099370071" + }, + { + "m_Id": "a6c38edd2e8743a9b057ba8452b9f129" + }, + { + "m_Id": "82af2db1018543d7832af96c1cfc981f" + }, + { + "m_Id": "3ec4797e381747829ef4712c85fcf7a1" + }, + { + "m_Id": "b0b352c4503a43d083a64e57352b29a0" + }, + { + "m_Id": "424dbeeb009344efa29c304c4979e3d6" + }, + { + "m_Id": "05805bc6fcc941fd889922555c6c86d7" + }, + { + "m_Id": "a4ad98d8828c424384229c344ebe2ed0" + }, + { + "m_Id": "3e372195f4bd4845852a37839e5b602d" + }, + { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + }, + { + "m_Id": "4a0041116f73406db7a62ae80ff54ef4" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CombineNode", + "m_ObjectId": "bc9afcb18afa4ccc82d2cdc34d3f4641", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Combine", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -5537.0, + "y": -3827.000244140625, + "width": 126.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "5e42524569844befad16fda5a94eb9cb" + }, + { + "m_Id": "54d7a93ffec5490aa4591da23a21b693" + }, + { + "m_Id": "aa2794b8f0e24bf281d22e0fef0647be" + }, + { + "m_Id": "200245fc8bbe4826b209ab5f7ffe074c" + }, + { + "m_Id": "fc2e62201c5847e798fd939314413fcd" + }, + { + "m_Id": "fe11fa80cc1847a5a37f6757d521cf25" + }, + { + "m_Id": "de0c6f7f7af94defa6c3dbc6433de9d4" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c183b5bd9bbe45089f93996e73110918", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "c234e5216678436195ee1a5914bc79da", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "GenerateUV (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4409.0, + "y": -2338.0, + "width": 222.0, + "height": 142.00001525878907 + } + }, + "m_Slots": [ + { + "m_Id": "8902cb30b1684db8b996562e0140cb18" + }, + { + "m_Id": "3db1608e927e4102a3c3a88e9fcab39a" + }, + { + "m_Id": "0f7ffb6d2de4447f9736780cbcee8e07" + }, + { + "m_Id": "d4954b7bbbb0412cbc997bcbe7dfa808" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "GenerateUV", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "c35312edaa2344788b1964ee2f63a236", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "c3e6d7c20c184bf39fd8822130e693e7", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "c422a9a9ff824176aad2241f58c44d0b", + "m_Id": 0, + "m_DisplayName": "Outline Offset 1", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "c478c32c45884c57a62f7b2aa8ddc3b0", + "m_Id": 2, + "m_DisplayName": "Alpha", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Alpha", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c52a1744a9a14989b0ae452ad6de6061", + "m_Id": 0, + "m_DisplayName": "SSR", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SSR", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c6bdb985bc16435fa72f5a3c81bb633c", + "m_Id": 6, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c7d4094601ac4bc1aead609c72b1f1c1", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c7ddee91dc5b48dc828309c77fdb0b88", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4444.0, + "y": -4266.0, + "width": 153.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "a7942746b5564dc7bbbae1deb2403022" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "c88fcbaeea954a5f9c68c339fa8b604d", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "c9b722d107ce4cd6a748c883472b9b0f", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "c9d7f0dbae7d422985a1cc87c025e76b", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4284.0, + "y": -3165.0, + "width": 144.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "79147f6986644769b58d9ed64fe771e1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "cb3c0c3f08654b068bea44c4ffb15f4a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DShaderProperty", + "m_ObjectId": "c9ec735d1a1046769e5601b2c97c849a", + "m_Guid": { + "m_GuidSerialized": "281a9526-c332-4471-a44e-ece4a1e95ef6" + }, + "m_Name": "Face Texture", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Texture2D_75569DEA", + "m_OverrideReferenceName": "_FaceTex", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "isMainTexture": false, + "useTilingAndOffset": false, + "m_Modifiable": true, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ca2a1083dc014f39ab8af0cdf140866b", + "m_Id": 0, + "m_DisplayName": "_FaceTex_ST", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty", + "m_ObjectId": "cb3c0c3f08654b068bea44c4ffb15f4a", + "m_Guid": { + "m_GuidSerialized": "21009d12-8d94-4273-b0d0-a8ee0608ddcf" + }, + "m_Name": "OutlineMode", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Boolean_cb3c0c3f08654b068bea44c4ffb15f4a", + "m_OverrideReferenceName": "_OutlineMode", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cb5e9f9567e84f8fa5463efc0e256e19", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "cb7117ecb1d047a8b2cb00ed552cb181", + "m_Group": { + "m_Id": "" + }, + "m_Name": "SurfaceDescription.Alpha", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3032.66650390625, + "y": -3029.33349609375, + "width": 200.0, + "height": 41.33349609375 + } + }, + "m_Slots": [ + { + "m_Id": "724e17584e97443e9e285dfa7253c8e3" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "SurfaceDescription.Alpha" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cc88101667c9488f9c5a716e851c1b21", + "m_Id": 3, + "m_DisplayName": "Color0", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color0", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "cce40479b6284b6fa3174db9f09d0ac9", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "cd7281fb41aa4e61ac0fdf71d4f4bd46", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "cda5e3b4c1054bf3a65c0b7ec6bc778a", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "cdddee3a537c464697357f11b966f9b8", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4420.0, + "y": -4483.0, + "width": 156.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "41b9b79b3859472882bcea393703eec0" + }, + { + "m_Id": "c7d4094601ac4bc1aead609c72b1f1c1" + }, + { + "m_Id": "767769f736d5478cba5f10a415e28e7f" + }, + { + "m_Id": "b691728a389a417d9b4f2d02541209c2" + }, + { + "m_Id": "045c4f6b050549c7a0efb208e6349779" + }, + { + "m_Id": "509e6f38505b4b0695b263706a55028f" + }, + { + "m_Id": "204dacb5a95b424facf11cb6f65bd188" + }, + { + "m_Id": "35cbea6373dd4e4f8d0fea36e8add392" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "cfaf3f3a5a1146e194cddad30c95aada", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d0a791a544614667962a9a9a9ce0c68a", + "m_Title": "Screen Space Ratio", + "m_Position": { + "x": -6485.591796875, + "y": -3365.3779296875 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d0b10e52e21941b183f5f635894c76c8", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d1a17e42e7a04dc38984e3c01149445b", + "m_Id": 7, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d219977210094c0082c517d8dc00c8bb", + "m_Id": 0, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "d258902c6ec74942afdb9ebf8c1d07f8", + "m_Title": "Generate Normal", + "m_Position": { + "x": -4511.33349609375, + "y": -3999.3330078125 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "d30452ac6b244ecca03df4d7b4de9f81", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d48c3871e3064027a10ae9f4babd3be0", + "m_Id": 0, + "m_DisplayName": "_UnderlaySoftness", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d4954b7bbbb0412cbc997bcbe7dfa808", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "d4df208fc23b42f2b52364124f1b661c", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5236.99951171875, + "y": -3260.999755859375, + "width": 143.99998474121095, + "height": 33.999996185302737 + } + }, + "m_Slots": [ + { + "m_Id": "757174b6f25040fdbb20355a21752222" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "74b41464cbed4e9e8e23af5ab9be40cf" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "d5173cc3c6cd4f1998550f3187a3e9c8", + "m_Id": 0, + "m_DisplayName": "Normal", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Normal", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "d6a6a119394e4082a11bc024a6e42ef8", + "m_Id": 0, + "m_DisplayName": "Outline Color 2", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "d880558893fb442b9320cf55885d1117", + "m_Id": 0, + "m_DisplayName": "_FaceUVSpeed", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d8edec16956c4f15b7d51d6ec10753f4", + "m_Id": 2, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "d9bcb754db834583b6518c5ed5152114", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d9dc4839ee2847999110bdb234d6041a", + "m_Id": 1, + "m_DisplayName": "G", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "da7a06d393a44089842070d51d2aa0a6", + "m_Id": 0, + "m_DisplayName": "_MainTex", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "daaf032a109749a88c9b8ff8e1f8b541", + "m_Title": "Offset Scale", + "m_Position": { + "x": -5893.0, + "y": -3921.000244140625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVNode", + "m_ObjectId": "dbcb748279484a4590e53518c49122b8", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "UV", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4744.0, + "y": -2762.0, + "width": 145.0, + "height": 130.0 + } + }, + "m_Slots": [ + { + "m_Id": "7a0f504e4175406dbd8134250f4e350b" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_OutputChannel": 1 +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "dc75c4e3a1bc4bb0a128086c2b0679a5", + "m_Guid": { + "m_GuidSerialized": "85cd941f-2fd2-43a3-b0fa-9f728bfb4220" + }, + "m_Name": "Face Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_99AFBB3D", + "m_OverrideReferenceName": "_FaceColor", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + }, + "isMainColor": false, + "m_ColorMode": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "de0c6f7f7af94defa6c3dbc6433de9d4", + "m_Id": 6, + "m_DisplayName": "RG", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RG", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "deac82280a2b43078e0e40863e2d974c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot", + "m_ObjectId": "def8e0b9d8384982bc5b4c32d877e458", + "m_Id": 0, + "m_DisplayName": "Outline Texture", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "dff7a66b353a4023b29c9d937da77960", + "m_Group": { + "m_Id": "484b51c50485473b819c4f05087b32d7" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4602.0, + "y": -4298.0, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "7b8a19bd115e4167a25b59cb3218a817" + }, + { + "m_Id": "0b57f2d35157477ab2b29a5aac14ae8b" + }, + { + "m_Id": "e9e06fcb161e44ba8cc9f6f60264df78" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.UVMaterialSlot", + "m_ObjectId": "e141833aa78b4fd59ecad949beb43a78", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ], + "m_Channel": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e2d28f29bbac4983a401574480b5ca28", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.NormalMaterialSlot", + "m_ObjectId": "e386b183a18245a796b024022f7f3074", + "m_Id": 0, + "m_DisplayName": "Normal (Object Space)", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "NormalOS", + "m_StageCapability": 2, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_Space": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e444f2c81d1e48329fa2c91005277e8d", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "e495a9f7a11f4eb89334e83be154ceb9", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e51a636b2621440eb94cc802c1cf4bfc", + "m_Id": 2, + "m_DisplayName": "Height", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Height", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "e6e80c6b0db545cda26b079a9a78fbb3", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "e818605f8f5a4f01bf61caaa33693581", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "ComputeSDF44 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4113.0, + "y": -3368.999755859375, + "width": 243.99998474121095, + "height": 214.0 + } + }, + "m_Slots": [ + { + "m_Id": "641eda269d7b4da9acb65f8d50035ea9" + }, + { + "m_Id": "f6823778a3cf42d5bbe8a83e5f9c9fa3" + }, + { + "m_Id": "9c26fdddba244d36a854298c00473247" + }, + { + "m_Id": "f684c5678e9e4f078157a3ab7ef5057b" + }, + { + "m_Id": "14ad19bf20a140dd88d58452d7df688b" + }, + { + "m_Id": "215a82c127204988b751de7d3a39b955" + }, + { + "m_Id": "c478c32c45884c57a62f7b2aa8ddc3b0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "ComputeSDF44", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "e9e06fcb161e44ba8cc9f6f60264df78", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebbd94a7102a4457a48ac492de3bff14", + "m_Id": 5, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ebd6d75abcb84108bcadbfe7ee5f6244", + "m_Id": 7, + "m_DisplayName": "TextureHeight", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "TextureHeight", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "ec184d6d9fb2494897774c9e7d279e6d", + "m_Group": { + "m_Id": "013228b0fdf1424097798f0973a9a4fb" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4754.0, + "y": -2625.0, + "width": 145.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ca2a1083dc014f39ab8af0cdf140866b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "07946387933e416db576b677f0711e5f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubtractNode", + "m_ObjectId": "ec1f2e8bc9fd4ae38b133c60ee6c49b8", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Subtract", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4927.0, + "y": -3204.0, + "width": 130.0, + "height": 117.99999237060547 + } + }, + "m_Slots": [ + { + "m_Id": "748c31bbcecc4b30bec2e42c0612175b" + }, + { + "m_Id": "4bda5c294e1949138d033640e1d385b4" + }, + { + "m_Id": "4e64dac49ddc47c3b5b1e27b17a08304" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector4ShaderProperty", + "m_ObjectId": "ec79eb447dfd47a9b3380344c6a60f43", + "m_Guid": { + "m_GuidSerialized": "54c77f8b-0534-4b35-a3f0-83ab2ebe6c1f" + }, + "m_Name": "_OutlineTex_ST", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector4_1774DE83", + "m_OverrideReferenceName": "_OutlineTex_ST", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 1.0, + "y": 1.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "ecf16c34d46f4502ac601f0c38c7576b", + "m_Title": "Vertex Color", + "m_Position": { + "x": -3614.000244140625, + "y": -3549.000244140625 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "ed1d1f1613334c3bb904dd08161cd7e5", + "m_Id": 0, + "m_DisplayName": "_GradientScale", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "ed6c215a65584deeaefad1d2c7743044", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "edbee7a8952b46529ac5ad0365775774", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", + "m_ObjectId": "ef0b93f78372439696f50711eaf57d90", + "m_Id": 0, + "m_DisplayName": "Base Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "BaseColor", + "m_StageCapability": 2, + "m_Value": { + "x": 0.7353569269180298, + "y": 0.7353569269180298, + "z": 0.7353569269180298 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [ + "X", + "Y", + "Z" + ], + "m_ColorMode": 0, + "m_DefaultColor": { + "r": 0.5, + "g": 0.5, + "b": 0.5, + "a": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "ef9738ec7e894772a14e9dce441c16c6", + "m_Id": 2, + "m_DisplayName": "UV", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "UV", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [ + "X", + "Y" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", + "m_ObjectId": "f01d52cdcb1647aab35782b4af535efd", + "m_Id": 3, + "m_DisplayName": "Sampler", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Sampler", + "m_StageCapability": 3, + "m_BareResource": false +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "f23a8b2b7c85478388ff7a8c8a6de740", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Layer4 (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -3819.0, + "y": -3286.0, + "width": 193.0, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "0fac35636fca4474a6afaefc3c757775" + }, + { + "m_Id": "cc88101667c9488f9c5a716e851c1b21" + }, + { + "m_Id": "68ec7c31365549d6a8ce883edfc02de2" + }, + { + "m_Id": "02559cbe5ad441a3904ccb75ded2b2c5" + }, + { + "m_Id": "34a67e0fef884f9399e674d9eeaf720c" + }, + { + "m_Id": "3802c81c3be24823aa1d7c9997a33c29" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "Layer4", + "m_FunctionSource": "96de908384869cd409c75efa351d5edf", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "f2903158b3624759bca1fcd843698078", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "f2a351a5375c441b8d9ab7e2c9545a77", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DPropertiesNode", + "m_ObjectId": "f383b24f0bc6434dafe44b3e3d338a63", + "m_Group": { + "m_Id": "d0a791a544614667962a9a9a9ce0c68a" + }, + "m_Name": "Texel Size", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -6318.6669921875, + "y": -3153.3330078125, + "width": 185.33348083496095, + "height": 101.33348846435547 + } + }, + "m_Slots": [ + { + "m_Id": "fb5e1e2a67c14602808358686bb75091" + }, + { + "m_Id": "712da461f71a454db59d349f752d41ee" + }, + { + "m_Id": "b000f852aa984e9dae25b125a4607f4e" + }, + { + "m_Id": "849275cac05e4ca8bd0b38ab7ae43bf8" + }, + { + "m_Id": "59cea37675824d99995b370f09cef20a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "f3d31c1f18d8491a8ecf5cbc37e4b7db", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4291.33349609375, + "y": -3246.0, + "width": 154.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "ed1d1f1613334c3bb904dd08161cd7e5" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a6bbb32e8d884be9bb36db91fe4b81b1" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f42ad06b3c6a45d3ab33de904c063412", + "m_Id": 3, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f48f04ad45d046a8b88e71731ed506e7", + "m_Id": 4, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 2, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.BlockNode", + "m_ObjectId": "f4ecc442a2d246759f7c2c0412953d28", + "m_Group": { + "m_Id": "" + }, + "m_Name": "VertexDescription.Normal", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 0.0, + "y": 0.0, + "width": 0.0, + "height": 0.0 + } + }, + "m_Slots": [ + { + "m_Id": "a3f8b6e8ae7f48e2989a029904401502" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedDescriptor": "VertexDescription.Normal" +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f6823778a3cf42d5bbe8a83e5f9c9fa3", + "m_Id": 1, + "m_DisplayName": "SD", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "SD", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f684c5678e9e4f078157a3ab7ef5057b", + "m_Id": 4, + "m_DisplayName": "Isoperimeter", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Isoperimeter", + "m_StageCapability": 3, + "m_Value": { + "x": 3.0, + "y": 2.0, + "z": 1.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "f814deb543c24fbbafbcdb5071d96022", + "m_Group": { + "m_Id": "42cadae0923e4969b50bbc3f78185934" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -4569.0, + "y": -3245.000244140625, + "width": 184.0, + "height": 253.0 + } + }, + "m_Slots": [ + { + "m_Id": "abd59150589b436cadf8c9e6f43ccb8e" + }, + { + "m_Id": "7acfafd73b8c4dfab8c55c18a887e087" + }, + { + "m_Id": "928621a3ca2d41c89a10336bbbc81ddc" + }, + { + "m_Id": "b7f9ac55517141868bfb9d2ad6429792" + }, + { + "m_Id": "09b1b86c1c074337a4c439d3a308dd2e" + }, + { + "m_Id": "1f247658c7ba45fb93c41f51e21acb0d" + }, + { + "m_Id": "d30452ac6b244ecca03df4d7b4de9f81" + }, + { + "m_Id": "215b30ae27784ec3a13360a9029af283" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "f864c900600e427ba7793f00c715e971", + "m_Id": 0, + "m_DisplayName": "Outline Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fa6de3be9f5b4411b5081b49e645f424", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "e00": 2.0, + "e01": 2.0, + "e02": 2.0, + "e03": 2.0, + "e10": 2.0, + "e11": 2.0, + "e12": 2.0, + "e13": 2.0, + "e20": 2.0, + "e21": 2.0, + "e22": 2.0, + "e23": 2.0, + "e30": 2.0, + "e31": 2.0, + "e32": 2.0, + "e33": 2.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "faace8101df943d8956faa31728cb004", + "m_Group": { + "m_Id": "daaf032a109749a88c9b8ff8e1f8b541" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -5400.0, + "y": -3851.000244140625, + "width": 130.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "77e28f3e930b4c249145630ec961af95" + }, + { + "m_Id": "f2903158b3624759bca1fcd843698078" + }, + { + "m_Id": "30ca940fe2794c949f2a1d4d2caaa446" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "facc84930f544fd7a0205a6176b18ac0", + "m_Id": 2, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Texture2DInputMaterialSlot", + "m_ObjectId": "fb15d0ba56d54a6192f11e107aeb5fa8", + "m_Id": 1, + "m_DisplayName": "Texture", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Texture", + "m_StageCapability": 3, + "m_BareResource": false, + "m_Texture": { + "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "m_DefaultType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "fb5e1e2a67c14602808358686bb75091", + "m_Id": 0, + "m_DisplayName": "Width", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Width", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "fc2e62201c5847e798fd939314413fcd", + "m_Id": 4, + "m_DisplayName": "RGBA", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", + "m_ObjectId": "fd0b096ed5b74f9e9ec51327be200731", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "e00": 0.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 0.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 0.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 0.0 + }, + "m_DefaultValue": { + "e00": 1.0, + "e01": 0.0, + "e02": 0.0, + "e03": 0.0, + "e10": 0.0, + "e11": 1.0, + "e12": 0.0, + "e13": 0.0, + "e20": 0.0, + "e21": 0.0, + "e22": 1.0, + "e23": 0.0, + "e30": 0.0, + "e31": 0.0, + "e32": 0.0, + "e33": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SampleTexture2DNode", + "m_ObjectId": "fdb77c3e92ee497b88ca5dc46dc45350", + "m_Group": { + "m_Id": "98934a69591249d5b8b92b39045359a3" + }, + "m_Name": "Sample Texture 2D", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -4171.0, + "y": -2362.0, + "width": 180.0, + "height": 181.0 + } + }, + "m_Slots": [ + { + "m_Id": "4328cdbf78b94c038fd614c59bfe1cac" + }, + { + "m_Id": "04dfcc9ff13a4bf282ed46faec39d15c" + }, + { + "m_Id": "71dd947935b64ce38f0d25406dde447b" + }, + { + "m_Id": "61a6ac5f29344d109411f26850ab0a96" + }, + { + "m_Id": "44806230fa384c1e95f9c5918a14f056" + }, + { + "m_Id": "4eb3c00a1ca44e10be833b7ca61ff059" + }, + { + "m_Id": "57abc172afd449e2a4d567f93432507b" + }, + { + "m_Id": "cda5e3b4c1054bf3a65c0b7ec6bc778a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_TextureType": 0, + "m_NormalMapSpace": 0, + "m_EnableGlobalMipBias": true, + "m_MipSamplingMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "fe11fa80cc1847a5a37f6757d521cf25", + "m_Id": 5, + "m_DisplayName": "RGB", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "RGB", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta new file mode 100644 index 00000000..248825ca --- /dev/null +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF-URP Unlit.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 124c112a6e8f1a54e8b0870e881b56d8 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/Assets/TextMesh Pro/Shaders/TMP_SDF.shader b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader index 011ee199..bbcfd119 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_SDF.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_SDF.shader @@ -4,10 +4,10 @@ Properties { _FaceTex ("Face Texture", 2D) = "white" {} _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 - [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceColor ("Face Color", Color) = (1,1,1,1) _FaceDilate ("Face Dilate", Range(-1,1)) = 0 - [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineTex ("Outline Texture", 2D) = "white" {} _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 @@ -21,7 +21,7 @@ Properties { _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 - [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularColor ("Specular", Color) = (1,1,1,1) _SpecularPower ("Specular", Range(0,4)) = 2.0 _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 _Diffuse ("Diffuse", Range(0,1)) = 0.5 @@ -37,13 +37,13 @@ Properties { _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) - [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 - [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowColor ("Color", Color) = (0, 1, 0, 0.5) _GlowOffset ("Offset", Range(-1,1)) = 0 _GlowInner ("Inner", Range(0,1)) = 0.05 _GlowOuter ("Outer", Range(0,1)) = 0.05 @@ -127,17 +127,18 @@ SubShader { #include "TMPro_Properties.cginc" #include "TMPro.cginc" - struct vertex_t { + struct vertex_t + { UNITY_VERTEX_INPUT_INSTANCE_ID float4 position : POSITION; float3 normal : NORMAL; fixed4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; - - struct pixel_t { + struct pixel_t + { UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float4 position : SV_POSITION; @@ -147,16 +148,20 @@ SubShader { float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) float3 viewDir : TEXCOORD3; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float4 texcoord2 : TEXCOORD4; // u,v, scale, bias fixed4 underlayColor : COLOR1; - #endif - float4 textures : TEXCOORD5; + #endif + + float4 textures : TEXCOORD5; }; // Used by Unity internally to handle Texture Tiling and Offset. float4 _FaceTex_ST; float4 _OutlineTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; pixel_t VertShader(vertex_t input) { @@ -167,7 +172,7 @@ SubShader { UNITY_TRANSFER_INSTANCE_ID(input,output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.position; vert.x += _VertexOffsetX; @@ -178,7 +183,7 @@ SubShader { float2 pixelSize = vPosition.w; pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(input.texcoord0.w) * _GradientScale * (_Sharpness + 1); if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; @@ -188,13 +193,13 @@ SubShader { float alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA); - #if GLOW_ON + #if GLOW_ON alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); - #endif + #endif alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; - #if (UNDERLAY_ON || UNDERLAY_INNER) + #if (UNDERLAY_ON || UNDERLAY_INNER) float4 underlayColor = _UnderlayColor; underlayColor.rgb *= underlayColor.a; @@ -205,23 +210,28 @@ SubShader { float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 bOffset = float2(x, y); - #endif + #endif // Generate UV for the Masking Texture float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); // Support for texture tiling and offset - float2 textureUV = UnpackUV(input.texcoord1.x); + float2 textureUV = input.texcoord1; float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + input.color.rgb = UIGammaToLinear(input.color.rgb); + } output.position = vPosition; output.color = input.color; output.atlas = input.texcoord0; output.param = float4(alphaClip, scale, bias, weight); - output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + const half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * maskSoftness + pixelSize.xy)); output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); #if (UNDERLAY_ON || UNDERLAY_INNER) output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); @@ -239,9 +249,9 @@ SubShader { float c = tex2D(_MainTex, input.atlas).a; - #ifndef UNDERLAY_ON + #ifndef UNDERLAY_ON clip(c - input.param.x); - #endif + #endif float scale = input.param.y; float bias = input.param.z; @@ -261,7 +271,7 @@ SubShader { faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); - #if BEVEL_ON + #if BEVEL_ON float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); float3 n = GetSurfaceNormal(input.atlas, weight, dxy); @@ -278,36 +288,35 @@ SubShader { fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; - #endif + #endif - #if UNDERLAY_ON + #if UNDERLAY_ON float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); - #endif + #endif - #if UNDERLAY_INNER + #if UNDERLAY_INNER float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); - #endif + #endif - #if GLOW_ON + #if GLOW_ON float4 glowColor = GetGlowColor(sd, scale); faceColor.rgb += glowColor.rgb * glowColor.a; - #endif + #endif // Alternative implementation to UnityGet2DClipping with support for softness. - #if UNITY_UI_CLIP_RECT + #if UNITY_UI_CLIP_RECT half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); faceColor *= m.x * m.y; - #endif + #endif - #if UNITY_UI_ALPHACLIP + #if UNITY_UI_ALPHACLIP clip(faceColor.a - 0.001); - #endif + #endif - return faceColor * input.color.a; + return faceColor * input.color.a; } - ENDCG } } diff --git a/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader index e8283a78..4012a081 100644 --- a/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader +++ b/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader @@ -2,18 +2,18 @@ Shader "TextMeshPro/Sprite" { Properties { - [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} - _Color ("Tint", Color) = (1,1,1,1) - - _StencilComp ("Stencil Comparison", Float) = 8 - _Stencil ("Stencil ID", Float) = 0 - _StencilOp ("Stencil Operation", Float) = 0 - _StencilWriteMask ("Stencil Write Mask", Float) = 255 - _StencilReadMask ("Stencil Read Mask", Float) = 255 - - _CullMode ("Cull Mode", Float) = 0 - _ColorMask ("Color Mask", Float) = 15 - _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 } @@ -21,19 +21,19 @@ Shader "TextMeshPro/Sprite" SubShader { Tags - { - "Queue"="Transparent" - "IgnoreProjector"="True" - "RenderType"="Transparent" + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } - + Stencil { Ref [_Stencil] Comp [_StencilComp] - Pass [_StencilOp] + Pass [_StencilOp] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] } @@ -58,7 +58,7 @@ Shader "TextMeshPro/Sprite" #pragma multi_compile __ UNITY_UI_CLIP_RECT #pragma multi_compile __ UNITY_UI_ALPHACLIP - + struct appdata_t { float4 vertex : POSITION; @@ -69,29 +69,43 @@ Shader "TextMeshPro/Sprite" struct v2f { - float4 vertex : SV_POSITION; - fixed4 color : COLOR; - float2 texcoord : TEXCOORD0; - float4 worldPosition : TEXCOORD1; + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + float4 mask : TEXCOORD2; UNITY_VERTEX_OUTPUT_STEREO }; - + sampler2D _MainTex; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; float4 _MainTex_ST; + float _UIMaskSoftnessX; + float _UIMaskSoftnessY; + int _UIVertexColorAlwaysGammaSpace; v2f vert(appdata_t v) { v2f OUT; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); - OUT.worldPosition = v.vertex; - OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + float4 vPosition = UnityObjectToClipPos(v.vertex); + OUT.worldPosition = v.vertex; + OUT.vertex = vPosition; + + float2 pixelSize = vPosition.w; + pixelSize /= abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); - + OUT.mask = half4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))); + + if (_UIVertexColorAlwaysGammaSpace && !IsGammaSpace()) + { + v.color.rgb = UIGammaToLinear(v.color.rgb); + } OUT.color = v.color * _Color; return OUT; } @@ -99,9 +113,10 @@ Shader "TextMeshPro/Sprite" fixed4 frag(v2f IN) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; - - #ifdef UNITY_UI_CLIP_RECT - color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; #endif #ifdef UNITY_UI_ALPHACLIP @@ -110,7 +125,7 @@ Shader "TextMeshPro/Sprite" return color; } - ENDCG + ENDCG } } } diff --git a/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta b/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta index 0d6eb56c..f21163e2 100644 --- a/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta +++ b/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta @@ -4,6 +4,6 @@ ShaderImporter: externalObjects: {} defaultTextures: [] nonModifiableTextures: [] - userData: + userData: Version 2.0 assetBundleName: assetBundleVariant: diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc index 5969fec1..d145a773 100644 --- a/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc +++ b/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc @@ -1,20 +1,22 @@ -ο»Ώstruct vertex_t { +ο»Ώstruct vertex_t +{ UNITY_VERTEX_INPUT_INSTANCE_ID float4 position : POSITION; float3 normal : NORMAL; float4 color : COLOR; - float2 texcoord0 : TEXCOORD0; + float4 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; }; -struct pixel_t { +struct pixel_t +{ UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO float4 position : SV_POSITION; float4 faceColor : COLOR; float4 outlineColor : COLOR1; float4 texcoord0 : TEXCOORD0; - float4 param : TEXCOORD1; // weight, scaleRatio + float4 param : TEXCOORD1; // x = weight, y = no longer used float2 mask : TEXCOORD2; #if (UNDERLAY_ON || UNDERLAY_INNER) float4 texcoord2 : TEXCOORD3; @@ -22,10 +24,14 @@ struct pixel_t { #endif }; -float4 SRGBToLinear(float4 rgba) { +float4 SRGBToLinear(float4 rgba) +{ return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); } +float _UIMaskSoftnessX; +float _UIMaskSoftnessY; + pixel_t VertShader(vertex_t input) { pixel_t output; @@ -35,7 +41,7 @@ pixel_t VertShader(vertex_t input) UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - float bold = step(input.texcoord1.y, 0); + float bold = step(input.texcoord0.w, 0); float4 vert = input.position; vert.x += _VertexOffsetX; @@ -71,7 +77,7 @@ pixel_t VertShader(vertex_t input) output.faceColor = faceColor; output.outlineColor = outlineColor; output.texcoord0 = float4(input.texcoord0.xy, maskUV.xy); - output.param = float4(0.5 - weight, 1.3333 * _GradientScale * (_Sharpness + 1) / _TextureWidth, _OutlineWidth * _ScaleRatioA * 0.5, 0); + output.param = float4(0.5 - weight, 0, _OutlineWidth * _ScaleRatioA * 0.5, 0); float2 mask = float2(0, 0); #if UNITY_UI_CLIP_RECT @@ -99,8 +105,9 @@ float4 PixShader(pixel_t input) : SV_Target float d = tex2D(_MainTex, input.texcoord0.xy).a; - float2 UV = input.texcoord0.xy; - float scale = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))) * input.param.y; + float pixelSize = abs(ddx(input.texcoord0.y)) + abs(ddy(input.texcoord0.y)); + pixelSize *= _TextureHeight * 0.75; + float scale = 1 / pixelSize * _GradientScale * (_Sharpness + 1); #if (UNDERLAY_ON | UNDERLAY_INNER) float layerScale = scale; @@ -112,7 +119,7 @@ float4 PixShader(pixel_t input) : SV_Target float4 faceColor = input.faceColor * saturate((d - input.param.x) * scale + 0.5); - #ifdef OUTLINE_ON + #if OUTLINE_ON float4 outlineColor = lerp(input.faceColor, input.outlineColor, sqrt(min(1.0, input.param.z * scale * 2))); faceColor = lerp(outlineColor, input.faceColor, saturate((d - input.param.x - input.param.z) * scale + 0.5)); faceColor *= saturate((d - input.param.x + input.param.z) * scale + 0.5); @@ -130,7 +137,7 @@ float4 PixShader(pixel_t input) : SV_Target faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - layerBias)) * sd * (1 - faceColor.a); #endif - #ifdef MASKING + #if MASKING float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; a = saturate(t / _MaskEdgeSoftness); @@ -140,7 +147,8 @@ float4 PixShader(pixel_t input) : SV_Target // Alternative implementation to UnityGet2DClipping with support for softness #if UNITY_UI_CLIP_RECT - float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale)); + half2 maskSoftness = half2(max(_UIMaskSoftnessX, _MaskSoftnessX), max(_UIMaskSoftnessY, _MaskSoftnessY)); + float2 maskZW = 0.25 / (0.25 * maskSoftness + 1 / scale); float2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW); faceColor *= m.x * m.y; #endif diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc index 2e962588..b806b4f9 100644 --- a/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc +++ b/Assets/TextMesh Pro/Shaders/TMPro_Properties.cginc @@ -66,11 +66,6 @@ uniform float _MaskID; uniform sampler2D _MaskTex; uniform float4 _MaskCoord; uniform float4 _ClipRect; // bottom left(x,y) : top right(z,w) -//uniform float _MaskWipeControl; -//uniform float _MaskEdgeSoftness; -//uniform fixed4 _MaskEdgeColor; -//uniform bool _MaskInverse; - uniform float _MaskSoftnessX; uniform float _MaskSoftnessY; diff --git a/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc index 622ae875..2153a9a7 100644 --- a/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc +++ b/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc @@ -5,7 +5,7 @@ void VertShader(inout appdata_full v, out Input data) UNITY_INITIALIZE_OUTPUT(Input, data); - float bold = step(v.texcoord1.y, 0); + float bold = step(v.texcoord.w, 0); // Generate normal for backface float3 view = ObjSpaceViewDir(v.vertex); @@ -20,14 +20,12 @@ void VertShader(inout appdata_full v, out Input data) pixelSize /= float2(_ScaleX, _ScaleY) * mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy); float scale = rsqrt(dot(pixelSize, pixelSize)); - scale *= abs(v.texcoord1.y) * _GradientScale * (_Sharpness + 1); + scale *= abs(v.texcoord.w) * _GradientScale * (_Sharpness + 1); scale = lerp(scale * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(v.normal.xyz), normalize(WorldSpaceViewDir(vert))))); data.param.y = scale; #endif - data.param.x = (lerp(_WeightNormal, _WeightBold, bold) / 4.0 + _FaceDilate) * _ScaleRatioA * 0.5; // - - v.texcoord1.xy = UnpackUV(v.texcoord1.x); + data.param.x = (lerp(_WeightNormal, _WeightBold, bold) / 4.0 + _FaceDilate) * _ScaleRatioA * 0.5; // data.viewDirEnv = mul((float3x3)_EnvMatrix, WorldSpaceViewDir(v.vertex)); } @@ -82,7 +80,7 @@ void PixShader(Input input, inout SurfaceOutput o) float3 n = float3(0, 0, -1); float3 emission = float3(0, 0, 0); #endif - + #if GLOW_ON float4 glowColor = GetGlowColor(sd, scale); glowColor.a *= input.color.a; diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/MyGameDevTools.SceneLoading.asmdef b/Packages/com.mygamedevtools.scene-loader/Runtime/MyGameDevTools.SceneLoading.asmdef index 2f2957be..b8f25cf9 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/MyGameDevTools.SceneLoading.asmdef +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/MyGameDevTools.SceneLoading.asmdef @@ -1,12 +1,10 @@ { "name": "MyGameDevTools.SceneLoading", - "rootNamespace": "", + "rootNamespace": "MyGameDevTools.SceneLoading", "references": [ "GUID:6055be8ebefd69e48b49212b09b47b2f", "GUID:9e24947de15b9834991c9d8411ea37cf", - "GUID:84651a3751eca9349aac36a66bba901b", - "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:593a5b492d29ac6448b1ebf7f035ef33" + "GUID:84651a3751eca9349aac36a66bba901b" ], "includePlatforms": [], "excludePlatforms": [], @@ -21,15 +19,15 @@ "expression": "2.2", "define": "ENABLE_TMP" }, + { + "name": "com.unity.ugui", + "expression": "2", + "define": "ENABLE_TMP" + }, { "name": "com.unity.addressables", "expression": "1.19", "define": "ENABLE_ADDRESSABLES" - }, - { - "name": "com.cysharp.unitask", - "expression": "2", - "define": "ENABLE_UNITASK" } ], "noEngineReferences": false diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/MyGameDevTools.SceneLoading.Tests.asmdef b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/MyGameDevTools.SceneLoading.Tests.asmdef index e3601d61..d738710f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/MyGameDevTools.SceneLoading.Tests.asmdef +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/MyGameDevTools.SceneLoading.Tests.asmdef @@ -1,14 +1,13 @@ { "name": "MyGameDevTools.SceneLoading.Tests", - "rootNamespace": "", + "rootNamespace": "MyGameDevTools.SceneLoading.Tests", "references": [ "GUID:eee6d035ccac42b4e845b99014468585", "GUID:27619889b8ba8c24980f49ee34dbb44a", "GUID:9e24947de15b9834991c9d8411ea37cf", "GUID:69448af7b92c7f342b298e06a37122aa", "GUID:84651a3751eca9349aac36a66bba901b", - "GUID:6055be8ebefd69e48b49212b09b47b2f", - "GUID:f51ebe6a0ceec4240a699833d6309b23" + "GUID:6055be8ebefd69e48b49212b09b47b2f" ], "includePlatforms": [], "excludePlatforms": [], @@ -27,15 +26,15 @@ "expression": "2.2", "define": "ENABLE_TMP" }, + { + "name": "com.unity.ugui", + "expression": "2", + "define": "ENABLE_TMP" + }, { "name": "com.unity.addressables", "expression": "1.19", "define": "ENABLE_ADDRESSABLES" - }, - { - "name": "com.cysharp.unitask", - "expression": "2", - "define": "ENABLE_UNITASK" } ], "noEngineReferences": false diff --git a/Packages/manifest.json b/Packages/manifest.json index 5ac968f5..f568ea0f 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,7 +1,5 @@ { "dependencies": { - "com.cysharp.unitask": "2.5.0", - "com.mygamedevtools.script-template": "3.4.0", "com.unity.addressables": "2.2.2", "com.unity.feature.development": "1.0.2", "com.unity.ide.visualstudio": "2.0.22", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 3df8411a..2a2293d0 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,25 +1,11 @@ { "dependencies": { - "com.cysharp.unitask": { - "version": "2.5.0", - "depth": 0, - "source": "registry", - "dependencies": {}, - "url": "https://package.openupm.com" - }, "com.mygamedevtools.scene-loader": { "version": "file:com.mygamedevtools.scene-loader", "depth": 0, "source": "embedded", "dependencies": {} }, - "com.mygamedevtools.script-template": { - "version": "3.4.0", - "depth": 0, - "source": "registry", - "dependencies": {}, - "url": "https://package.openupm.com" - }, "com.unity.addressables": { "version": "2.2.2", "depth": 0, From 04bf7cb6db0065eae43c8048f3afed6ed104c6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 6 Jan 2025 23:29:19 -0300 Subject: [PATCH 14/53] add static api implementation --- .github/workflows/test.yml | 2 +- .../Runtime/API.meta | 8 + .../Runtime/API/AdvancedSceneManager.cs | 665 ++++++++++++++++++ .../Runtime/API/AdvancedSceneManager.cs.meta | 2 + .../MyGameDevTools.SceneLoading.Api.asmdef | 25 + ...yGameDevTools.SceneLoading.Api.asmdef.meta | 7 + .../Runtime/AdvancedSceneManager.cs | 4 +- .../Tests/Runtime/API.meta | 8 + ...GameDevTools.SceneLoading.Api.Tests.asmdef | 31 + ...evTools.SceneLoading.Api.Tests.asmdef.meta | 7 + .../Runtime/API/SceneManager_ApiTests.cs | 76 ++ .../Runtime/API/SceneManager_ApiTests.cs.meta | 2 + .../Runtime/Utilities/SceneTestEnvironment.cs | 106 +-- .../Settings.json | 2 +- 14 files changed, 893 insertions(+), 52 deletions(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c0520ec5..c10bbd4f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: artifactsPath: ${{ matrix.testMode }}-artifacts githubToken: ${{ secrets.GITHUB_TOKEN }} checkName: ${{ matrix.testMode }} Test Results - coverageOptions: 'generateAdditionalMetrics;assemblyFilters:+MyGameDevTools.SceneLoading' + coverageOptions: 'generateAdditionalMetrics;assemblyFilters:+MyGameDevTools.SceneLoading,+MyGameDevTools.SceneLoading.API' - name: Upload Coverage to Codecov uses: codecov/codecov-action@v4 with: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta new file mode 100644 index 00000000..ae728fa5 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c640f50bc329674bb4054ee052adc44 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs new file mode 100644 index 00000000..abac2eda --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs @@ -0,0 +1,665 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +#if ENABLE_ADDRESSABLES +using UnityEngine.AddressableAssets; +#endif +using UnityEngine.SceneManagement; + +namespace MyGameDevTools.SceneLoading.Api +{ + public static class AdvancedSceneManager + { + static ISceneManager Instance + { + get + { + if (_instance == null) + throw new NullReferenceException("[AdvancedSceneManager] The static scene manager instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); + return _instance; + } + } + + static ISceneManager _instance; + + [RuntimeInitializeOnLoadMethod] + internal static void Initialize() + { + _instance = new SceneLoading.AdvancedSceneManager(true); + } + + #region ISceneManager + /// + /// Reports that the active scene has changed, passing the previous and current active scene as parameters. + ///
+ /// In some scenarios, the previous or the current scene might be invalid (you can check it through ), but never both at the same time. + ///
+ /// This can occur when the first active scene is being set (there was no previous active scene) or when the last scene gets unloaded (leaving no other scene to be activated). + ///
+ public static event Action ActiveSceneChanged + { + add => Instance.ActiveSceneChanged += value; + remove => Instance.ActiveSceneChanged -= value; + } + /// + /// Reports when a scene gets unloaded. + /// + public static event Action SceneUnloaded + { + add => Instance.SceneUnloaded += value; + remove => Instance.SceneUnloaded -= value; + } + /// + /// Reports when a scene gets loaded. + /// + public static event Action SceneLoaded + { + add => Instance.SceneLoaded += value; + remove => Instance.SceneLoaded -= value; + } + + /// + /// The amount of scenes loaded. + /// + public static int LoadedSceneCount => Instance.LoadedSceneCount; + /// + /// The amount of scenes managed by the internal . + /// This includes scenes that are being unloaded. + /// + public static int TotalSceneCount => Instance.TotalSceneCount; + + /// + /// Sets the target as the active scene. + /// Internally calls . + /// + /// Scene to be enabled as the active scene. + public static void SetActiveScene(Scene scene) => Instance.SetActiveScene(scene); + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to the target scene or a group of scenes via a struct, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A struct that may hold one or more scenes and the target active index. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default) => Instance.TransitionAsync(sceneParameters, intermediateSceneReference, token); + + /// + /// Loads the target scene or group of scenes provided via a struct. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// A struct that may hold one or more scenes and the target active index. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneParameters, progress, token); + + /// + /// Unloads the target scene or group of scenes provided via a struct. + /// + /// + /// A struct that may hold one or more scenes. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) => Instance.UnloadAsync(sceneParameters, token); + + /// + /// Gets the current active scene. + /// This should point to the same scene you get via . + /// + /// The current active scene, or an invalid scene if none of the loaded scenes are enabled as the active scene. + public static Scene GetActiveScene() => Instance.GetActiveScene(); + + /// + /// Gets the loaded scene at the of the loaded scenes list. + /// + /// Index of the target scene in the loaded scenes list. + /// The loaded scene at the of the loaded scenes list. + public static Scene GetLoadedSceneAt(int index) => Instance.GetLoadedSceneAt(index); + + /// + /// Gets the last loaded scene of this . + /// + /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . + public static Scene GetLastLoadedScene() => Instance.GetLastLoadedScene(); + + /// + /// Gets a loaded scene by its . + /// + /// Name of the loaded scene to be found. + /// A loaded scene with the given . + public static Scene GetLoadedSceneByName(string name) => Instance.GetLoadedSceneByName(name); + #endregion + + #region Extensions + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' names. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneNames, setIndexActive, progress, token); + + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' build indexes. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndices, setIndexActive, progress, token); + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's name. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneName, setActive, progress, token); + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's build index. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAsync(int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndex, setActive, progress, token); + +#if ENABLE_ADDRESSABLES + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' . + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReferences, setIndexActive, progress, token); + + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' addressable address. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(addresses, setIndexActive, progress, token); + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's . + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReference, setActive, progress, token); + + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's addressable address. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static ValueTask LoadAddressableAsync(string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(address, setActive, progress, token); +#endif + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their names to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetSceneNames, loadingSceneName, setIndexActive, token); + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their build index to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndices, loadingBuildIndex, setIndexActive, token); + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene name to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(string targetSceneName, string loadingSceneName = null, CancellationToken token = default) => Instance.TransitionAsync(targetSceneName, loadingSceneName, token); + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene build index to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If -1, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAsync(int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndex, loadingBuildIndex, token); + +#if ENABLE_ADDRESSABLES + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReferences, loadingAssetReference, setIndexActive, token); + + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their addressable addresses to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddresses, loadingAddress, setIndexActive, token); + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReference, loadingAssetReference, token); + + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene addressable address to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static ValueTask TransitionAddressableAsync(string targetAddress, string loadingAddress = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddress, loadingAddress, token); +#endif + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their names to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(string[] sceneNames, CancellationToken token = default) => Instance.UnloadAsync(sceneNames, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(int[] buildIndices, CancellationToken token = default) => Instance.UnloadAsync(buildIndices, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(Scene[] scenes, CancellationToken token = default) => Instance.UnloadAsync(scenes, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's name to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(string sceneName, CancellationToken token = default) => Instance.UnloadAsync(sceneName, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(int buildIndex, CancellationToken token = default) => Instance.UnloadAsync(buildIndex, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAsync(Scene scene, CancellationToken token = default) => Instance.UnloadAsync(scene, token); + +#if ENABLE_ADDRESSABLES + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(AssetReference[] assetReferences, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReferences, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(string[] addresses, CancellationToken token = default) => Instance.UnloadAddressableAsync(addresses, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(AssetReference assetReference, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReference, token); + + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's addressable address to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static ValueTask UnloadAddressableAsync(string address, CancellationToken token = default) => Instance.UnloadAddressableAsync(address, token); +#endif + #endregion + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta new file mode 100644 index 00000000..5dbe823d --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a08c7b1ee6e5566469682ddc16ef7686 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef new file mode 100644 index 00000000..05dca3c7 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef @@ -0,0 +1,25 @@ +{ + "name": "MyGameDevTools.SceneLoading.Api", + "rootNamespace": "MyGameDevTools.SceneLoading.Api", + "references": [ + "GUID:eee6d035ccac42b4e845b99014468585", + "GUID:9e24947de15b9834991c9d8411ea37cf" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [ + "!DISABLE_STATIC_SCENE_MANAGER" + ], + "versionDefines": [ + { + "name": "com.unity.addressables", + "expression": "1.19", + "define": "ENABLE_ADDRESSABLES" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta new file mode 100644 index 00000000..4532c1be --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1f93bbe54fc0e834b9fd2f0a07956dc1 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 95c01b4f..23f77b9d 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -150,13 +150,13 @@ public ValueTask TransitionAsync(SceneParameters sceneParameters, I public ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token); + return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); } public ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token); + return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token).RunAndDisposeToken(linkedSource); } async ValueTask LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta new file mode 100644 index 00000000..18df0987 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 25e02e29935b3c54b890d974a4a8425f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef new file mode 100644 index 00000000..41cd6073 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef @@ -0,0 +1,31 @@ +{ + "name": "MyGameDevTools.SceneLoading.Api.Tests", + "rootNamespace": "MyGameDevTools.SceneLoading.Api.Tests", + "references": [ + "GUID:eee6d035ccac42b4e845b99014468585", + "GUID:1f93bbe54fc0e834b9fd2f0a07956dc1", + "GUID:0b51ebc09bbfe624d8c5427c1e3c295d", + "GUID:27619889b8ba8c24980f49ee34dbb44a", + "GUID:9e24947de15b9834991c9d8411ea37cf", + "GUID:84651a3751eca9349aac36a66bba901b" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": true, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [ + { + "name": "com.unity.addressables", + "expression": "1.19", + "define": "ENABLE_ADDRESSABLES" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta new file mode 100644 index 00000000..291cac7a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5c68751d3ac318941ad3501cd94032e1 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs new file mode 100644 index 00000000..dda62d47 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs @@ -0,0 +1,76 @@ +using MyGameDevTools.SceneLoading.Tests; +using NUnit.Framework; +using UnityEngine.SceneManagement; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Api.Tests +{ + public class SceneManager_ApiTests : IPrebuildSetup, IPostBuildCleanup + { + int _scenesActivated; + int _scenesUnloaded; + int _scenesLoaded; + + public void Setup() => new SceneTestEnvironment().Setup(); + + public void Cleanup() => new SceneTestEnvironment().Cleanup(); + + [OneTimeSetUp] + public void OneTimeSetup() + { + SceneTestEnvironment.ValidateSceneEnvironment(); + + AdvancedSceneManager.ActiveSceneChanged += ReportSceneActivation; + AdvancedSceneManager.SceneUnloaded += ReportSceneUnloaded; + AdvancedSceneManager.SceneLoaded += ReportSceneLoaded; + } + + [OneTimeTearDown] + public void OneTimeTeardown() + { + AdvancedSceneManager.ActiveSceneChanged -= ReportSceneActivation; + AdvancedSceneManager.SceneUnloaded -= ReportSceneUnloaded; + AdvancedSceneManager.SceneLoaded -= ReportSceneLoaded; + } + + [SetUp] + public void TestSetup() + { + AdvancedSceneManager.SetActiveScene(AdvancedSceneManager.GetLoadedSceneAt(0)); + + _scenesActivated = 0; + _scenesUnloaded = 0; + _scenesLoaded = 0; + } + + [Test] + public void InitialStateTest() + { + int loadedScenes = 0; + Assert.DoesNotThrow(() => loadedScenes = AdvancedSceneManager.LoadedSceneCount); + Assert.AreEqual(1, loadedScenes); + Assert.AreEqual(1, AdvancedSceneManager.TotalSceneCount); + + Scene activeScene = SceneManager.GetActiveScene(); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetActiveScene()); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLastLoadedScene()); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneAt(0)); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneByName(activeScene.name)); + } + + void ReportSceneActivation(Scene previousScene, Scene newScene) + { + _scenesActivated++; + } + + void ReportSceneUnloaded(Scene unloadedScene) + { + _scenesUnloaded++; + } + + void ReportSceneLoaded(Scene loadedScene) + { + _scenesLoaded++; + } + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta new file mode 100644 index 00000000..2d9ca28a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 57ff7888822b8c743bf60397e36fec4c \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index ef414855..aef09ff7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -22,6 +22,34 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup public const string ScenePathBase = "Assets/_test"; public const int DefaultTimeout = 3000; + static readonly ILoadSceneInfo[][] _multipleLoadSceneInfoList = new ILoadSceneInfo[][] + { + new ILoadSceneInfo[] + { + new LoadSceneInfoName(SceneBuilder.SceneNames[0]), + new LoadSceneInfoIndex(1), +#if ENABLE_ADDRESSABLES + new LoadSceneInfoAddress(SceneBuilder.SceneNames[2]), + new LoadSceneInfoAddress(SceneBuilder.SceneNames[3]), +#endif + new LoadSceneInfoName(SceneBuilder.ScenePaths[3]) + }, + // This list of scenes expects two load scene infos that point to the same source scene, + // and validates whether that causes any issues when linking to the target loaded scene. + new ILoadSceneInfo[] + { + new LoadSceneInfoIndex(1), + new LoadSceneInfoName(SceneBuilder.SceneNames[1]), + new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), +#if ENABLE_ADDRESSABLES + // Since we can't test statically with AssetReference, we should at least validate + // that two AsyncOperations with the same addressable source do not cause issues. + new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), + new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), +#endif + } + }; + public static readonly ILoadSceneInfo[] SingleLoadSceneInfoList = new ILoadSceneInfo[] { new LoadSceneInfoName(SceneBuilder.SceneNames[1]), @@ -66,34 +94,6 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup new AdvancedSceneManager(), }; - static readonly ILoadSceneInfo[][] _multipleLoadSceneInfoList = new ILoadSceneInfo[][] - { - new ILoadSceneInfo[] - { - new LoadSceneInfoName(SceneBuilder.SceneNames[0]), - new LoadSceneInfoIndex(1), -#if ENABLE_ADDRESSABLES - new LoadSceneInfoAddress(SceneBuilder.SceneNames[2]), - new LoadSceneInfoAddress(SceneBuilder.SceneNames[3]), -#endif - new LoadSceneInfoName(SceneBuilder.ScenePaths[3]) - }, - // This list of scenes expects two load scene infos that point to the same source scene, - // and validates whether that causes any issues when linking to the target loaded scene. - new ILoadSceneInfo[] - { - new LoadSceneInfoIndex(1), - new LoadSceneInfoName(SceneBuilder.SceneNames[1]), - new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), -#if ENABLE_ADDRESSABLES - // Since we can't test statically with AssetReference, we should at least validate - // that two AsyncOperations with the same addressable source do not cause issues. - new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), - new LoadSceneInfoAddress(SceneBuilder.SceneNames[1]), -#endif - } - }; - #if UNITY_EDITOR #if ENABLE_ADDRESSABLES const string _addressableScenePathBase = "Assets/_addressables-test"; @@ -104,6 +104,9 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup public void Setup() { #if UNITY_EDITOR + if (IsSceneEnvironmentSetup()) + return; + int sceneCount = SceneBuilder.SceneNames.Length; List buildScenes = new(sceneCount); @@ -136,6 +139,9 @@ public void Setup() public void Cleanup() { #if UNITY_EDITOR + if (!IsSceneEnvironmentSetup()) + return; + EditorBuildSettings.scenes = EditorBuildSettings.scenes.Where(scene => !scene.path.StartsWith(ScenePathBase)).ToArray(); if (!Directory.Exists(ScenePathBase)) @@ -161,26 +167,7 @@ public void Cleanup() public static void ValidateSceneEnvironment() { #if UNITY_EDITOR - var builtScenes = EditorBuildSettings.scenes; - Assert.True(hasAllEnvironmentScenes()); - - bool hasAllEnvironmentScenes() - { - foreach (var name in SceneBuilder.SceneNames) - { - if (!hasBuiltSceneWithName(name)) - return false; - } - return true; - } - - bool hasBuiltSceneWithName(string name) - { - foreach (var builtScene in builtScenes) - if (builtScene.path.Contains(name)) - return true; - return false; - } + Assert.True(IsSceneEnvironmentSetup()); #if ENABLE_ADDRESSABLES var operation = Addressables.LoadResourceLocationsAsync(SceneBuilder.SceneNames); @@ -196,6 +183,29 @@ bool areLocationsValid() return true; } #endif +#endif + } + + public static bool IsSceneEnvironmentSetup() + { +#if UNITY_EDITOR + EditorBuildSettingsScene[] buildScenes = EditorBuildSettings.scenes; + foreach (string name in SceneBuilder.SceneNames) + { + if (!hasBuiltSceneWithName(name, buildScenes)) + return false; + } + return true; + + static bool hasBuiltSceneWithName(string name, EditorBuildSettingsScene[] buildScenes) + { + foreach (EditorBuildSettingsScene buildScene in buildScenes) + if (buildScene.path.Contains(name)) + return true; + return false; + } +#else + return false; #endif } } diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json index e0fe6fa9..465a29dd 100644 --- a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -4,7 +4,7 @@ { "type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "IncludeAssemblies", - "value": "{\"m_Value\":\"MyGameDevTools.SceneLoading\"}" + "value": "{\"m_Value\":\"MyGameDevTools.SceneLoading,MyGameDevTools.SceneLoading.Api\"}" }, { "type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", From 7ef87126f0e156cc6c31144b00bc2d47e1853cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Fri, 17 Jan 2025 19:57:09 -0300 Subject: [PATCH 15/53] feat: bump new version --- .../Runtime/API/AdvancedSceneManager.cs | 2 +- .../Runtime/Structs/LoadSceneInfoName.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs index abac2eda..fb36d41d 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs @@ -11,7 +11,7 @@ namespace MyGameDevTools.SceneLoading.Api { public static class AdvancedSceneManager { - static ISceneManager Instance + internal static ISceneManager Instance { get { diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/LoadSceneInfoName.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/LoadSceneInfoName.cs index 28244388..65874b03 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/LoadSceneInfoName.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/LoadSceneInfoName.cs @@ -18,7 +18,7 @@ namespace MyGameDevTools.SceneLoading /// Creates a new based on the scene's name or path. /// The scene must be added to the Build Settings in order to be loaded. ///
- /// `The scene's asset name or path, as displayed in the Build Settings window. + /// The scene's asset name or path, as displayed in the Build Settings window. public LoadSceneInfoName(string sceneNameOrPath) { if (string.IsNullOrWhiteSpace(sceneNameOrPath)) From 99ec00023c86fd4188eb16f9312d2de34540fbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 20 Jan 2025 23:05:30 -0300 Subject: [PATCH 16/53] feat: replace ValueTask return types with Task --- .../Runtime/API/AdvancedSceneManager.cs | 116 +++++++++--------- .../Runtime/AdvancedSceneManager.cs | 24 ++-- .../Runtime/Interfaces/ISceneManager.cs | 12 +- .../Utilities/SceneManagerExtensions.cs | 104 ++++++++-------- .../Runtime/Utilities/TaskExtensions.cs | 12 ++ .../Tests/Runtime/SceneManagerTests.cs | 34 ++--- .../Runtime/SceneManager_CancellationTests.cs | 6 +- .../Runtime/SceneManager_DisposeTests.cs | 8 +- .../Runtime/SceneManager_ExtensionTests.cs | 16 +-- .../Runtime/Utilities/SceneTestUtilities.cs | 2 +- 10 files changed, 173 insertions(+), 161 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs index fb36d41d..ffe3292f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs @@ -96,8 +96,8 @@ public static event Action SceneLoaded /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default) => Instance.TransitionAsync(sceneParameters, intermediateSceneReference, token); + /// A with all scenes loaded. + public static Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default) => Instance.TransitionAsync(sceneParameters, intermediateSceneReference, token); /// /// Loads the target scene or group of scenes provided via a struct. @@ -113,8 +113,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneParameters, progress, token); + /// A with all scenes loaded. + public static Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneParameters, progress, token); /// /// Unloads the target scene or group of scenes provided via a struct. @@ -124,11 +124,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) => Instance.UnloadAsync(sceneParameters, token); + public static Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) => Instance.UnloadAsync(sceneParameters, token); /// /// Gets the current active scene. @@ -176,8 +176,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneNames, setIndexActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAsync(string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneNames, setIndexActive, progress, token); /// /// Loads the target scenes. @@ -196,8 +196,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndices, setIndexActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAsync(int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndices, setIndexActive, progress, token); /// /// Loads the target scene. @@ -216,8 +216,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneName, setActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAsync(string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneName, setActive, progress, token); /// /// Loads the target scene. @@ -236,8 +236,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndex, setActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAsync(int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndex, setActive, progress, token); #if ENABLE_ADDRESSABLES /// @@ -257,8 +257,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReferences, setIndexActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAddressableAsync(AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReferences, setIndexActive, progress, token); /// /// Loads the target scenes. @@ -277,8 +277,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(addresses, setIndexActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAddressableAsync(string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(addresses, setIndexActive, progress, token); /// /// Loads the target scene. @@ -297,8 +297,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReference, setActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAddressableAsync(AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReference, setActive, progress, token); /// /// Loads the target scene. @@ -317,8 +317,8 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(address, setActive, progress, token); + /// A with all scenes loaded. + public static Task LoadAddressableAsync(string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(address, setActive, progress, token); #endif /// @@ -344,8 +344,8 @@ public static event Action SceneLoaded /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetSceneNames, loadingSceneName, setIndexActive, token); + /// A with all scenes loaded. + public static Task TransitionAsync(string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetSceneNames, loadingSceneName, setIndexActive, token); /// /// Triggers a transition to a group of scenes. @@ -370,8 +370,8 @@ public static event Action SceneLoaded /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndices, loadingBuildIndex, setIndexActive, token); + /// A with all scenes loaded. + public static Task TransitionAsync(int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndices, loadingBuildIndex, setIndexActive, token); /// /// Triggers a transition to the target scene. @@ -393,8 +393,8 @@ public static event Action SceneLoaded /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(string targetSceneName, string loadingSceneName = null, CancellationToken token = default) => Instance.TransitionAsync(targetSceneName, loadingSceneName, token); + /// A with all scenes loaded. + public static Task TransitionAsync(string targetSceneName, string loadingSceneName = null, CancellationToken token = default) => Instance.TransitionAsync(targetSceneName, loadingSceneName, token); /// /// Triggers a transition to the target scene. @@ -416,8 +416,8 @@ public static event Action SceneLoaded /// If -1, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndex, loadingBuildIndex, token); + /// A with all scenes loaded. + public static Task TransitionAsync(int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndex, loadingBuildIndex, token); #if ENABLE_ADDRESSABLES /// @@ -443,8 +443,8 @@ public static event Action SceneLoaded /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReferences, loadingAssetReference, setIndexActive, token); + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReferences, loadingAssetReference, setIndexActive, token); /// /// Triggers a transition to a group of scenes. @@ -469,8 +469,8 @@ public static event Action SceneLoaded /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddresses, loadingAddress, setIndexActive, token); + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddresses, loadingAddress, setIndexActive, token); /// /// Triggers a transition to the target scene. @@ -492,8 +492,8 @@ public static event Action SceneLoaded /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReference, loadingAssetReference, token); + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReference, loadingAssetReference, token); /// /// Triggers a transition to the target scene. @@ -515,8 +515,8 @@ public static event Action SceneLoaded /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(string targetAddress, string loadingAddress = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddress, loadingAddress, token); + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(string targetAddress, string loadingAddress = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddress, loadingAddress, token); #endif /// @@ -527,11 +527,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(string[] sceneNames, CancellationToken token = default) => Instance.UnloadAsync(sceneNames, token); + public static Task UnloadAsync(string[] sceneNames, CancellationToken token = default) => Instance.UnloadAsync(sceneNames, token); /// /// Unloads the target scene or group of scenes. @@ -541,11 +541,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(int[] buildIndices, CancellationToken token = default) => Instance.UnloadAsync(buildIndices, token); + public static Task UnloadAsync(int[] buildIndices, CancellationToken token = default) => Instance.UnloadAsync(buildIndices, token); /// /// Unloads the target scene or group of scenes. @@ -555,11 +555,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(Scene[] scenes, CancellationToken token = default) => Instance.UnloadAsync(scenes, token); + public static Task UnloadAsync(Scene[] scenes, CancellationToken token = default) => Instance.UnloadAsync(scenes, token); /// /// Unloads the target scene or group of scenes. @@ -569,11 +569,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(string sceneName, CancellationToken token = default) => Instance.UnloadAsync(sceneName, token); + public static Task UnloadAsync(string sceneName, CancellationToken token = default) => Instance.UnloadAsync(sceneName, token); /// /// Unloads the target scene or group of scenes. @@ -583,11 +583,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(int buildIndex, CancellationToken token = default) => Instance.UnloadAsync(buildIndex, token); + public static Task UnloadAsync(int buildIndex, CancellationToken token = default) => Instance.UnloadAsync(buildIndex, token); /// /// Unloads the target scene or group of scenes. @@ -597,11 +597,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(Scene scene, CancellationToken token = default) => Instance.UnloadAsync(scene, token); + public static Task UnloadAsync(Scene scene, CancellationToken token = default) => Instance.UnloadAsync(scene, token); #if ENABLE_ADDRESSABLES /// @@ -612,11 +612,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(AssetReference[] assetReferences, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReferences, token); + public static Task UnloadAddressableAsync(AssetReference[] assetReferences, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReferences, token); /// /// Unloads the target scene or group of scenes. @@ -626,11 +626,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(string[] addresses, CancellationToken token = default) => Instance.UnloadAddressableAsync(addresses, token); + public static Task UnloadAddressableAsync(string[] addresses, CancellationToken token = default) => Instance.UnloadAddressableAsync(addresses, token); /// /// Unloads the target scene or group of scenes. @@ -640,11 +640,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(AssetReference assetReference, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReference, token); + public static Task UnloadAddressableAsync(AssetReference assetReference, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReference, token); /// /// Unloads the target scene or group of scenes. @@ -654,11 +654,11 @@ public static event Action SceneLoaded /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(string address, CancellationToken token = default) => Instance.UnloadAddressableAsync(address, token); + public static Task UnloadAddressableAsync(string address, CancellationToken token = default) => Instance.UnloadAddressableAsync(address, token); #endif #endregion } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 23f77b9d..d2aba865 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -136,7 +136,7 @@ public Scene GetLoadedSceneByName(string name) throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); } - public ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) + public Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) { if (!sceneParameters.ShouldSetActive()) throw new ArgumentException($"[{GetType().Name}] You need to provide a SceneParameters object with a valid 'setIndexActive' value to perform scene transitions.", nameof(sceneParameters)); @@ -147,19 +147,19 @@ public ValueTask TransitionAsync(SceneParameters sceneParameters, I : TransitionWithIntermediateAsync(sceneParameters, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); } - public ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) + public Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); } - public ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) + public Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) { CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token).RunAndDisposeToken(linkedSource); } - async ValueTask LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) + async Task LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int setIndexActive = sceneParameters.GetIndexToActivate(); @@ -195,7 +195,7 @@ async ValueTask LoadScenesAsync_Internal(SceneParameters sceneParam return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); } - async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) + async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) { if (sceneInfos == null || sceneInfos.Length == 0) throw new ArgumentException($"[{GetType().Name}] Provided scene group is null or empty.", nameof(sceneInfos)); @@ -243,7 +243,7 @@ async ValueTask UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneIn return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); } - async ValueTask TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) + async Task TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) { // If only one scene is loaded, we need to create a temporary scene for transition. Scene tempScene = default; @@ -262,7 +262,7 @@ async ValueTask TransitionDirectlyAsync(SceneParameters sceneParame return new SceneResult(loadedScenes); } - async ValueTask TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async Task TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { Scene loadingScene; try @@ -286,7 +286,7 @@ async ValueTask TransitionWithIntermediateAsync(SceneParameters sce : await TransitionWithIntermediateNoLoadingAsync(sceneParameters, intermediateSceneInfo, token); } - async ValueTask TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + async Task TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; await WaitForLoadingStateAsync(progress, LoadingState.Loading, token); @@ -302,7 +302,7 @@ async ValueTask TransitionWithIntermediateLoadingAsync(SceneParamet return new SceneResult(loadedScenes); } - async ValueTask WaitForLoadingStateAsync(LoadingProgress progress, LoadingState targetState, CancellationToken token = default) + async Task WaitForLoadingStateAsync(LoadingProgress progress, LoadingState targetState, CancellationToken token = default) { while (progress.State != targetState && !token.IsCancellationRequested) { @@ -310,7 +310,7 @@ async ValueTask WaitForLoadingStateAsync(LoadingProgress progress, LoadingState } } - async ValueTask TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async Task TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { await UnloadSourceSceneAsync(token); Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); @@ -318,11 +318,11 @@ async ValueTask TransitionWithIntermediateNoLoadingAsync(SceneParam return new SceneResult(loadedScenes); } - ValueTask UnloadSourceSceneAsync(CancellationToken token) + Task UnloadSourceSceneAsync(CancellationToken token) { Scene sourceScene = GetActiveScene(); if (!sourceScene.IsValid()) - return default; + return Task.FromResult(default); return UnloadAsync(new SceneParameters(new LoadSceneInfoScene(sourceScene)), token); } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index f9ad1e8b..35225115 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -66,8 +66,8 @@ public interface ISceneManager : IDisposable /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - ValueTask TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); + /// A with all scenes loaded. + Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); /// /// Loads the target scene or group of scenes provided via a struct. @@ -83,8 +83,8 @@ public interface ISceneManager : IDisposable /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - ValueTask LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default); + /// A with all scenes loaded. + Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default); /// /// Unloads the target scene or group of scenes provided via a struct. @@ -94,11 +94,11 @@ public interface ISceneManager : IDisposable /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- ValueTask UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default); + Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default); /// /// Gets the current active scene in this instance. diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs index 26e7bbbd..a9893a34 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -28,8 +28,8 @@ public static class SceneManagerExtensions /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(this ISceneManager sceneManager, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); @@ -53,8 +53,8 @@ public static ValueTask LoadAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(this ISceneManager sceneManager, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); @@ -78,8 +78,8 @@ public static ValueTask LoadAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(this ISceneManager sceneManager, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName), setActive); return sceneManager.LoadAsync(sceneParams, progress, token); @@ -102,8 +102,8 @@ public static ValueTask LoadAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAsync(this ISceneManager sceneManager, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex), setActive); return sceneManager.LoadAsync(sceneParams, progress, token); @@ -127,8 +127,8 @@ public static ValueTask LoadAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); @@ -152,8 +152,8 @@ public static ValueTask LoadAddressableAsync(this ISceneManager sce /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); @@ -177,8 +177,8 @@ public static ValueTask LoadAddressableAsync(this ISceneManager sce /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference), setActive); return sceneManager.LoadAsync(sceneParams, progress, token); @@ -201,8 +201,8 @@ public static ValueTask LoadAddressableAsync(this ISceneManager sce /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static ValueTask LoadAddressableAsync(this ISceneManager sceneManager, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address), setActive); return sceneManager.LoadAsync(sceneParams, progress, token); @@ -232,8 +232,8 @@ public static ValueTask LoadAddressableAsync(this ISceneManager sce /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetSceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); @@ -263,8 +263,8 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetBuildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; @@ -291,8 +291,8 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); @@ -319,8 +319,8 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// If -1, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), true); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; @@ -351,8 +351,8 @@ public static ValueTask TransitionAsync(this ISceneManager sceneMan /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAssetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; @@ -382,8 +382,8 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAddresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); @@ -410,8 +410,8 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), true); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; @@ -438,8 +438,8 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static ValueTask TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, string loadingAddress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, string loadingAddress = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); @@ -455,11 +455,11 @@ public static ValueTask TransitionAddressableAsync(this ISceneManag /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos); @@ -474,11 +474,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos); @@ -493,11 +493,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); SceneParameters sceneParams = new(sceneInfos); @@ -512,11 +512,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName)); return sceneManager.UnloadAsync(sceneParams, token); @@ -530,11 +530,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex)); return sceneManager.UnloadAsync(sceneParams, token); @@ -548,11 +548,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoScene(scene)); return sceneManager.UnloadAsync(sceneParams, token); @@ -567,11 +567,11 @@ public static ValueTask UnloadAsync(this ISceneManager sceneManager /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos); @@ -586,11 +586,11 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos); @@ -605,11 +605,11 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference)); return sceneManager.UnloadAsync(sceneParams, token); @@ -623,11 +623,11 @@ public static ValueTask UnloadAddressableAsync(this ISceneManager s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static ValueTask UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address)); return sceneManager.UnloadAsync(sceneParams, token); diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs index 6e350df1..5ba6e790 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs @@ -6,6 +6,18 @@ namespace MyGameDevTools.SceneLoading { public static class TaskExtensions { + public static async Task RunAndDisposeToken(this Task valueTask, CancellationTokenSource tokenSource) + { + try + { + return await valueTask; + } + finally + { + tokenSource.Dispose(); + } + } + public static async void Forget(this Task task, Action onException = null) { try diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index c615783f..51b8426e 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -95,7 +95,7 @@ public IEnumerator InitializationScene_Unload() ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); WaitTask waitTask = default; - Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).AsTask())); + Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))))); yield return waitTask; } @@ -129,7 +129,7 @@ public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), name [UnityTest] public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)).AsTask(); + var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); yield return new WaitTask(loadTask); @@ -150,7 +150,7 @@ public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironmen [UnityTest] public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).AsTask()); + yield return new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1])))); Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } @@ -181,7 +181,7 @@ public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), name { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitValueTask(manager.LoadAsync(sceneParameters, progress)); + yield return new WaitTask(manager.LoadAsync(sceneParameters, progress)); Assert.AreEqual(1, progress.Value); } @@ -197,7 +197,7 @@ public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof for (int i = 0; i < length; i++) { var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); - yield return new WaitValueTask(loadTask); + yield return new WaitTask(loadTask); loadedScenes[i] = loadTask.Result; } @@ -219,7 +219,7 @@ public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(Sc var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = new WaitTask(manager.LoadAsync(sceneName).AsTask()); + var wait = new WaitTask(manager.LoadAsync(sceneName)); Assert.Throws(() => wait.MoveNext()); } @@ -235,7 +235,7 @@ public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(S var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = new WaitTask(manager.UnloadAsync(sceneName).AsTask()); + var wait = new WaitTask(manager.UnloadAsync(sceneName)); Assert.Throws(() => wait.MoveNext()); } @@ -243,7 +243,7 @@ public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(S public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { - yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene).AsTask(), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] @@ -259,7 +259,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron // The temporary scene unload does not go through the ISceneManager SceneManager.sceneUnloaded += sceneUnloaded; - var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene).AsTask(); + var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); yield return new WaitTask(task); @@ -284,18 +284,18 @@ public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviro { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitValueTask(task); + yield return new WaitTask(task); Scene scene = task.Result; task = manager.UnloadAsync(scene); - yield return new WaitValueTask(task); + yield return new WaitTask(task); Assert.Zero(manager.LoadedSceneCount); } - public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); manager.SceneLoaded += reportSceneLoaded; @@ -304,7 +304,7 @@ public IEnumerator Load_Template(ISceneManager manager, Func(task); + yield return new WaitTask(task); manager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; @@ -336,17 +336,17 @@ public IEnumerator Transition_Template(ISceneManager manager, Func manager.TotalSceneCount == sceneCount); } - public IEnumerator Unload_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) + public IEnumerator Unload_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); - yield return new WaitValueTask(load); + yield return new WaitTask(load); var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); var reportedScenes = new List(sceneCount); manager.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); - yield return new WaitValueTask(unload); + yield return new WaitTask(unload); manager.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; @@ -377,7 +377,7 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitValueTask LoadFirstScene(ISceneManager sceneManager) => new(sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); + public static WaitTask LoadFirstScene(ISceneManager sceneManager) => new(sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); void ReportSceneActivation(Scene previousScene, Scene newScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index 3ff4905f..84ce286b 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -11,7 +11,7 @@ public class SceneManager_CancellationTests : SceneTestBase public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters, token: tokenSource.Token).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters, token: tokenSource.Token)); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -22,10 +22,10 @@ public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironm public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); yield return waitTask; - waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token).AsTask()); + waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token)); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index 0fbc56ab..94bff706 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -25,7 +25,7 @@ public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func< public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -35,10 +35,10 @@ public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFun public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters).AsTask()); + WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); yield return waitTask; - waitTask = new(manager.UnloadAsync(sceneParameters).AsTask()); + waitTask = new(manager.UnloadAsync(sceneParameters)); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -50,7 +50,7 @@ public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneManagerCre async Awaitable Test() { ISceneManager manager = managerCreateFunc(); - await SceneManagerTests.LoadFirstScene(manager).ValueTask; + await SceneManagerTests.LoadFirstScene(manager).Task; var task = manager.TransitionAsync(sceneParameters, loadingScene); manager.Dispose(); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs index 199b3cb9..9bee61dd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs @@ -69,50 +69,50 @@ public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSo [UnityTest] public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(1, 0).AsTask(), 1, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(1, 0), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 0).AsTask(), _buildIndexes.Length, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 0), _buildIndexes.Length, 0); } [UnityTest] public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]).AsTask(), 1, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); } #if ENABLE_ADDRESSABLES [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]).AsTask(), 1, 0); + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]).AsTask(), 1, 0); + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]).AsTask(), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); } #endif diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index d2852f54..faff9570 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -11,7 +11,7 @@ public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) var lastScene = sceneManager.GetLastLoadedScene(); while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneManager.UnloadAsync(lastScene).AsTask()); + yield return new WaitTask(sceneManager.UnloadAsync(lastScene)); lastScene = sceneManager.GetLastLoadedScene(); } From 5fcc055a0c7965421f127b4057b4993c7d4e3fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 20 Jan 2025 23:38:48 -0300 Subject: [PATCH 17/53] fix: improve load scene info match with scene data --- .../Runtime/Interfaces/ISceneData.cs | 7 ++++ .../Runtime/Structs/SceneDataAddressable.cs | 9 ++++ .../Runtime/Structs/SceneDataStandard.cs | 5 +++ .../Runtime/Utilities/SceneDataUtilities.cs | 5 +-- .../Tests/Runtime/SceneManagerTests.cs | 42 +++++++++++++++++++ .../Runtime/Utilities/SceneTestEnvironment.cs | 7 ++++ 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs index e2a411f5..797c0676 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs @@ -37,6 +37,13 @@ public interface ISceneData ///
void UpdateSceneReference(); + /// + /// Returns whether this can be matched by the given . + /// If the is equal to the or has a direct reference to the scene, it returns true. + /// + /// to validate a match. + bool MatchesLoadSceneInfo(ILoadSceneInfo loadSceneInfo); + /// /// Triggers the load async operation and updates the reference. /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataAddressable.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataAddressable.cs index 821c8e9d..cf97d0f9 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataAddressable.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataAddressable.cs @@ -52,6 +52,15 @@ public void UpdateSceneReference() _sceneReference = AsyncOperation.GetResult(); } + public bool MatchesLoadSceneInfo(ILoadSceneInfo loadSceneInfo) + { + return loadSceneInfo.Type switch + { + LoadSceneInfoType.AssetReference or LoadSceneInfoType.Address => loadSceneInfo.Equals(_loadSceneInfo), + _ => loadSceneInfo.CanBeReferenceToScene(_sceneReference), + }; + } + public IAsyncSceneOperation LoadSceneAsync() { switch (_loadSceneInfo.Type) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataStandard.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataStandard.cs index 67340fe8..6f7ff868 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataStandard.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/SceneDataStandard.cs @@ -65,6 +65,11 @@ public void UpdateSceneReference() Debug.LogWarning($"[{nameof(SceneDataStandard)}] This type of scene data should not have its scene set automatically. Instead, it is expected to set it by calling {nameof(ISceneData.SetSceneReferenceManually)}."); } + public bool MatchesLoadSceneInfo(ILoadSceneInfo loadSceneInfo) + { + return loadSceneInfo.CanBeReferenceToScene(_sceneReference); + } + public IAsyncSceneOperation LoadSceneAsync() { switch (_loadSceneInfo.Type) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs index 547877d5..2eb7b678 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs @@ -158,15 +158,14 @@ public static bool TryLinkLoadedSceneWithSceneData(Scene scene, IList /// Tries to get an from a collection of s that match the given . ///
- public static bool TryGetSceneDataByLoadSceneInfo(ILoadSceneInfo loadSceneInfo, ICollection sceneDataList, out ISceneData sceneData) + public static bool TryGetSceneDataByLoadSceneInfo(ILoadSceneInfo loadSceneInfo, IEnumerable sceneDataList, out ISceneData sceneData) { if (loadSceneInfo == null) throw new ArgumentNullException(nameof(loadSceneInfo)); foreach (ISceneData tempSceneData in sceneDataList) { - if ((loadSceneInfo.Type == LoadSceneInfoType.SceneHandle && tempSceneData.SceneReference == (Scene)loadSceneInfo.Reference) - || tempSceneData.LoadSceneInfo.Equals(loadSceneInfo)) + if (tempSceneData.MatchesLoadSceneInfo(loadSceneInfo)) { sceneData = tempSceneData; return true; diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 51b8426e..e823d4d3 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -295,6 +295,48 @@ public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviro Assert.Zero(manager.LoadedSceneCount); } + [UnityTest] + public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + { + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + + yield return new WaitTask(task); + + task = manager.UnloadAsync(SceneBuilder.SceneNames[1]); + + yield return new WaitTask(task); + + Assert.Zero(manager.LoadedSceneCount); + } + + [UnityTest] + public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + { + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + + yield return new WaitTask(task); + + task = manager.UnloadAsync(SceneBuilder.ScenePaths[1]); + + yield return new WaitTask(task); + + Assert.Zero(manager.LoadedSceneCount); + } + + [UnityTest] + public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + { + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + + yield return new WaitTask(task); + + task = manager.UnloadAsync(1); + + yield return new WaitTask(task); + + Assert.Zero(manager.LoadedSceneCount); + } + public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index aef09ff7..bea5baaa 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -60,6 +60,13 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup #endif }; + public static readonly ILoadSceneInfo[] SingleLoadSceneInfoList_NoAddressable = new ILoadSceneInfo[] + { + new LoadSceneInfoName(SceneBuilder.SceneNames[1]), + new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), + new LoadSceneInfoIndex(1), + }; + public static readonly SceneParameters[] SceneParametersList = new SceneParameters[] { new(SingleLoadSceneInfoList[0], false), From c2ed748381ab5d6436b8ccdb68259a802981eb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Thu, 30 Jan 2025 01:23:01 -0300 Subject: [PATCH 18/53] fix: refactor awaitable calls, update loading code --- .../Runtime/AdvancedSceneManager.cs | 79 ++++++---------- .../Interfaces/IAsyncSceneOperation.cs | 6 ++ .../Runtime/Loading/LoadingBehavior.cs | 10 +- .../Runtime/Loading/LoadingFader.cs | 12 +-- .../Runtime/Loading/LoadingProgress.cs | 42 ++++----- .../Runtime/Loading/LoadingState.cs | 35 ------- .../Runtime/Loading/LoadingState.cs.meta | 11 --- .../Structs/AsyncSceneOperationAddressable.cs | 19 +++- .../Structs/AsyncSceneOperationStandard.cs | 19 +++- .../Runtime/Utilities/TaskExtensions.cs | 46 ---------- .../Runtime/Utilities/UnityTaskUtilities.cs | 92 +++++++++++++++++++ .../Utilities/UnityTaskUtilities.cs.meta | 2 + .../Runtime/Utilities/WaitValueTask.cs | 24 ----- .../Runtime/Utilities/WaitValueTask.cs.meta | 2 - .../Tests/Runtime/LoadingBehaviorTests.cs | 26 +++--- .../Tests/Runtime/LoadingFaderTests.cs | 7 +- .../Tests/Runtime/LoadingProgressTests.cs | 10 +- Packages/packages-lock.json | 4 +- ProjectSettings/ProjectVersion.txt | 4 +- 19 files changed, 206 insertions(+), 244 deletions(-) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index d2aba865..5171f3b6 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -173,11 +173,7 @@ async Task LoadScenesAsync_Internal(SceneParameters sceneParameters sceneDataArray[i].LoadSceneAsync(); } - while (!SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray) && !token.IsCancellationRequested) - { - await Awaitable.NextFrameAsync(token); - progress?.Report(SceneDataUtilities.GetAverageSceneLoadOperationProgress(sceneDataArray)); - } + await PollProgressAsync(sceneDataArray, progress, token); token.ThrowIfCancellationRequested(); @@ -200,9 +196,10 @@ async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, if (sceneInfos == null || sceneInfos.Length == 0) throw new ArgumentException($"[{GetType().Name}] Provided scene group is null or empty.", nameof(sceneInfos)); + int sceneCount = sceneInfos.Length; ISceneData[] sceneDataArray = SceneDataUtilities.GetLoadedSceneDatasWithLoadSceneInfos(sceneInfos, _loadedScenes); + Task[] loadTasks = new Task[sceneCount]; - int sceneCount = sceneInfos.Length; ISceneData tempSceneData; int i; for (i = 0; i < sceneCount; i++) @@ -210,25 +207,20 @@ async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, tempSceneData = sceneDataArray[i]; _loadedScenes.Remove(tempSceneData); _unloadingScenes.Add(tempSceneData); - tempSceneData.UnloadSceneAsync(); + loadTasks[i] = UnityTaskUtilities.FromAsyncOperation(sceneDataArray[i].UnloadSceneAsync(), token); } - while (!SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray) && !token.IsCancellationRequested) + try { - // Since the unload operation will keep running even after cancelling the task, - // we need to remove these scenes from the unloading scenes list on cancellation. - try - { - await Awaitable.NextFrameAsync(token); - } - catch (OperationCanceledException exception) + await Task.WhenAll(loadTasks); + } + catch (OperationCanceledException exception) + { + for (i = 0; i < sceneCount; i++) { - for (i = 0; i < sceneCount; i++) - { - _unloadingScenes.Remove(sceneDataArray[i]); - } - throw exception; + _unloadingScenes.Remove(sceneDataArray[i]); } + throw exception; } for (i = 0; i < sceneCount; i++) @@ -245,7 +237,7 @@ async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, async Task TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) { - // If only one scene is loaded, we need to create a temporary scene for transition. + // If only one scene is loaded, create a temporary scene for transition. Scene tempScene = default; if (LoadedSceneCount <= 1) { @@ -257,30 +249,18 @@ async Task TransitionDirectlyAsync(SceneParameters sceneParameters, if (tempScene.IsValid()) { - await Awaitable.FromAsyncOperation(SceneManager.UnloadSceneAsync(tempScene)); + IAsyncSceneOperation unloadOperation = new AsyncSceneOperationStandard(SceneManager.UnloadSceneAsync(tempScene)); + await UnityTaskUtilities.FromAsyncOperation(unloadOperation, token); } return new SceneResult(loadedScenes); } async Task TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { - Scene loadingScene; - try - { - loadingScene = await LoadAsync(new SceneParameters(intermediateSceneInfo, false), token: token); - } - catch - { - throw; - } - + Scene loadingScene = await LoadAsync(new SceneParameters(intermediateSceneInfo, false), token: token); intermediateSceneInfo = new LoadSceneInfoScene(loadingScene); -#if UNITY_2023_2_OR_NEWER LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None).FirstOrDefault(l => l.gameObject.scene == loadingScene); -#else - LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(l => l.gameObject.scene == loadingScene); -#endif return loadingBehavior ? await TransitionWithIntermediateLoadingAsync(sceneParameters, intermediateSceneInfo, loadingBehavior, token) : await TransitionWithIntermediateNoLoadingAsync(sceneParameters, intermediateSceneInfo, token); @@ -289,27 +269,17 @@ async Task TransitionWithIntermediateAsync(SceneParameters scenePar async Task TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; - await WaitForLoadingStateAsync(progress, LoadingState.Loading, token); - + await progress.TransitionInTask.Task; await UnloadSourceSceneAsync(token); Scene[] loadedScenes = await LoadAsync(sceneParameters, progress, token); - progress.SetState(LoadingState.TargetSceneLoaded); - - await WaitForLoadingStateAsync(progress, LoadingState.TransitionComplete, token); + progress.SetLoadingCompleted(); + await progress.TransitionOutTask.Task; await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); return new SceneResult(loadedScenes); } - async Task WaitForLoadingStateAsync(LoadingProgress progress, LoadingState targetState, CancellationToken token = default) - { - while (progress.State != targetState && !token.IsCancellationRequested) - { - await Awaitable.NextFrameAsync(token); - } - } - async Task TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { await UnloadSourceSceneAsync(token); @@ -318,6 +288,17 @@ async Task TransitionWithIntermediateNoLoadingAsync(SceneParameters return new SceneResult(loadedScenes); } + async Task PollProgressAsync(ISceneData[] sceneDataArray, IProgress progress, CancellationToken token = default) + { + bool isDone = false; + while (!isDone && !token.IsCancellationRequested) + { + await Task.Yield(); + isDone = SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray); + progress?.Report(SceneDataUtilities.GetAverageSceneLoadOperationProgress(sceneDataArray)); + } + } + Task UnloadSourceSceneAsync(CancellationToken token) { Scene sourceScene = GetActiveScene(); diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/IAsyncSceneOperation.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/IAsyncSceneOperation.cs index 539a3e3a..f30007e7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/IAsyncSceneOperation.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/IAsyncSceneOperation.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine.SceneManagement; namespace MyGameDevTools.SceneLoading @@ -7,6 +8,11 @@ namespace MyGameDevTools.SceneLoading ///
public interface IAsyncSceneOperation { + /// + /// Event fired when the async operation is done. + /// + event Action Completed; + /// /// Progress of the load/unload operation from 0 to 1 (float). /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingBehavior.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingBehavior.cs index 584459a6..70c963a7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingBehavior.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingBehavior.cs @@ -21,19 +21,19 @@ public class LoadingBehavior : MonoBehaviour void Awake() { Progress = new LoadingProgress(); - Progress.StateChanged += OnLoadingStateChange; + Progress.LoadingCompleted += OnLoadingCompleted; } void Start() { if (!waitForScriptedStart) - Progress.SetState(LoadingState.Loading); + Progress.StartTransition(); } - void OnLoadingStateChange(LoadingState loadingState) + void OnLoadingCompleted() { - if (loadingState == LoadingState.TargetSceneLoaded && !waitForScriptedEnd) - Progress.SetState(LoadingState.TransitionComplete); + if (!waitForScriptedEnd) + Progress.EndTransition(); } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingFader.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingFader.cs index 76c6877a..26cb834a 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingFader.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingFader.cs @@ -28,23 +28,17 @@ void Awake() void Start() { _loadingProgress = loadingBehavior.Progress; - _loadingProgress.StateChanged += OnLoadingStateChanged; + _loadingProgress.LoadingCompleted += FadeOut; FadeIn(); } - void OnLoadingStateChanged(LoadingState loadingState) - { - if (loadingState == LoadingState.TargetSceneLoaded) - FadeOut(); - } - void FadeOut() { StartCoroutine(fadeOutRoutine()); IEnumerator fadeOutRoutine() { yield return FadeRoutine(_fadeOutCurve); - _loadingProgress.SetState(LoadingState.TransitionComplete); + _loadingProgress.EndTransition(); } } @@ -54,7 +48,7 @@ void FadeIn() IEnumerator fadeInRoutine() { yield return FadeRoutine(_fadeInCurve); - _loadingProgress.SetState(LoadingState.Loading); + _loadingProgress.StartTransition(); } } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingProgress.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingProgress.cs index ff6f31c8..089c7293 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingProgress.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingProgress.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using UnityEngine; namespace MyGameDevTools.SceneLoading @@ -8,41 +9,34 @@ namespace MyGameDevTools.SceneLoading ///
public class LoadingProgress : IProgress { - /// - /// Reports when the has changed. - /// - public event Action StateChanged; /// /// Reports when the scene loading progress increases. Values range from 0 to 1. /// public event Action Progressed; + public event Action LoadingCompleted; - /// - /// Current state of the scene loading progress. - /// - public LoadingState State { get; private set; } + public readonly TaskCompletionSource TransitionInTask; + public readonly TaskCompletionSource TransitionOutTask; - /// - /// Creates a new instance of a , optionally adjusting its loading ratio. - ///
- ///
public LoadingProgress() { - State = LoadingState.WaitingToStart; + TransitionInTask = new TaskCompletionSource(); + TransitionOutTask = new TaskCompletionSource(); } - /// - /// Sets the value. - /// You can use this method to apply loading screen transition effects, such as fade in/out. - ///
- /// The target scene will only start to be loaded on the state, and the entire transition will only finish in the state. - /// The only sets the state, once after the target scene has finished loading in the background. - ///
- /// The to be set. - public void SetState(LoadingState targetState) + public void StartTransition() + { + TransitionInTask.SetResult(true); + } + + public void EndTransition() + { + TransitionOutTask.SetResult(true); + } + + public void SetLoadingCompleted() { - State = targetState; - StateChanged?.Invoke(State); + LoadingCompleted?.Invoke(); } /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs deleted file mode 100644 index 785d4d84..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace MyGameDevTools.SceneLoading -{ - /// - /// States of the loading scene, during a scene transition operation. - /// - public enum LoadingState - { - /// - /// Default state. Holds the loading of the target scene until the state is set. - /// Can be used to display loading screen transition effects, such as a fade in. - /// - WaitingToStart, - /// - /// The target scene is being loaded during this state. - /// Can be set automatically by the if is disabled. - ///
- /// Otherwise, it should be set via after a loading screen transition effect, such as a fade in. - ///
- Loading, - /// - /// The target scene has been successfully loaded at this state. - /// It is set by the . Do not set this state manually. - ///
- /// Holds the conclusion of the scene transition until the state is set. - ///
- TargetSceneLoaded, - /// - /// The scene transition is complete and the loading scene can be unloaded. - /// Can be set automatically by the if is disabled. - ///
- /// Otherwise, it should be set via after a loading screen transition effect, such as a fade out. - ///
- TransitionComplete - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs.meta deleted file mode 100644 index 047aa594..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Loading/LoadingState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0eea660b2ae8d4e498bba8839358ec36 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationAddressable.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationAddressable.cs index 2bbc3f7b..47b87fcb 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationAddressable.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationAddressable.cs @@ -7,15 +7,17 @@ namespace MyGameDevTools.SceneLoading { /// - /// Struct to implement with the addressable . + /// Implementation of with the addressable . /// - public readonly struct AsyncSceneOperationAddressable : IAsyncSceneOperation + public class AsyncSceneOperationAddressable : IAsyncSceneOperation { - public readonly float Progress => _asyncOperationHandle.PercentComplete; + public event Action Completed; - public readonly bool IsDone => _asyncOperationHandle.IsDone; + public float Progress => _asyncOperationHandle.PercentComplete; - public readonly bool HasDirectReferenceToScene => true; + public bool IsDone => _asyncOperationHandle.IsDone; + + public bool HasDirectReferenceToScene => true; public AsyncOperationHandle AsyncOperationHandle => _asyncOperationHandle; @@ -27,6 +29,7 @@ public AsyncSceneOperationAddressable(AsyncOperationHandle operat throw new ArgumentException($"Cannot create a {nameof(AsyncSceneOperationAddressable)} from an invalid AsyncOperationHandle.", nameof(operationHandle)); _asyncOperationHandle = operationHandle; + _asyncOperationHandle.CompletedTypeless += OnAsyncOperationCompleted; } public Scene GetResult() @@ -38,6 +41,12 @@ public Scene GetResult() return _asyncOperationHandle.Result.Scene; } + + void OnAsyncOperationCompleted(AsyncOperationHandle asyncOperation) + { + _asyncOperationHandle.CompletedTypeless -= OnAsyncOperationCompleted; + Completed?.Invoke(); + } } } #endif \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationStandard.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationStandard.cs index 54f259c9..708eca9c 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationStandard.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Structs/AsyncSceneOperationStandard.cs @@ -5,21 +5,24 @@ namespace MyGameDevTools.SceneLoading { /// - /// Struct to implement with the non-addressable . + /// Implementation of with the non-addressable . /// - public readonly struct AsyncSceneOperationStandard : IAsyncSceneOperation + public class AsyncSceneOperationStandard : IAsyncSceneOperation { - public readonly float Progress => _asyncOperation.progress; + public event Action Completed; - public readonly bool IsDone => _asyncOperation.isDone; + public float Progress => _asyncOperation.progress; - public readonly bool HasDirectReferenceToScene => false; + public bool IsDone => _asyncOperation.isDone; + + public bool HasDirectReferenceToScene => false; readonly AsyncOperation _asyncOperation; public AsyncSceneOperationStandard(AsyncOperation operation) { _asyncOperation = operation ?? throw new ArgumentException($"Cannot create a {nameof(AsyncSceneOperationStandard)} without a valid AsyncOperation instance.", nameof(operation)); + _asyncOperation.completed += OnAsyncOperationCompleted; } public Scene GetResult() @@ -27,5 +30,11 @@ public Scene GetResult() Debug.LogWarning($"{nameof(AsyncSceneOperationStandard)} cannot link directly to the loaded scene due to SceneManager API limitations."); return default; } + + void OnAsyncOperationCompleted(AsyncOperation asyncOperation) + { + _asyncOperation.completed -= OnAsyncOperationCompleted; + Completed?.Invoke(); + } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs index 5ba6e790..8cd7d65d 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using System.Threading.Tasks; @@ -17,50 +16,5 @@ public static async Task RunAndDisposeToken(this Task valueTask, Cancel tokenSource.Dispose(); } } - - public static async void Forget(this Task task, Action onException = null) - { - try - { - await task; - } - catch (Exception exception) - { - if (onException == null) - throw exception; - - onException(exception); - } - } - } - - public static class ValueTaskExtensions - { - public static async ValueTask RunAndDisposeToken(this ValueTask valueTask, CancellationTokenSource tokenSource) - { - try - { - return await valueTask; - } - finally - { - tokenSource.Dispose(); - } - } - - public static async void Forget(this ValueTask valueTask, Action onException = null) - { - try - { - await valueTask; - } - catch (Exception exception) - { - if (onException == null) - throw exception; - - onException(exception); - } - } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs new file mode 100644 index 00000000..623a34c9 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.LowLevel; + +namespace MyGameDevTools.SceneLoading +{ + public static class UnityTaskUtilities + { + static Queue Actions; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void HookToPlayerLoop() + { +#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER + bool domainReloadDisabled = UnityEditor.EditorSettings.enterPlayModeOptionsEnabled && UnityEditor.EditorSettings.enterPlayModeOptions.HasFlag(UnityEditor.EnterPlayModeOptions.DisableDomainReload); + if (!domainReloadDisabled && Actions != null) + return; +#else + if (Actions != null) + return; +#endif + + Actions = new Queue(16); + PlayerLoopSystem playerLoop = PlayerLoop.GetCurrentPlayerLoop(); + List updatedSystems = new(playerLoop.subSystemList) + { + new PlayerLoopSystem + { + type = typeof(UnityTaskUtilities), + updateDelegate = ProcessMainThreadQueue + } + }; + + playerLoop.subSystemList = updatedSystems.ToArray(); + PlayerLoop.SetPlayerLoop(playerLoop); + } + + public static Task FromAsyncOperation(IAsyncSceneOperation asyncSceneOperation, CancellationToken token = default) + { + TaskCompletionSource tcs = new(); + + token.Register(() => + { + if (!tcs.Task.IsCompleted) + { + tcs.TrySetCanceled(token); + } + }); + + Enqueue(() => + { + if (tcs.Task.IsCanceled || tcs.Task.IsFaulted) + return; + + if (asyncSceneOperation.IsDone) + { + tcs.SetResult(true); + return; + } + + asyncSceneOperation.Completed += () => + { + tcs.TrySetResult(true); + }; + }); + + return tcs.Task; + } + + static void Enqueue(Action action) + { + lock (Actions) + { + Actions.Enqueue(action); + } + } + + static void ProcessMainThreadQueue() + { + lock (Actions) + { + while (Actions.TryDequeue(out Action action)) + { + action.Invoke(); + } + } + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs.meta new file mode 100644 index 00000000..f5824d8c --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/UnityTaskUtilities.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ee47331024b569f45b526a646a9a6013 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs deleted file mode 100644 index 42a57c31..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections; -using System.Threading.Tasks; - -namespace MyGameDevTools.SceneLoading -{ - public readonly struct WaitValueTask : IEnumerator - { - public object Current => null; - - public readonly ValueTask ValueTask; - - public WaitValueTask(ValueTask valueTask) - { - ValueTask = valueTask; - } - - public bool MoveNext() - { - return !ValueTask.IsCompleted && !ValueTask.IsCanceled && !ValueTask.IsFaulted; - } - - public void Reset() { } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta deleted file mode 100644 index beedf3ce..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/WaitValueTask.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4c3e708735afb0e4aa8caf712ac9245b \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingBehaviorTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingBehaviorTests.cs index ca67cabe..86cd97c2 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingBehaviorTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingBehaviorTests.cs @@ -25,16 +25,12 @@ public IEnumerator AutomaticTriggers() var behavior = new GameObject().AddComponent(); var progress = behavior.Progress; - Assert.AreEqual(LoadingState.WaitingToStart, progress.State); - yield return null; - Assert.AreEqual(LoadingState.Loading, progress.State); - progress.Report(1); - progress.SetState(LoadingState.TargetSceneLoaded); + progress.SetLoadingCompleted(); - Assert.AreEqual(LoadingState.TransitionComplete, progress.State); + Assert.True(progress.TransitionOutTask.Task.Result); } [UnityTest] @@ -45,23 +41,23 @@ public IEnumerator ManualTriggers() behavior.waitForScriptedStart = true; behavior.waitForScriptedEnd = true; - var progress = behavior.Progress; - - Assert.AreEqual(LoadingState.WaitingToStart, progress.State); + bool completed = false; + var progress = behavior.Progress; + progress.LoadingCompleted += () => completed = true; yield return null; - Assert.AreEqual(LoadingState.WaitingToStart, progress.State); + progress.StartTransition(); + Assert.True(progress.TransitionInTask.Task.Result); - progress.SetState(LoadingState.Loading); progress.Report(1); - progress.SetState(LoadingState.TargetSceneLoaded); + progress.SetLoadingCompleted(); yield return null; - Assert.AreEqual(LoadingState.TargetSceneLoaded, progress.State); + Assert.True(completed); - progress.SetState(LoadingState.TransitionComplete); - Assert.AreEqual(LoadingState.TransitionComplete, progress.State); + progress.EndTransition(); + Assert.True(progress.TransitionOutTask.Task.Result); } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingFaderTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingFaderTests.cs index d678a9f7..faf87327 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingFaderTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingFaderTests.cs @@ -34,18 +34,17 @@ public IEnumerator FadeInOut() loadingFader.fadeTime = .2f; loadingFader.loadingBehavior = loadingBehavior; - Assert.AreEqual(LoadingState.WaitingToStart, progress.State); Assert.AreEqual(0, canvasGroup.alpha); yield return new WaitForSeconds(loadingFader.fadeTime * 2); - Assert.AreEqual(LoadingState.Loading, progress.State); + Assert.True(progress.TransitionInTask.Task.IsCompletedSuccessfully); Assert.AreEqual(1, canvasGroup.alpha); - progress.SetState(LoadingState.TargetSceneLoaded); + progress.SetLoadingCompleted(); yield return new WaitForSeconds(loadingFader.fadeTime * 2); - Assert.AreEqual(LoadingState.TransitionComplete, progress.State); + Assert.True(progress.TransitionOutTask.Task.IsCompletedSuccessfully); Assert.AreEqual(0, canvasGroup.alpha); } } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingProgressTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingProgressTests.cs index aa920970..dfa23bc0 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingProgressTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/LoadingProgressTests.cs @@ -8,14 +8,12 @@ public class LoadingProgressTests public void SetState_Test() { var progress = new LoadingProgress(); - Assert.AreEqual(LoadingState.WaitingToStart, progress.State); - LoadingState cachedState = default; - progress.StateChanged += state => cachedState = state; + bool completed = false; + progress.LoadingCompleted += () => completed = true; - progress.SetState(LoadingState.Loading); - Assert.AreEqual(LoadingState.Loading, progress.State); - Assert.AreEqual(progress.State, cachedState); + progress.SetLoadingCompleted(); + Assert.True(completed); } [Test] diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 2a2293d0..8e6c3d9d 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -43,7 +43,7 @@ "com.unity.ide.visualstudio": "2.0.22", "com.unity.ide.rider": "3.0.31", "com.unity.editorcoroutines": "1.0.0", - "com.unity.performance.profile-analyzer": "1.2.2", + "com.unity.performance.profile-analyzer": "1.2.3", "com.unity.test-framework": "1.4.5", "com.unity.testtools.codecoverage": "1.2.6" } @@ -67,7 +67,7 @@ "url": "https://packages.unity.com" }, "com.unity.performance.profile-analyzer": { - "version": "1.2.2", + "version": "1.2.3", "depth": 1, "source": "registry", "dependencies": {}, diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index ffdee9b2..d5ce6c02 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.31f1 -m_EditorVersionWithRevision: 6000.0.31f1 (a206c360e2a8) +m_EditorVersion: 6000.0.33f1 +m_EditorVersionWithRevision: 6000.0.33f1 (433b0a79340b) From 908023f0b0bb4f460f2a5d0266728660aa5bdaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Thu, 30 Jan 2025 20:06:34 -0300 Subject: [PATCH 19/53] increase code coverage --- .../Runtime/API/SceneManager_ApiTests.cs | 76 ------- .../API/SceneManager_Api_Extensions_Tests.cs | 202 +++++++++++++++++ .../SceneManager_Api_Extensions_Tests.cs.meta | 2 + .../Runtime/API/SceneManager_Api_Tests.cs | 213 ++++++++++++++++++ ...cs.meta => SceneManager_Api_Tests.cs.meta} | 0 .../Runtime/SceneManager_ExtensionTests.cs | 17 ++ ProjectSettings/ProjectSettings.asset | 7 +- 7 files changed, 439 insertions(+), 78 deletions(-) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/{SceneManager_ApiTests.cs.meta => SceneManager_Api_Tests.cs.meta} (100%) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs deleted file mode 100644 index dda62d47..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using MyGameDevTools.SceneLoading.Tests; -using NUnit.Framework; -using UnityEngine.SceneManagement; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Api.Tests -{ - public class SceneManager_ApiTests : IPrebuildSetup, IPostBuildCleanup - { - int _scenesActivated; - int _scenesUnloaded; - int _scenesLoaded; - - public void Setup() => new SceneTestEnvironment().Setup(); - - public void Cleanup() => new SceneTestEnvironment().Cleanup(); - - [OneTimeSetUp] - public void OneTimeSetup() - { - SceneTestEnvironment.ValidateSceneEnvironment(); - - AdvancedSceneManager.ActiveSceneChanged += ReportSceneActivation; - AdvancedSceneManager.SceneUnloaded += ReportSceneUnloaded; - AdvancedSceneManager.SceneLoaded += ReportSceneLoaded; - } - - [OneTimeTearDown] - public void OneTimeTeardown() - { - AdvancedSceneManager.ActiveSceneChanged -= ReportSceneActivation; - AdvancedSceneManager.SceneUnloaded -= ReportSceneUnloaded; - AdvancedSceneManager.SceneLoaded -= ReportSceneLoaded; - } - - [SetUp] - public void TestSetup() - { - AdvancedSceneManager.SetActiveScene(AdvancedSceneManager.GetLoadedSceneAt(0)); - - _scenesActivated = 0; - _scenesUnloaded = 0; - _scenesLoaded = 0; - } - - [Test] - public void InitialStateTest() - { - int loadedScenes = 0; - Assert.DoesNotThrow(() => loadedScenes = AdvancedSceneManager.LoadedSceneCount); - Assert.AreEqual(1, loadedScenes); - Assert.AreEqual(1, AdvancedSceneManager.TotalSceneCount); - - Scene activeScene = SceneManager.GetActiveScene(); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetActiveScene()); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLastLoadedScene()); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneAt(0)); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneByName(activeScene.name)); - } - - void ReportSceneActivation(Scene previousScene, Scene newScene) - { - _scenesActivated++; - } - - void ReportSceneUnloaded(Scene unloadedScene) - { - _scenesUnloaded++; - } - - void ReportSceneLoaded(Scene loadedScene) - { - _scenesLoaded++; - } - } -} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs new file mode 100644 index 00000000..7b3e5ff5 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs @@ -0,0 +1,202 @@ +using System.Collections; +using System.Threading.Tasks; +using MyGameDevTools.SceneLoading.Tests; +using NUnit.Framework; +using UnityEngine.AddressableAssets; +using UnityEngine.ResourceManagement.AsyncOperations; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Api.Tests +{ + public partial class SceneManager_Api_Tests + { + int[] _buildIndexes = new[] { 0, 1, 2, 3 }; + + AssetReference[] _assetReferences; + + [OneTimeSetUp] + public void AssetReferenceSetup() + { + AsyncOperationHandle operationHandle = Addressables.LoadAssetAsync(nameof(SceneReferenceData)); + operationHandle.WaitForCompletion(); + + SceneReferenceData sceneReferenceData = operationHandle.Result; + _assetReferences = sceneReferenceData.sceneReferences.ToArray(); + + Addressables.Release(operationHandle); + } + + [UnityTest] + public IEnumerator Load_Extension_ByIndex() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAsync(1, true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByIndex_Multiple() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName_Multiple() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress_Multiple() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple() + { + var progress = new SimpleProgress(); + yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); + } +#endif + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(1, 0), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex_Multiple() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(_buildIndexes, 0), _buildIndexes.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName_Multiple() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple() + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); + } +#endif + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(1, true), () => AdvancedSceneManager.UnloadAsync(1), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex_Multiple() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(_buildIndexes, 0), () => AdvancedSceneManager.UnloadAsync(_buildIndexes), _buildIndexes.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true), () => AdvancedSceneManager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName_Multiple() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 0), () => AdvancedSceneManager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByScene_Multiple() + { + Task loadTask = Task.FromResult(default); + yield return Unload_Template(() => + { + loadTask = AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 0); + return loadTask; + }, () => + { + SceneResult result = loadTask.GetAwaiter().GetResult(); + return AdvancedSceneManager.UnloadAsync(result.GetScenes()); + }, SceneBuilder.SceneNames.Length); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => AdvancedSceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => AdvancedSceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences[1], true), () => AdvancedSceneManager.UnloadAddressableAsync(_assetReferences[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple() + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences, 0), () => AdvancedSceneManager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); + } +#endif + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta new file mode 100644 index 00000000..a98247e1 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 03df37f55ff66674b848bc615005b6b1 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs new file mode 100644 index 00000000..fb074cfd --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using MyGameDevTools.SceneLoading.Tests; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Api.Tests +{ + public partial class SceneManager_Api_Tests : IPrebuildSetup, IPostBuildCleanup + { + int _scenesActivated; + int _scenesUnloaded; + int _scenesLoaded; + + public void Setup() => new SceneTestEnvironment().Setup(); + + public void Cleanup() => new SceneTestEnvironment().Cleanup(); + + [OneTimeSetUp] + public void OneTimeSetup() + { + SceneTestEnvironment.ValidateSceneEnvironment(); + + AdvancedSceneManager.ActiveSceneChanged += ReportSceneActivation; + AdvancedSceneManager.SceneUnloaded += ReportSceneUnloaded; + AdvancedSceneManager.SceneLoaded += ReportSceneLoaded; + } + + [OneTimeTearDown] + public void OneTimeTeardown() + { + AdvancedSceneManager.ActiveSceneChanged -= ReportSceneActivation; + AdvancedSceneManager.SceneUnloaded -= ReportSceneUnloaded; + AdvancedSceneManager.SceneLoaded -= ReportSceneLoaded; + } + + [SetUp] + public void TestSetup() + { + AdvancedSceneManager.SetActiveScene(AdvancedSceneManager.GetLoadedSceneAt(0)); + + _scenesActivated = 0; + _scenesUnloaded = 0; + _scenesLoaded = 0; + } + + [UnityTearDown] + public IEnumerator UnloadScenesOnTearDown() + { + yield return UnloadAllScenes(); + Assert.AreEqual(1, SceneManager.sceneCount); + } + + [Test] + public void InitialStateTest() + { + int loadedScenes = 0; + Assert.DoesNotThrow(() => loadedScenes = AdvancedSceneManager.LoadedSceneCount); + Assert.AreEqual(1, loadedScenes); + Assert.AreEqual(1, AdvancedSceneManager.TotalSceneCount); + + Scene activeScene = SceneManager.GetActiveScene(); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetActiveScene()); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLastLoadedScene()); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneAt(0)); + Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneByName(activeScene.name)); + } + + [UnityTest] + public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + var progress = new SimpleProgress(); + return Load_Template(() => AdvancedSceneManager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); + } + + [UnityTest] + public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(sceneParameters), () => AdvancedSceneManager.UnloadAsync(sceneParameters), sceneParameters.Length); + } + + [UnityTest] + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. + TransitionSceneParametersList))] SceneParameters sceneParameters) + { + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(sceneParameters), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + } + + public IEnumerator Load_Template(Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + { + var reportedScenes = new List(sceneCount); + AdvancedSceneManager.SceneLoaded += reportSceneLoaded; + + var task = loadTask(); + + Assert.AreEqual(0, progress.Value); + + yield return new WaitTask(task); + + AdvancedSceneManager.SceneLoaded -= reportSceneLoaded; + Scene[] loadedScenes = task.Result; + + Assert.AreEqual(1, progress.Value); + Assert.AreEqual(sceneCount, loadedScenes.Length); + Assert.AreEqual(sceneCount, reportedScenes.Count); + Assert.AreEqual(sceneCount + 1, AdvancedSceneManager.LoadedSceneCount); + if (setIndexActive >= 0) + Assert.AreEqual(AdvancedSceneManager.GetActiveScene(), loadedScenes[setIndexActive]); + Assert.AreEqual(sceneCount, _scenesLoaded); + Assert.AreEqual(0, _scenesUnloaded); + Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); + + void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); + } + + public IEnumerator Transition_Template(Func> transitionTask, int sceneCount, int setIndexActive) + { + yield return LoadFirstScene(); + + var task = transitionTask(); + yield return new WaitTask(task); + + Scene[] loadedScenes = task.Result; + Assert.AreEqual(sceneCount, loadedScenes.Length); + Assert.AreEqual(loadedScenes[setIndexActive], AdvancedSceneManager.GetActiveScene()); + + yield return new WaitUntil(() => AdvancedSceneManager.TotalSceneCount == sceneCount + 1); + } + + public IEnumerator Unload_Template(Func> loadTask, Func> unloadTask, int sceneCount) + { + var load = loadTask(); + yield return new WaitTask(load); + var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); + + var reportedScenes = new List(sceneCount); + AdvancedSceneManager.SceneUnloaded += reportSceneUnloaded; + + var unload = unloadTask(); + yield return new WaitTask(unload); + + AdvancedSceneManager.SceneUnloaded -= reportSceneUnloaded; + Scene[] unloadedScenes = unload.Result; + + Assert.AreEqual(sceneCount, unloadedScenes.Length); + Assert.AreEqual(sceneCount, reportedScenes.Count); + Assert.AreEqual(1, AdvancedSceneManager.LoadedSceneCount); + Assert.AreEqual(sceneCount, _scenesLoaded); + Assert.AreEqual(sceneCount, _scenesUnloaded); + + for (int i = 0; i < sceneCount; i++) + Assert.True(hasReference(loadedSceneHandles[i], reportedScenes)); + + void reportSceneUnloaded(Scene loadedScene) => reportedScenes.Add(loadedScene); + + bool hasReference(int handle, List scenes) + { + foreach (var scene in scenes) + if (scene.handle == handle) + { + scenes.Remove(scene); + return true; + } + return false; + } + } + + /// + /// Required to test some transition scenarios. + /// + public static WaitTask LoadFirstScene() => new(AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); + + public static IEnumerator UnloadManagerScenes() + { + var lastScene = AdvancedSceneManager.GetLastLoadedScene(); + // The AdvancedSceneManager registers the init scene as one of its managed scenes + while (AdvancedSceneManager.LoadedSceneCount > 1 && lastScene.IsValid()) + { + yield return new WaitTask(AdvancedSceneManager.UnloadAsync(lastScene)); + lastScene = AdvancedSceneManager.GetLastLoadedScene(); + } + + Assert.AreEqual(1, AdvancedSceneManager.LoadedSceneCount); + Assert.True(AdvancedSceneManager.GetActiveScene().IsValid()); + } + + public static IEnumerator UnloadAllScenes() + { + yield return UnloadManagerScenes(); + yield return SceneTestUtilities.UnloadRemainingScenes(); + } + + void ReportSceneActivation(Scene previousScene, Scene newScene) + { + _scenesActivated++; + } + + void ReportSceneUnloaded(Scene unloadedScene) + { + _scenesUnloaded++; + } + + void ReportSceneLoaded(Scene loadedScene) + { + _scenesLoaded++; + } + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_ApiTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs index 9bee61dd..b864da34 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Threading.Tasks; using NUnit.Framework; using UnityEngine.TestTools; @@ -140,6 +141,22 @@ public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTes yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); } + [UnityTest] + public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + Task loadTask = Task.FromResult(default); + yield return Unload_Template(manager, () => + { + loadTask = manager.LoadAsync(SceneBuilder.SceneNames, 0); + return loadTask; + }, () => + { + SceneResult result = loadTask.GetAwaiter().GetResult(); + return manager.UnloadAsync(result.GetScenes()); + }, SceneBuilder.SceneNames.Length); + } + + #if ENABLE_ADDRESSABLES [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 20a6825c..0614e568 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -49,6 +49,7 @@ PlayerSettings: m_StereoRenderingPath: 0 m_ActiveColorSpace: 0 unsupportedMSAAFallback: 0 + m_SpriteBatchMaxVertexCount: 65535 m_SpriteBatchVertexThreshold: 300 m_MTRendering: 1 mipStripping: 0 @@ -77,12 +78,11 @@ PlayerSettings: androidMinimumWindowHeight: 300 androidFullscreenMode: 1 androidAutoRotationBehavior: 1 - androidApplicationEntry: 1 androidPredictiveBackSupport: 0 + androidApplicationEntry: 1 defaultIsNativeResolution: 1 macRetinaSupport: 1 runInBackground: 1 - captureSingleScreen: 0 muteOtherAudioSources: 0 Prepare IOS For Recording: 0 Force IOS Speakers When Recording: 0 @@ -392,6 +392,7 @@ PlayerSettings: playModeTestRunnerEnabled: 0 runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 + editorGfxJobOverride: 1 enableInternalProfiler: 0 logObjCUncaughtExceptions: 1 enableCrashReportAPI: 0 @@ -763,3 +764,5 @@ PlayerSettings: platformRequiresReadableAssets: 0 virtualTexturingSupportEnabled: 0 insecureHttpOption: 0 + androidVulkanDenyFilterList: [] + androidVulkanAllowFilterList: [] From fd05ac64a32f95cb107b92efb4dcc68ce7374e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Thu, 30 Jan 2025 20:35:18 -0300 Subject: [PATCH 20/53] fix player tests --- .../Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs | 6 +++--- .../Tests/Runtime/SceneManagerTests.cs | 4 ++++ .../Tests/Runtime/SceneManager_ExtensionTests.cs | 7 +++---- .../Tests/Runtime/Utilities/SceneTestEnvironment.cs | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs index 7b3e5ff5..0bf0d8d4 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs @@ -10,7 +10,7 @@ namespace MyGameDevTools.SceneLoading.Api.Tests { public partial class SceneManager_Api_Tests { - int[] _buildIndexes = new[] { 0, 1, 2, 3 }; + int[] _buildIndexes = new[] { 1, 2, 3 }; AssetReference[] _assetReferences; @@ -87,13 +87,13 @@ public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple() [UnityTest] public IEnumerator Transition_Extension_ByIndex() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(1, 0), 1, 0); + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(1, 1), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByIndex_Multiple() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(_buildIndexes, 0), _buildIndexes.Length, 0); + yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); } [UnityTest] diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index e823d4d3..f6ace0e5 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -330,7 +330,11 @@ public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnviro yield return new WaitTask(task); +#if UNITY_EDITOR task = manager.UnloadAsync(1); +#else + task = manager.UnloadAsync(2); +#endif yield return new WaitTask(task); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs index b864da34..0f578e82 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs @@ -7,7 +7,7 @@ namespace MyGameDevTools.SceneLoading.Tests { public partial class SceneManagerTests { - int[] _buildIndexes = new[] { 0, 1, 2, 3 }; + readonly int[] _buildIndexes = new[] { 1, 2, 3 }; [UnityTest] public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) @@ -70,13 +70,13 @@ public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSo [UnityTest] public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(1, 0), 1, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(1, 1), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 0), _buildIndexes.Length, 0); + yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); } [UnityTest] @@ -156,7 +156,6 @@ public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTe }, SceneBuilder.SceneNames.Length); } - #if ENABLE_ADDRESSABLES [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index bea5baaa..068fcb88 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -64,7 +64,6 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup { new LoadSceneInfoName(SceneBuilder.SceneNames[1]), new LoadSceneInfoName(SceneBuilder.ScenePaths[1]), - new LoadSceneInfoIndex(1), }; public static readonly SceneParameters[] SceneParametersList = new SceneParameters[] From 45a11e1584dc50b04411b8a28448bfeabaddf67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 25 Feb 2025 16:21:56 -0300 Subject: [PATCH 21/53] improve wait task transformation --- .../Runtime/Utilities/TaskExtensions.cs | 5 +++ .../Runtime/API/SceneManager_Api_Tests.cs | 12 +++--- .../Tests/Runtime/SceneManagerTests.cs | 42 +++++++++---------- .../Runtime/SceneManager_CancellationTests.cs | 4 +- .../Runtime/SceneManager_DisposeTests.cs | 4 +- 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs index 8cd7d65d..4973aefd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/TaskExtensions.cs @@ -16,5 +16,10 @@ public static async Task RunAndDisposeToken(this Task valueTask, Cancel tokenSource.Dispose(); } } + + public static WaitTask ToWaitTask(this Task task) + { + return new WaitTask(task); + } } } \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs index fb074cfd..90486890 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs @@ -100,7 +100,7 @@ public IEnumerator Load_Template(Func> loadTask, SimpleProgres Assert.AreEqual(0, progress.Value); - yield return new WaitTask(task); + yield return task.ToWaitTask(); AdvancedSceneManager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; @@ -123,7 +123,7 @@ public IEnumerator Transition_Template(Func> transitionTask, i yield return LoadFirstScene(); var task = transitionTask(); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); @@ -135,14 +135,14 @@ public IEnumerator Transition_Template(Func> transitionTask, i public IEnumerator Unload_Template(Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); - yield return new WaitTask(load); + yield return load.ToWaitTask(); var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); var reportedScenes = new List(sceneCount); AdvancedSceneManager.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); - yield return new WaitTask(unload); + yield return unload.ToWaitTask(); AdvancedSceneManager.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; @@ -173,7 +173,7 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene() => new(AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); + public static WaitTask LoadFirstScene() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); public static IEnumerator UnloadManagerScenes() { @@ -181,7 +181,7 @@ public static IEnumerator UnloadManagerScenes() // The AdvancedSceneManager registers the init scene as one of its managed scenes while (AdvancedSceneManager.LoadedSceneCount > 1 && lastScene.IsValid()) { - yield return new WaitTask(AdvancedSceneManager.UnloadAsync(lastScene)); + yield return AdvancedSceneManager.UnloadAsync(lastScene).ToWaitTask(); lastScene = AdvancedSceneManager.GetLastLoadedScene(); } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index f6ace0e5..041ed682 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -95,7 +95,7 @@ public IEnumerator InitializationScene_Unload() ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); WaitTask waitTask = default; - Assert.DoesNotThrow(() => waitTask = new(sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))))); + Assert.DoesNotThrow(() => waitTask = sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).ToWaitTask()); yield return waitTask; } @@ -131,7 +131,7 @@ public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment { var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); - yield return new WaitTask(loadTask); + yield return loadTask.ToWaitTask(); Scene loadedScene = loadTask.Result; var managerActiveScene = manager.GetActiveScene(); @@ -150,7 +150,7 @@ public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironmen [UnityTest] public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return new WaitTask(manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1])))); + yield return manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } @@ -181,7 +181,7 @@ public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), name { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return new WaitTask(manager.LoadAsync(sceneParameters, progress)); + yield return manager.LoadAsync(sceneParameters, progress).ToWaitTask(); Assert.AreEqual(1, progress.Value); } @@ -197,7 +197,7 @@ public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof for (int i = 0; i < length; i++) { var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); - yield return new WaitTask(loadTask); + yield return loadTask.ToWaitTask(); loadedScenes[i] = loadTask.Result; } @@ -219,7 +219,7 @@ public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(Sc var sceneName = "not-a-real-scene"; if (manager is SceneManager || manager is AdvancedSceneManager) LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = new WaitTask(manager.LoadAsync(sceneName)); + var wait = manager.LoadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } @@ -235,7 +235,7 @@ public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(S var sceneName = "not-a-real-scene"; if (manager is not AdvancedSceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = new WaitTask(manager.UnloadAsync(sceneName)); + var wait = manager.UnloadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } @@ -261,7 +261,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Scene loadedScene = task.Result; @@ -284,13 +284,13 @@ public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviro { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Scene scene = task.Result; task = manager.UnloadAsync(scene); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Assert.Zero(manager.LoadedSceneCount); } @@ -300,11 +300,11 @@ public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnviron { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitTask(task); + yield return task.ToWaitTask(); task = manager.UnloadAsync(SceneBuilder.SceneNames[1]); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Assert.Zero(manager.LoadedSceneCount); } @@ -314,11 +314,11 @@ public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnviron { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitTask(task); + yield return task.ToWaitTask(); task = manager.UnloadAsync(SceneBuilder.ScenePaths[1]); - yield return new WaitTask(task); + yield return task.ToWaitTask(); Assert.Zero(manager.LoadedSceneCount); } @@ -328,7 +328,7 @@ public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnviro { var task = manager.LoadAsync(new SceneParameters(sceneInfo)); - yield return new WaitTask(task); + yield return task.ToWaitTask(); #if UNITY_EDITOR task = manager.UnloadAsync(1); @@ -336,7 +336,7 @@ public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnviro task = manager.UnloadAsync(2); #endif - yield return new WaitTask(task); + yield return task.ToWaitTask(); Assert.Zero(manager.LoadedSceneCount); } @@ -350,7 +350,7 @@ public IEnumerator Load_Template(ISceneManager manager, Func> Assert.AreEqual(0, progress.Value); - yield return new WaitTask(task); + yield return task.ToWaitTask(); manager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; @@ -373,7 +373,7 @@ public IEnumerator Transition_Template(ISceneManager manager, Func(task); + yield return task.ToWaitTask(); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); @@ -385,14 +385,14 @@ public IEnumerator Transition_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); - yield return new WaitTask(load); + yield return load.ToWaitTask(); var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); var reportedScenes = new List(sceneCount); manager.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); - yield return new WaitTask(unload); + yield return unload.ToWaitTask(); manager.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; @@ -423,7 +423,7 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene(ISceneManager sceneManager) => new(sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true)); + public static WaitTask LoadFirstScene(ISceneManager sceneManager) => sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); void ReportSceneActivation(Scene previousScene, Scene newScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index 84ce286b..1277f0fd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -11,7 +11,7 @@ public class SceneManager_CancellationTests : SceneTestBase public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters, token: tokenSource.Token)); + WaitTask waitTask = manager.LoadAsync(sceneParameters, token: tokenSource.Token).ToWaitTask(); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -22,7 +22,7 @@ public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironm public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); yield return waitTask; waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token)); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index 94bff706..02d8b242 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -25,7 +25,7 @@ public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func< public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); manager.Dispose(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -35,7 +35,7 @@ public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFun public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = new(manager.LoadAsync(sceneParameters)); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); yield return waitTask; waitTask = new(manager.UnloadAsync(sceneParameters)); From afb5ed2002ae96940f21521fe8c7018f611623a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 25 Feb 2025 17:14:25 -0300 Subject: [PATCH 22/53] fix: remove name collision and additional assembly --- .github/workflows/test.yml | 2 +- .../Runtime/API.meta | 8 - .../Runtime/API/AdvancedSceneManager.cs | 665 -------------- .../Runtime/API/AdvancedSceneManager.cs.meta | 2 - .../MyGameDevTools.SceneLoading.Api.asmdef | 25 - ...yGameDevTools.SceneLoading.Api.asmdef.meta | 7 - .../Runtime/AdvancedSceneManager.cs | 866 ++++++++++++------ .../Runtime/AdvancedSceneManager.cs.meta | 2 +- .../Runtime/Interfaces/ISceneData.cs | 4 +- .../Runtime/Interfaces/ISceneManager.cs | 16 +- .../Runtime/SceneDirector.cs | 311 +++++++ .../Runtime/SceneDirector.cs.meta | 2 + .../Utilities/SceneManagerExtensions.cs | 122 +-- .../Tests/Runtime/API.meta | 8 - ...GameDevTools.SceneLoading.Api.Tests.asmdef | 31 - ...evTools.SceneLoading.Api.Tests.asmdef.meta | 7 - ...=> AdvancedSceneManager_ExtensionTests.cs} | 5 +- ...vancedSceneManager_ExtensionTests.cs.meta} | 0 ...Tests.cs => AdvancedSceneManager_Tests.cs} | 10 +- ...eta => AdvancedSceneManager_Tests.cs.meta} | 0 ...eManagerTests.cs => SceneDirectorTests.cs} | 189 ++-- ...sts.cs.meta => SceneDirectorTests.cs.meta} | 0 ...s => SceneDirector_AssetReferenceTests.cs} | 10 +- ...SceneDirector_AssetReferenceTests.cs.meta} | 0 ....cs => SceneDirector_CancellationTests.cs} | 12 +- ...> SceneDirector_CancellationTests.cs.meta} | 0 .../Runtime/SceneDirector_DisposeTests.cs | 72 ++ ...eta => SceneDirector_DisposeTests.cs.meta} | 0 .../Runtime/SceneDirector_ExtensionTests.cs | 185 ++++ ...a => SceneDirector_ExtensionTests.cs.meta} | 0 .../Runtime/SceneManager_DisposeTests.cs | 72 -- .../Runtime/SceneManager_ExtensionTests.cs | 185 ---- .../Runtime/Utilities/SceneTestEnvironment.cs | 4 +- .../Runtime/Utilities/SceneTestUtilities.cs | 20 +- .../Settings.json | 2 +- 35 files changed, 1377 insertions(+), 1467 deletions(-) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef delete mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{API/SceneManager_Api_Extensions_Tests.cs => AdvancedSceneManager_ExtensionTests.cs} (98%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{API/SceneManager_Api_Extensions_Tests.cs.meta => AdvancedSceneManager_ExtensionTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{API/SceneManager_Api_Tests.cs => AdvancedSceneManager_Tests.cs} (96%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{API/SceneManager_Api_Tests.cs.meta => AdvancedSceneManager_Tests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManagerTests.cs => SceneDirectorTests.cs} (54%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManagerTests.cs.meta => SceneDirectorTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_AssetReferenceTests.cs => SceneDirector_AssetReferenceTests.cs} (77%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_AssetReferenceTests.cs.meta => SceneDirector_AssetReferenceTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_CancellationTests.cs => SceneDirector_CancellationTests.cs} (53%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_CancellationTests.cs.meta => SceneDirector_CancellationTests.cs.meta} (100%) create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_DisposeTests.cs.meta => SceneDirector_DisposeTests.cs.meta} (100%) create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneManager_ExtensionTests.cs.meta => SceneDirector_ExtensionTests.cs.meta} (100%) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c10bbd4f..c0520ec5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: artifactsPath: ${{ matrix.testMode }}-artifacts githubToken: ${{ secrets.GITHUB_TOKEN }} checkName: ${{ matrix.testMode }} Test Results - coverageOptions: 'generateAdditionalMetrics;assemblyFilters:+MyGameDevTools.SceneLoading,+MyGameDevTools.SceneLoading.API' + coverageOptions: 'generateAdditionalMetrics;assemblyFilters:+MyGameDevTools.SceneLoading' - name: Upload Coverage to Codecov uses: codecov/codecov-action@v4 with: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta deleted file mode 100644 index ae728fa5..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 1c640f50bc329674bb4054ee052adc44 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs deleted file mode 100644 index ffe3292f..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs +++ /dev/null @@ -1,665 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; -#if ENABLE_ADDRESSABLES -using UnityEngine.AddressableAssets; -#endif -using UnityEngine.SceneManagement; - -namespace MyGameDevTools.SceneLoading.Api -{ - public static class AdvancedSceneManager - { - internal static ISceneManager Instance - { - get - { - if (_instance == null) - throw new NullReferenceException("[AdvancedSceneManager] The static scene manager instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); - return _instance; - } - } - - static ISceneManager _instance; - - [RuntimeInitializeOnLoadMethod] - internal static void Initialize() - { - _instance = new SceneLoading.AdvancedSceneManager(true); - } - - #region ISceneManager - /// - /// Reports that the active scene has changed, passing the previous and current active scene as parameters. - ///
- /// In some scenarios, the previous or the current scene might be invalid (you can check it through ), but never both at the same time. - ///
- /// This can occur when the first active scene is being set (there was no previous active scene) or when the last scene gets unloaded (leaving no other scene to be activated). - ///
- public static event Action ActiveSceneChanged - { - add => Instance.ActiveSceneChanged += value; - remove => Instance.ActiveSceneChanged -= value; - } - /// - /// Reports when a scene gets unloaded. - /// - public static event Action SceneUnloaded - { - add => Instance.SceneUnloaded += value; - remove => Instance.SceneUnloaded -= value; - } - /// - /// Reports when a scene gets loaded. - /// - public static event Action SceneLoaded - { - add => Instance.SceneLoaded += value; - remove => Instance.SceneLoaded -= value; - } - - /// - /// The amount of scenes loaded. - /// - public static int LoadedSceneCount => Instance.LoadedSceneCount; - /// - /// The amount of scenes managed by the internal . - /// This includes scenes that are being unloaded. - /// - public static int TotalSceneCount => Instance.TotalSceneCount; - - /// - /// Sets the target as the active scene. - /// Internally calls . - /// - /// Scene to be enabled as the active scene. - public static void SetActiveScene(Scene scene) => Instance.SetActiveScene(scene); - - /// - /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () - /// to the target scene or a group of scenes via a struct, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// A struct that may hold one or more scenes and the target active index. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default) => Instance.TransitionAsync(sceneParameters, intermediateSceneReference, token); - - /// - /// Loads the target scene or group of scenes provided via a struct. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// A struct that may hold one or more scenes and the target active index. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneParameters, progress, token); - - /// - /// Unloads the target scene or group of scenes provided via a struct. - /// - /// - /// A struct that may hold one or more scenes. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) => Instance.UnloadAsync(sceneParameters, token); - - /// - /// Gets the current active scene. - /// This should point to the same scene you get via . - /// - /// The current active scene, or an invalid scene if none of the loaded scenes are enabled as the active scene. - public static Scene GetActiveScene() => Instance.GetActiveScene(); - - /// - /// Gets the loaded scene at the of the loaded scenes list. - /// - /// Index of the target scene in the loaded scenes list. - /// The loaded scene at the of the loaded scenes list. - public static Scene GetLoadedSceneAt(int index) => Instance.GetLoadedSceneAt(index); - - /// - /// Gets the last loaded scene of this . - /// - /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . - public static Scene GetLastLoadedScene() => Instance.GetLastLoadedScene(); - - /// - /// Gets a loaded scene by its . - /// - /// Name of the loaded scene to be found. - /// A loaded scene with the given . - public static Scene GetLoadedSceneByName(string name) => Instance.GetLoadedSceneByName(name); - #endregion - - #region Extensions - /// - /// Loads the target scenes. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scenes' names. - /// - /// - /// The index of the scene to be set active, or -1 if none. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAsync(string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneNames, setIndexActive, progress, token); - - /// - /// Loads the target scenes. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scenes' build indexes. - /// - /// - /// The index of the scene to be set active, or -1 if none. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAsync(int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndices, setIndexActive, progress, token); - - /// - /// Loads the target scene. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scene's name. - /// - /// - /// If the scene should be activated after load. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAsync(string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneName, setActive, progress, token); - - /// - /// Loads the target scene. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scene's build index. - /// - /// - /// If the scene should be activated after load. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAsync(int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndex, setActive, progress, token); - -#if ENABLE_ADDRESSABLES - /// - /// Loads the target scenes. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scenes' . - /// - /// - /// The index of the scene to be set active, or -1 if none. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReferences, setIndexActive, progress, token); - - /// - /// Loads the target scenes. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scenes' addressable address. - /// - /// - /// The index of the scene to be set active, or -1 if none. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(addresses, setIndexActive, progress, token); - - /// - /// Loads the target scene. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scene's . - /// - /// - /// If the scene should be activated after load. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReference, setActive, progress, token); - - /// - /// Loads the target scene. - /// You may also provide the desired index to set as the active scene. - /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. - /// - /// - /// The target scene's addressable address. - /// - /// - /// If the scene should be activated after load. - /// - /// - /// Object to report the loading operations progress to, from 0 to 1. - /// - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(address, setActive, progress, token); -#endif - - /// - /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () - /// to a group of scenes, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// An array of scenes by their names to transition to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetSceneNames, loadingSceneName, setIndexActive, token); - - /// - /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () - /// to a group of scenes, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// An array of scenes by their build index to transition to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndices, loadingBuildIndex, setIndexActive, token); - - /// - /// Triggers a transition to the target scene. - /// It will transition from the current active scene () - /// to the target scene, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// The target scene name to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(string targetSceneName, string loadingSceneName = null, CancellationToken token = default) => Instance.TransitionAsync(targetSceneName, loadingSceneName, token); - - /// - /// Triggers a transition to the target scene. - /// It will transition from the current active scene () - /// to the target scene, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// The target scene build index to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If -1, the transition will not have an intermediate loading scene. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndex, loadingBuildIndex, token); - -#if ENABLE_ADDRESSABLES - /// - /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () - /// to a group of scenes, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// An array of scenes by their to transition to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReferences, loadingAssetReference, setIndexActive, token); - - /// - /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () - /// to a group of scenes, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// An array of scenes by their addressable addresses to transition to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// - /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddresses, loadingAddress, setIndexActive, token); - - /// - /// Triggers a transition to the target scene. - /// It will transition from the current active scene () - /// to the target scene, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// The target scene to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReference, loadingAssetReference, token); - - /// - /// Triggers a transition to the target scene. - /// It will transition from the current active scene () - /// to the target scene, with an optional . - /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. - /// The complete transition flow is: - ///

- /// 1. Load the intermediate scene (if provided).
- /// 2. Unload the source scene (if any).
- /// 3. Load all target scenes.
- /// 4. Unload the intermediate scene (if provided).
- ///
- /// - /// The target scene addressable address to be transitioned to. - /// - /// - /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). - /// If null, the transition will not have an intermediate loading scene. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(string targetAddress, string loadingAddress = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddress, loadingAddress, token); -#endif - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// An array of scenes by their names to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(string[] sceneNames, CancellationToken token = default) => Instance.UnloadAsync(sceneNames, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// An array of scenes by their build index to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(int[] buildIndices, CancellationToken token = default) => Instance.UnloadAsync(buildIndices, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// An array of scenes to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(Scene[] scenes, CancellationToken token = default) => Instance.UnloadAsync(scenes, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// The target scene's name to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(string sceneName, CancellationToken token = default) => Instance.UnloadAsync(sceneName, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// The target scene's build index to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(int buildIndex, CancellationToken token = default) => Instance.UnloadAsync(buildIndex, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// The target scene to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAsync(Scene scene, CancellationToken token = default) => Instance.UnloadAsync(scene, token); - -#if ENABLE_ADDRESSABLES - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// An array of scenes to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAddressableAsync(AssetReference[] assetReferences, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReferences, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// An array of scenes to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAddressableAsync(string[] addresses, CancellationToken token = default) => Instance.UnloadAddressableAsync(addresses, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// The target scene's to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAddressableAsync(AssetReference assetReference, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReference, token); - - /// - /// Unloads the target scene or group of scenes. - /// - /// - /// The target scene's addressable address to be unloaded. - /// - /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// - /// A with all the unloaded scenes. - ///
- /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. - ///
- public static Task UnloadAddressableAsync(string address, CancellationToken token = default) => Instance.UnloadAddressableAsync(address, token); -#endif - #endregion - } -} diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta deleted file mode 100644 index 5dbe823d..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/AdvancedSceneManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: a08c7b1ee6e5566469682ddc16ef7686 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef deleted file mode 100644 index 05dca3c7..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "MyGameDevTools.SceneLoading.Api", - "rootNamespace": "MyGameDevTools.SceneLoading.Api", - "references": [ - "GUID:eee6d035ccac42b4e845b99014468585", - "GUID:9e24947de15b9834991c9d8411ea37cf" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [ - "!DISABLE_STATIC_SCENE_MANAGER" - ], - "versionDefines": [ - { - "name": "com.unity.addressables", - "expression": "1.19", - "define": "ENABLE_ADDRESSABLES" - } - ], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta deleted file mode 100644 index 4532c1be..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/API/MyGameDevTools.SceneLoading.Api.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 1f93bbe54fc0e834b9fd2f0a07956dc1 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index 5171f3b6..cbdd0167 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -1,311 +1,667 @@ +#if !DISABLE_STATIC_SCENE_MANAGER using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using UnityEngine; +#if ENABLE_ADDRESSABLES +using UnityEngine.AddressableAssets; +#endif using UnityEngine.SceneManagement; namespace MyGameDevTools.SceneLoading { - /// - /// The is capable of managing both addressable and non-addressable scene operations. - /// - public class AdvancedSceneManager : ISceneManager + public static class AdvancedSceneManager { - public event Action ActiveSceneChanged; - public event Action SceneUnloaded; - public event Action SceneLoaded; - - public int LoadedSceneCount => _loadedScenes.Count; - public int TotalSceneCount => _loadedScenes.Count + _unloadingScenes.Count; - - readonly List _unloadingScenes = new(); - readonly List _loadedScenes = new(); - readonly CancellationTokenSource _lifetimeTokenSource = new(); - - ISceneData _activeScene; - - /// - /// Creates an with no initial scene references. - /// - public AdvancedSceneManager() : this(false) { } - /// - /// Creates a new with the option to add all loaded scenes to its management. - /// The advantage is that you can manage those scenes through this instead of having to - /// use the Unity . - /// - public AdvancedSceneManager(bool addLoadedScenes) + internal static ISceneDirector Instance { - if (!addLoadedScenes) + get { - return; + if (_instance == null) + throw new NullReferenceException("[AdvancedSceneManager] The static Scene Director instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); + return _instance; } + } - int loadedSceneCount = SceneManager.sceneCount; - for (int i = 0; i < loadedSceneCount; i++) - { - Scene scene = SceneManager.GetSceneAt(i); - if (scene.IsValid() && scene.isLoaded) - { - _loadedScenes.Add(SceneDataBuilder.BuildFromScene(scene)); - } - } + static ISceneDirector _instance; - if (loadedSceneCount > 0 && SceneDataUtilities.TryGetSceneDataByLoadedScene(SceneManager.GetActiveScene(), _loadedScenes, out ISceneData sceneData)) - { - _activeScene = sceneData; - } - else if (loadedSceneCount == 0) - { - Debug.LogWarning("Tried to create an `AdvancedSceneManager` with all loaded scenes, but encoutered none. Did you create the scene manager on `Awake()`? If so, try moving the call to `Start()` instead."); - } - } - /// - /// Creates a new with the option to add a list of loaded scenes to its management. - /// The advantage is that you can manage those scenes through this instead of having to - /// use the Unity . - /// - public AdvancedSceneManager(Scene[] initializationScenes) + [RuntimeInitializeOnLoadMethod] + internal static void Initialize() { - if (initializationScenes == null || initializationScenes.Length == 0) - { - throw new ArgumentException($"Trying to create an {nameof(AdvancedSceneManager)} with a null or empty array of initialization scenes. If you want to create it without any scenes, use the empty constructor instead.", nameof(initializationScenes)); - } - - int loadedSceneCount = initializationScenes.Length; - for (int i = 0; i < loadedSceneCount; i++) - { - Scene scene = initializationScenes[i]; - if (scene.IsValid() && scene.isLoaded) - { - _loadedScenes.Add(SceneDataBuilder.BuildFromScene(scene)); - } - } - if (loadedSceneCount > 0) - { - _activeScene = _loadedScenes[0]; - } + _instance = new SceneDirector(true); } - public void Dispose() + #region ISceneDirector + /// + /// Reports that the active scene has changed, passing the previous and current active scene as parameters. + ///
+ /// In some scenarios, the previous or the current scene might be invalid (you can check it through ), but never both at the same time. + ///
+ /// This can occur when the first active scene is being set (there was no previous active scene) or when the last scene gets unloaded (leaving no other scene to be activated). + ///
+ public static event Action ActiveSceneChanged { - _lifetimeTokenSource.Cancel(); - _lifetimeTokenSource.Dispose(); - - _unloadingScenes.Clear(); - _loadedScenes.Clear(); + add => Instance.ActiveSceneChanged += value; + remove => Instance.ActiveSceneChanged -= value; } - - public void SetActiveScene(Scene scene) + /// + /// Reports when a scene gets unloaded. + /// + public static event Action SceneUnloaded { - ISceneData sceneData = null; - bool isTargetSceneValid = scene.IsValid(); - if (isTargetSceneValid && !SceneDataUtilities.TryGetSceneDataByLoadedScene(scene, _loadedScenes, out sceneData)) - throw new InvalidOperationException($"[{GetType().Name}] Cannot set active the scene \"{scene.name}\" that has not been loaded through this {GetType().Name}."); - - ISceneData previousScene = _activeScene; - _activeScene = sceneData; - if (isTargetSceneValid) - SceneManager.SetActiveScene(scene); - - ActiveSceneChanged?.Invoke(previousScene != null ? previousScene.SceneReference : default, scene); + add => Instance.SceneUnloaded += value; + remove => Instance.SceneUnloaded -= value; } - - public Scene GetActiveScene() => _activeScene != null ? _activeScene.SceneReference : default; - - public Scene GetLastLoadedScene() + /// + /// Reports when a scene gets loaded. + /// + public static event Action SceneLoaded { - if (LoadedSceneCount == 0) - return default; - - for (int i = LoadedSceneCount - 1; i >= 0; i--) - if (!_unloadingScenes.Contains(_loadedScenes[i]) && _loadedScenes[i].SceneReference.isLoaded) - return _loadedScenes[i].SceneReference; - - return default; + add => Instance.SceneLoaded += value; + remove => Instance.SceneLoaded -= value; } - public Scene GetLoadedSceneAt(int index) => _loadedScenes[index].SceneReference; + /// + /// The amount of scenes loaded. + /// + public static int LoadedSceneCount => Instance.LoadedSceneCount; + /// + /// The amount of scenes managed by the internal . + /// This includes scenes that are being unloaded. + /// + public static int TotalSceneCount => Instance.TotalSceneCount; - public Scene GetLoadedSceneByName(string name) - { - foreach (ISceneData sceneData in _loadedScenes) - if (sceneData.SceneReference.name == name) - return sceneData.SceneReference; - throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); - } + /// + /// Sets the target as the active scene. + /// Internally calls . + /// + /// Scene to be enabled as the active scene. + public static void SetActiveScene(Scene scene) => Instance.SetActiveScene(scene); - public Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) - { - if (!sceneParameters.ShouldSetActive()) - throw new ArgumentException($"[{GetType().Name}] You need to provide a SceneParameters object with a valid 'setIndexActive' value to perform scene transitions.", nameof(sceneParameters)); + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to the target scene or a group of scenes via a struct, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A struct that may hold one or more scenes and the target active index. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default) => Instance.TransitionAsync(sceneParameters, intermediateSceneReference, token); - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return intermediateSceneReference == null - ? TransitionDirectlyAsync(sceneParameters, linkedSource.Token).RunAndDisposeToken(linkedSource) - : TransitionWithIntermediateAsync(sceneParameters, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); - } + /// + /// Loads the target scene or group of scenes provided via a struct. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// A struct that may hold one or more scenes and the target active index. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneParameters, progress, token); - public Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) - { - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); - } + /// + /// Unloads the target scene or group of scenes provided via a struct. + /// + /// + /// A struct that may hold one or more scenes. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) => Instance.UnloadAsync(sceneParameters, token); - public Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) - { - CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); - return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token).RunAndDisposeToken(linkedSource); - } + /// + /// Gets the current active scene. + /// This should point to the same scene you get via . + /// + /// The current active scene, or an invalid scene if none of the loaded scenes are enabled as the active scene. + public static Scene GetActiveScene() => Instance.GetActiveScene(); - async Task LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) - { - ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); - int setIndexActive = sceneParameters.GetIndexToActivate(); - int scenesToLoad = sceneInfos.Length; + /// + /// Gets the loaded scene at the of the loaded scenes list. + /// + /// Index of the target scene in the loaded scenes list. + /// The loaded scene at the of the loaded scenes list. + public static Scene GetLoadedSceneAt(int index) => Instance.GetLoadedSceneAt(index); - ISceneData[] sceneDataArray = new ISceneData[scenesToLoad]; - int i; - for (i = 0; i < scenesToLoad; i++) - { - sceneDataArray[i] = SceneDataBuilder.BuildFromLoadSceneInfo(sceneInfos[i]); - sceneDataArray[i].LoadSceneAsync(); - } + /// + /// Gets the last loaded scene of this . + /// + /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . + public static Scene GetLastLoadedScene() => Instance.GetLastLoadedScene(); - await PollProgressAsync(sceneDataArray, progress, token); + /// + /// Gets a loaded scene by its . + /// + /// Name of the loaded scene to be found. + /// A loaded scene with the given . + public static Scene GetLoadedSceneByName(string name) => Instance.GetLoadedSceneByName(name); + #endregion - token.ThrowIfCancellationRequested(); + #region Extensions + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' names. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAsync(string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneNames, setIndexActive, progress, token); - SceneDataUtilities.LinkLoadedScenesWithSceneDataArray(sceneDataArray, _loadedScenes); + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' build indexes. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAsync(int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndices, setIndexActive, progress, token); - _loadedScenes.AddRange(sceneDataArray); - for (i = 0; i < scenesToLoad; i++) - { - SceneLoaded?.Invoke(sceneDataArray[i].SceneReference); - } + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's name. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAsync(string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(sceneName, setActive, progress, token); - if (setIndexActive >= 0) - SetActiveScene(sceneDataArray[setIndexActive].SceneReference); + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's build index. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAsync(int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAsync(buildIndex, setActive, progress, token); + +#if ENABLE_ADDRESSABLES + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' . + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAddressableAsync(AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReferences, setIndexActive, progress, token); - return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); - } + /// + /// Loads the target scenes. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scenes' addressable address. + /// + /// + /// The index of the scene to be set active, or -1 if none. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAddressableAsync(string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(addresses, setIndexActive, progress, token); - async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) - { - if (sceneInfos == null || sceneInfos.Length == 0) - throw new ArgumentException($"[{GetType().Name}] Provided scene group is null or empty.", nameof(sceneInfos)); + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's . + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAddressableAsync(AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(assetReference, setActive, progress, token); - int sceneCount = sceneInfos.Length; - ISceneData[] sceneDataArray = SceneDataUtilities.GetLoadedSceneDatasWithLoadSceneInfos(sceneInfos, _loadedScenes); - Task[] loadTasks = new Task[sceneCount]; + /// + /// Loads the target scene. + /// You may also provide the desired index to set as the active scene. + /// Also, you can pass an object to receive the average progress of all loading operations, from 0 to 1. + /// + /// + /// The target scene's addressable address. + /// + /// + /// If the scene should be activated after load. + /// + /// + /// Object to report the loading operations progress to, from 0 to 1. + /// + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all scenes loaded. + public static Task LoadAddressableAsync(string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) => Instance.LoadAddressableAsync(address, setActive, progress, token); +#endif - ISceneData tempSceneData; - int i; - for (i = 0; i < sceneCount; i++) - { - tempSceneData = sceneDataArray[i]; - _loadedScenes.Remove(tempSceneData); - _unloadingScenes.Add(tempSceneData); - loadTasks[i] = UnityTaskUtilities.FromAsyncOperation(sceneDataArray[i].UnloadSceneAsync(), token); - } + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their names to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAsync(string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetSceneNames, loadingSceneName, setIndexActive, token); - try - { - await Task.WhenAll(loadTasks); - } - catch (OperationCanceledException exception) - { - for (i = 0; i < sceneCount; i++) - { - _unloadingScenes.Remove(sceneDataArray[i]); - } - throw exception; - } + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their build index to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAsync(int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndices, loadingBuildIndex, setIndexActive, token); - for (i = 0; i < sceneCount; i++) - { - tempSceneData = sceneDataArray[i]; - _unloadingScenes.Remove(tempSceneData); - SceneUnloaded?.Invoke(tempSceneData.SceneReference); - if (_activeScene == tempSceneData) - SetActiveScene(GetLastLoadedScene()); - } + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene name to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAsync(string targetSceneName, string loadingSceneName = null, CancellationToken token = default) => Instance.TransitionAsync(targetSceneName, loadingSceneName, token); - return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); - } + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene build index to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If -1, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAsync(int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) => Instance.TransitionAsync(targetBuildIndex, loadingBuildIndex, token); + +#if ENABLE_ADDRESSABLES + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReferences, loadingAssetReference, setIndexActive, token); - async Task TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) - { - // If only one scene is loaded, create a temporary scene for transition. - Scene tempScene = default; - if (LoadedSceneCount <= 1) - { - tempScene = SceneManager.CreateScene("temp-transition-scene"); - } - await UnloadSourceSceneAsync(token); + /// + /// Triggers a transition to a group of scenes. + /// It will transition from the current active scene () + /// to a group of scenes, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// An array of scenes by their addressable addresses to transition to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddresses, loadingAddress, setIndexActive, token); - Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAssetReference, loadingAssetReference, token); - if (tempScene.IsValid()) - { - IAsyncSceneOperation unloadOperation = new AsyncSceneOperationStandard(SceneManager.UnloadSceneAsync(tempScene)); - await UnityTaskUtilities.FromAsyncOperation(unloadOperation, token); - } - return new SceneResult(loadedScenes); - } + /// + /// Triggers a transition to the target scene. + /// It will transition from the current active scene () + /// to the target scene, with an optional . + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload the source scene (if any).
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// The target scene addressable address to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(string targetAddress, string loadingAddress = null, CancellationToken token = default) => Instance.TransitionAddressableAsync(targetAddress, loadingAddress, token); +#endif - async Task TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) - { - Scene loadingScene = await LoadAsync(new SceneParameters(intermediateSceneInfo, false), token: token); - intermediateSceneInfo = new LoadSceneInfoScene(loadingScene); + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their names to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(string[] sceneNames, CancellationToken token = default) => Instance.UnloadAsync(sceneNames, token); - LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None).FirstOrDefault(l => l.gameObject.scene == loadingScene); - return loadingBehavior - ? await TransitionWithIntermediateLoadingAsync(sceneParameters, intermediateSceneInfo, loadingBehavior, token) - : await TransitionWithIntermediateNoLoadingAsync(sceneParameters, intermediateSceneInfo, token); - } + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes by their build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(int[] buildIndices, CancellationToken token = default) => Instance.UnloadAsync(buildIndices, token); - async Task TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) - { - LoadingProgress progress = loadingBehavior.Progress; - await progress.TransitionInTask.Task; - await UnloadSourceSceneAsync(token); + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(Scene[] scenes, CancellationToken token = default) => Instance.UnloadAsync(scenes, token); - Scene[] loadedScenes = await LoadAsync(sceneParameters, progress, token); - progress.SetLoadingCompleted(); + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's name to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(string sceneName, CancellationToken token = default) => Instance.UnloadAsync(sceneName, token); - await progress.TransitionOutTask.Task; - await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); - return new SceneResult(loadedScenes); - } + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's build index to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(int buildIndex, CancellationToken token = default) => Instance.UnloadAsync(buildIndex, token); - async Task TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) - { - await UnloadSourceSceneAsync(token); - Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); - await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); - return new SceneResult(loadedScenes); - } + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAsync(Scene scene, CancellationToken token = default) => Instance.UnloadAsync(scene, token); + +#if ENABLE_ADDRESSABLES + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAddressableAsync(AssetReference[] assetReferences, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReferences, token); - async Task PollProgressAsync(ISceneData[] sceneDataArray, IProgress progress, CancellationToken token = default) - { - bool isDone = false; - while (!isDone && !token.IsCancellationRequested) - { - await Task.Yield(); - isDone = SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray); - progress?.Report(SceneDataUtilities.GetAverageSceneLoadOperationProgress(sceneDataArray)); - } - } + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// An array of scenes to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAddressableAsync(string[] addresses, CancellationToken token = default) => Instance.UnloadAddressableAsync(addresses, token); - Task UnloadSourceSceneAsync(CancellationToken token) - { - Scene sourceScene = GetActiveScene(); - if (!sourceScene.IsValid()) - return Task.FromResult(default); + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAddressableAsync(AssetReference assetReference, CancellationToken token = default) => Instance.UnloadAddressableAsync(assetReference, token); - return UnloadAsync(new SceneParameters(new LoadSceneInfoScene(sourceScene)), token); - } + /// + /// Unloads the target scene or group of scenes. + /// + /// + /// The target scene's addressable address to be unloaded. + /// + /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. + /// + /// A with all the unloaded scenes. + ///
+ /// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. + ///
+ public static Task UnloadAddressableAsync(string address, CancellationToken token = default) => Instance.UnloadAddressableAsync(address, token); +#endif + #endregion } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta index e333db32..5dbe823d 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: 10b1f79f9a55e30499c316c5a0fac018 \ No newline at end of file +guid: a08c7b1ee6e5566469682ddc16ef7686 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs index 797c0676..1b387866 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs @@ -25,7 +25,7 @@ public interface ISceneData /// Manually updates the scene reference with a given scene. /// Useful for linking scenes that have not been loaded through addressable operations (that can directly link the loaded scene). ///
- /// Should not be called outside of an . + /// Should not be called outside of an . ///
void SetSceneReferenceManually(Scene scene); @@ -33,7 +33,7 @@ public interface ISceneData /// Updates the value based on the result. /// Cannot be used for non-addressable contexts, since they are not able to directly link the loaded scene. ///
- /// Should not be called outside of an . + /// Should not be called outside of an . ///
void UpdateSceneReference(); diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index 35225115..0a85a376 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -7,9 +7,9 @@ namespace MyGameDevTools.SceneLoading { /// /// Interface to standardize scene management operations. - /// The scene manager is responsible for scene loading operations, keeping track of its loaded scene stack and dispatching scene load events. + /// The Scene Director is responsible for scene loading operations, keeping track of its loaded scene stack and dispatching scene load events. /// - public interface ISceneManager : IDisposable + public interface ISceneDirector : IDisposable { /// /// Reports that the active scene has changed, passing the previous and current active scene as parameters. @@ -29,12 +29,12 @@ public interface ISceneManager : IDisposable event Action SceneLoaded; /// - /// The amount of scenes loaded through this . + /// The amount of scenes loaded through this . /// To get the total amount of loaded scenes, check . /// int LoadedSceneCount { get; } /// - /// The amount of scenes managed by this . + /// The amount of scenes managed by this . /// This includes scenes that are being unloaded. /// int TotalSceneCount { get; } @@ -101,8 +101,8 @@ public interface ISceneManager : IDisposable Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default); /// - /// Gets the current active scene in this instance. - /// This should point to the same scene you get via if it was loaded through this . + /// Gets the current active scene in this instance. + /// This should point to the same scene you get via if it was loaded through this . /// /// The current active scene, or an invalid scene if none of the loaded scenes are enabled as the active scene. Scene GetActiveScene(); @@ -115,9 +115,9 @@ public interface ISceneManager : IDisposable Scene GetLoadedSceneAt(int index); /// - /// Gets the last loaded scene of this . + /// Gets the last loaded scene of this . /// - /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . + /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . Scene GetLastLoadedScene(); /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs new file mode 100644 index 00000000..516d0d36 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace MyGameDevTools.SceneLoading +{ + /// + /// The is capable of managing both addressable and non-addressable scene operations. + /// + public class SceneDirector : ISceneDirector + { + public event Action ActiveSceneChanged; + public event Action SceneUnloaded; + public event Action SceneLoaded; + + public int LoadedSceneCount => _loadedScenes.Count; + public int TotalSceneCount => _loadedScenes.Count + _unloadingScenes.Count; + + readonly List _unloadingScenes = new(); + readonly List _loadedScenes = new(); + readonly CancellationTokenSource _lifetimeTokenSource = new(); + + ISceneData _activeScene; + + /// + /// Creates an with no initial scene references. + /// + public SceneDirector() : this(false) { } + /// + /// Creates a new with the option to add all loaded scenes to its management. + /// The advantage is that you can manage those scenes through this instead of having to + /// use the Unity . + /// + public SceneDirector(bool addLoadedScenes) + { + if (!addLoadedScenes) + { + return; + } + + int loadedSceneCount = SceneManager.sceneCount; + for (int i = 0; i < loadedSceneCount; i++) + { + Scene scene = SceneManager.GetSceneAt(i); + if (scene.IsValid() && scene.isLoaded) + { + _loadedScenes.Add(SceneDataBuilder.BuildFromScene(scene)); + } + } + + if (loadedSceneCount > 0 && SceneDataUtilities.TryGetSceneDataByLoadedScene(SceneManager.GetActiveScene(), _loadedScenes, out ISceneData sceneData)) + { + _activeScene = sceneData; + } + else if (loadedSceneCount == 0) + { + Debug.LogWarning("Tried to create a `SceneDirector` with all loaded scenes, but encoutered none. Did you create the Scene Director on `Awake()`? If so, try moving the call to `Start()` instead."); + } + } + /// + /// Creates a new with the option to add a list of loaded scenes to its management. + /// The advantage is that you can manage those scenes through this instead of having to + /// use the Unity . + /// + public SceneDirector(Scene[] initializationScenes) + { + if (initializationScenes == null || initializationScenes.Length == 0) + { + throw new ArgumentException($"Trying to create an {nameof(SceneDirector)} with a null or empty array of initialization scenes. If you want to create it without any scenes, use the empty constructor instead.", nameof(initializationScenes)); + } + + int loadedSceneCount = initializationScenes.Length; + for (int i = 0; i < loadedSceneCount; i++) + { + Scene scene = initializationScenes[i]; + if (scene.IsValid() && scene.isLoaded) + { + _loadedScenes.Add(SceneDataBuilder.BuildFromScene(scene)); + } + } + if (loadedSceneCount > 0) + { + _activeScene = _loadedScenes[0]; + } + } + + public void Dispose() + { + _lifetimeTokenSource.Cancel(); + _lifetimeTokenSource.Dispose(); + + _unloadingScenes.Clear(); + _loadedScenes.Clear(); + } + + public void SetActiveScene(Scene scene) + { + ISceneData sceneData = null; + bool isTargetSceneValid = scene.IsValid(); + if (isTargetSceneValid && !SceneDataUtilities.TryGetSceneDataByLoadedScene(scene, _loadedScenes, out sceneData)) + throw new InvalidOperationException($"[{GetType().Name}] Cannot set active the scene \"{scene.name}\" that has not been loaded through this {GetType().Name}."); + + ISceneData previousScene = _activeScene; + _activeScene = sceneData; + if (isTargetSceneValid) + SceneManager.SetActiveScene(scene); + + ActiveSceneChanged?.Invoke(previousScene != null ? previousScene.SceneReference : default, scene); + } + + public Scene GetActiveScene() => _activeScene != null ? _activeScene.SceneReference : default; + + public Scene GetLastLoadedScene() + { + if (LoadedSceneCount == 0) + return default; + + for (int i = LoadedSceneCount - 1; i >= 0; i--) + if (!_unloadingScenes.Contains(_loadedScenes[i]) && _loadedScenes[i].SceneReference.isLoaded) + return _loadedScenes[i].SceneReference; + + return default; + } + + public Scene GetLoadedSceneAt(int index) => _loadedScenes[index].SceneReference; + + public Scene GetLoadedSceneByName(string name) + { + foreach (ISceneData sceneData in _loadedScenes) + if (sceneData.SceneReference.name == name) + return sceneData.SceneReference; + throw new ArgumentException($"[{GetType().Name}] Could not find any loaded scene with the name '{name}'.", nameof(name)); + } + + public Task TransitionAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneReference = null, CancellationToken token = default) + { + if (!sceneParameters.ShouldSetActive()) + throw new ArgumentException($"[{GetType().Name}] You need to provide a SceneParameters object with a valid 'setIndexActive' value to perform scene transitions.", nameof(sceneParameters)); + + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); + return intermediateSceneReference == null + ? TransitionDirectlyAsync(sceneParameters, linkedSource.Token).RunAndDisposeToken(linkedSource) + : TransitionWithIntermediateAsync(sceneParameters, intermediateSceneReference, linkedSource.Token).RunAndDisposeToken(linkedSource); + } + + public Task LoadAsync(SceneParameters sceneParameters, IProgress progress = null, CancellationToken token = default) + { + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); + return LoadScenesAsync_Internal(sceneParameters, progress, linkedSource.Token).RunAndDisposeToken(linkedSource); + } + + public Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default) + { + CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(_lifetimeTokenSource.Token, token); + return UnloadScenesAsync_Internal(sceneParameters.GetLoadSceneInfos(), linkedSource.Token).RunAndDisposeToken(linkedSource); + } + + async Task LoadScenesAsync_Internal(SceneParameters sceneParameters, IProgress progress, CancellationToken token) + { + ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); + int setIndexActive = sceneParameters.GetIndexToActivate(); + int scenesToLoad = sceneInfos.Length; + + ISceneData[] sceneDataArray = new ISceneData[scenesToLoad]; + int i; + for (i = 0; i < scenesToLoad; i++) + { + sceneDataArray[i] = SceneDataBuilder.BuildFromLoadSceneInfo(sceneInfos[i]); + sceneDataArray[i].LoadSceneAsync(); + } + + await PollProgressAsync(sceneDataArray, progress, token); + + token.ThrowIfCancellationRequested(); + + SceneDataUtilities.LinkLoadedScenesWithSceneDataArray(sceneDataArray, _loadedScenes); + + _loadedScenes.AddRange(sceneDataArray); + for (i = 0; i < scenesToLoad; i++) + { + SceneLoaded?.Invoke(sceneDataArray[i].SceneReference); + } + + if (setIndexActive >= 0) + SetActiveScene(sceneDataArray[setIndexActive].SceneReference); + + return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); + } + + async Task UnloadScenesAsync_Internal(ILoadSceneInfo[] sceneInfos, CancellationToken token) + { + if (sceneInfos == null || sceneInfos.Length == 0) + throw new ArgumentException($"[{GetType().Name}] Provided scene group is null or empty.", nameof(sceneInfos)); + + int sceneCount = sceneInfos.Length; + ISceneData[] sceneDataArray = SceneDataUtilities.GetLoadedSceneDatasWithLoadSceneInfos(sceneInfos, _loadedScenes); + Task[] loadTasks = new Task[sceneCount]; + + ISceneData tempSceneData; + int i; + for (i = 0; i < sceneCount; i++) + { + tempSceneData = sceneDataArray[i]; + _loadedScenes.Remove(tempSceneData); + _unloadingScenes.Add(tempSceneData); + loadTasks[i] = UnityTaskUtilities.FromAsyncOperation(sceneDataArray[i].UnloadSceneAsync(), token); + } + + try + { + await Task.WhenAll(loadTasks); + } + catch (OperationCanceledException exception) + { + for (i = 0; i < sceneCount; i++) + { + _unloadingScenes.Remove(sceneDataArray[i]); + } + throw exception; + } + + for (i = 0; i < sceneCount; i++) + { + tempSceneData = sceneDataArray[i]; + _unloadingScenes.Remove(tempSceneData); + SceneUnloaded?.Invoke(tempSceneData.SceneReference); + if (_activeScene == tempSceneData) + SetActiveScene(GetLastLoadedScene()); + } + + return new SceneResult(SceneDataUtilities.GetScenesFromSceneDataArray(sceneDataArray)); + } + + async Task TransitionDirectlyAsync(SceneParameters sceneParameters, CancellationToken token) + { + // If only one scene is loaded, create a temporary scene for transition. + Scene tempScene = default; + if (LoadedSceneCount <= 1) + { + tempScene = SceneManager.CreateScene("temp-transition-scene"); + } + await UnloadSourceSceneAsync(token); + + Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); + + if (tempScene.IsValid()) + { + IAsyncSceneOperation unloadOperation = new AsyncSceneOperationStandard(SceneManager.UnloadSceneAsync(tempScene)); + await UnityTaskUtilities.FromAsyncOperation(unloadOperation, token); + } + return new SceneResult(loadedScenes); + } + + async Task TransitionWithIntermediateAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + { + Scene loadingScene = await LoadAsync(new SceneParameters(intermediateSceneInfo, false), token: token); + intermediateSceneInfo = new LoadSceneInfoScene(loadingScene); + + LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None).FirstOrDefault(l => l.gameObject.scene == loadingScene); + return loadingBehavior + ? await TransitionWithIntermediateLoadingAsync(sceneParameters, intermediateSceneInfo, loadingBehavior, token) + : await TransitionWithIntermediateNoLoadingAsync(sceneParameters, intermediateSceneInfo, token); + } + + async Task TransitionWithIntermediateLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + { + LoadingProgress progress = loadingBehavior.Progress; + await progress.TransitionInTask.Task; + await UnloadSourceSceneAsync(token); + + Scene[] loadedScenes = await LoadAsync(sceneParameters, progress, token); + progress.SetLoadingCompleted(); + + await progress.TransitionOutTask.Task; + await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); + return new SceneResult(loadedScenes); + } + + async Task TransitionWithIntermediateNoLoadingAsync(SceneParameters sceneParameters, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + { + await UnloadSourceSceneAsync(token); + Scene[] loadedScenes = await LoadAsync(sceneParameters, token: token); + await UnloadAsync(new SceneParameters(intermediateSceneInfo), token); + return new SceneResult(loadedScenes); + } + + async Task PollProgressAsync(ISceneData[] sceneDataArray, IProgress progress, CancellationToken token = default) + { + bool isDone = false; + while (!isDone && !token.IsCancellationRequested) + { + await Task.Yield(); + isDone = SceneDataUtilities.HasCompletedAllSceneLoadOperations(sceneDataArray); + progress?.Report(SceneDataUtilities.GetAverageSceneLoadOperationProgress(sceneDataArray)); + } + } + + Task UnloadSourceSceneAsync(CancellationToken token) + { + Scene sourceScene = GetActiveScene(); + if (!sourceScene.IsValid()) + return Task.FromResult(default); + + return UnloadAsync(new SceneParameters(new LoadSceneInfoScene(sourceScene)), token); + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta new file mode 100644 index 00000000..e333db32 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 10b1f79f9a55e30499c316c5a0fac018 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs index a9893a34..bb7f91f7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -9,7 +9,7 @@ namespace MyGameDevTools.SceneLoading { - public static class SceneManagerExtensions + public static class SceneDirectorExtensions { /// /// Loads the target scenes. @@ -29,11 +29,11 @@ public static class SceneManagerExtensions /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAsync(this ISceneManager sceneManager, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public static Task LoadAsync(this ISceneDirector sceneDirector, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -54,11 +54,11 @@ public static Task LoadAsync(this ISceneManager sceneManager, strin /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAsync(this ISceneManager sceneManager, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public static Task LoadAsync(this ISceneDirector sceneDirector, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -79,10 +79,10 @@ public static Task LoadAsync(this ISceneManager sceneManager, int[] /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAsync(this ISceneManager sceneManager, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) + public static Task LoadAsync(this ISceneDirector sceneDirector, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName), setActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -103,10 +103,10 @@ public static Task LoadAsync(this ISceneManager sceneManager, strin /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAsync(this ISceneManager sceneManager, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) + public static Task LoadAsync(this ISceneDirector sceneDirector, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex), setActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } #if ENABLE_ADDRESSABLES @@ -128,11 +128,11 @@ public static Task LoadAsync(this ISceneManager sceneManager, int b /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -153,11 +153,11 @@ public static Task LoadAddressableAsync(this ISceneManager sceneMan /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneManager sceneManager, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -178,10 +178,10 @@ public static Task LoadAddressableAsync(this ISceneManager sceneMan /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) + public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference), setActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } /// @@ -202,16 +202,16 @@ public static Task LoadAddressableAsync(this ISceneManager sceneMan /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneManager sceneManager, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) + public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address), setActive); - return sceneManager.LoadAsync(sceneParams, progress, token); + return sceneDirector.LoadAsync(sceneParams, progress, token); } #endif /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -233,16 +233,16 @@ public static Task LoadAddressableAsync(this ISceneManager sceneMan /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) + public static Task TransitionAsync(this ISceneDirector sceneDirector, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetSceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -264,16 +264,16 @@ public static Task TransitionAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) + public static Task TransitionAsync(this ISceneDirector sceneDirector, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetBuildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -292,16 +292,16 @@ public static Task TransitionAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneManager sceneManager, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) + public static Task TransitionAsync(this ISceneDirector sceneDirector, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -320,17 +320,17 @@ public static Task TransitionAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) + public static Task TransitionAsync(this ISceneDirector sceneDirector, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), true); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } #if ENABLE_ADDRESSABLES /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -352,16 +352,16 @@ public static Task TransitionAsync(this ISceneManager sceneManager, /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) + public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAssetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -383,16 +383,16 @@ public static Task TransitionAddressableAsync(this ISceneManager sc /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) + public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAddresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -411,16 +411,16 @@ public static Task TransitionAddressableAsync(this ISceneManager sc /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) + public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), true); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -439,11 +439,11 @@ public static Task TransitionAddressableAsync(this ISceneManager sc /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, string loadingAddress = null, CancellationToken token = default) + public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, string targetAddress, string loadingAddress = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); - return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); } #endif @@ -459,11 +459,11 @@ public static Task TransitionAddressableAsync(this ISceneManager sc ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, string[] sceneNames, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -478,11 +478,11 @@ public static Task UnloadAsync(this ISceneManager sceneManager, str ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, int[] buildIndices, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -497,11 +497,11 @@ public static Task UnloadAsync(this ISceneManager sceneManager, int ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, Scene[] scenes, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -516,10 +516,10 @@ public static Task UnloadAsync(this ISceneManager sceneManager, Sce ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, string sceneName, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName)); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -534,10 +534,10 @@ public static Task UnloadAsync(this ISceneManager sceneManager, str ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, int buildIndex, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex)); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -552,10 +552,10 @@ public static Task UnloadAsync(this ISceneManager sceneManager, int ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) + public static Task UnloadAsync(this ISceneDirector sceneDirector, Scene scene, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoScene(scene)); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } #if ENABLE_ADDRESSABLES @@ -571,11 +571,11 @@ public static Task UnloadAsync(this ISceneManager sceneManager, Sce ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] assetReferences, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -590,11 +590,11 @@ public static Task UnloadAddressableAsync(this ISceneManager sceneM ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, string[] addresses, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -609,10 +609,10 @@ public static Task UnloadAddressableAsync(this ISceneManager sceneM ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, AssetReference assetReference, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference)); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } /// @@ -627,10 +627,10 @@ public static Task UnloadAddressableAsync(this ISceneManager sceneM ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. /// - public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, string address, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address)); - return sceneManager.UnloadAsync(sceneParams, token); + return sceneDirector.UnloadAsync(sceneParams, token); } #endif } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta deleted file mode 100644 index 18df0987..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 25e02e29935b3c54b890d974a4a8425f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef deleted file mode 100644 index 41cd6073..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "MyGameDevTools.SceneLoading.Api.Tests", - "rootNamespace": "MyGameDevTools.SceneLoading.Api.Tests", - "references": [ - "GUID:eee6d035ccac42b4e845b99014468585", - "GUID:1f93bbe54fc0e834b9fd2f0a07956dc1", - "GUID:0b51ebc09bbfe624d8c5427c1e3c295d", - "GUID:27619889b8ba8c24980f49ee34dbb44a", - "GUID:9e24947de15b9834991c9d8411ea37cf", - "GUID:84651a3751eca9349aac36a66bba901b" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": true, - "precompiledReferences": [ - "nunit.framework.dll" - ], - "autoReferenced": true, - "defineConstraints": [ - "UNITY_INCLUDE_TESTS" - ], - "versionDefines": [ - { - "name": "com.unity.addressables", - "expression": "1.19", - "define": "ENABLE_ADDRESSABLES" - } - ], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta deleted file mode 100644 index 291cac7a..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/MyGameDevTools.SceneLoading.Api.Tests.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 5c68751d3ac318941ad3501cd94032e1 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs similarity index 98% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs index 0bf0d8d4..6c1c63c4 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs @@ -1,14 +1,13 @@ using System.Collections; using System.Threading.Tasks; -using MyGameDevTools.SceneLoading.Tests; using NUnit.Framework; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.TestTools; -namespace MyGameDevTools.SceneLoading.Api.Tests +namespace MyGameDevTools.SceneLoading.Tests { - public partial class SceneManager_Api_Tests + public partial class AdvancedSceneManager_Tests { int[] _buildIndexes = new[] { 1, 2, 3 }; diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Extensions_Tests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs similarity index 96% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs index 90486890..2d86bc34 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs @@ -3,24 +3,20 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using MyGameDevTools.SceneLoading.Tests; using NUnit.Framework; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TestTools; -namespace MyGameDevTools.SceneLoading.Api.Tests +namespace MyGameDevTools.SceneLoading.Tests { - public partial class SceneManager_Api_Tests : IPrebuildSetup, IPostBuildCleanup + [PrebuildSetup(typeof(SceneTestEnvironment)), PostBuildCleanup(typeof(SceneTestEnvironment))] + public partial class AdvancedSceneManager_Tests { int _scenesActivated; int _scenesUnloaded; int _scenesLoaded; - public void Setup() => new SceneTestEnvironment().Setup(); - - public void Cleanup() => new SceneTestEnvironment().Cleanup(); - [OneTimeSetUp] public void OneTimeSetup() { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/API/SceneManager_Api_Tests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs similarity index 54% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs index 041ed682..3c5df2e0 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs @@ -11,7 +11,7 @@ namespace MyGameDevTools.SceneLoading.Tests { - public partial class SceneManagerTests : SceneTestBase + public partial class SceneDirectorTests : SceneTestBase { public static readonly ILoadSceneInfo[] LoadingSceneInfos = new ILoadSceneInfo[] { @@ -32,26 +32,26 @@ public void OneTimeSetup() { SceneTestEnvironment.ValidateSceneEnvironment(); - ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; - for (int i = 0; i < sceneManagers.Length; i++) + ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; + for (int i = 0; i < sceneDirectors.Length; i++) { - var manager = sceneManagers[i]; - manager.ActiveSceneChanged += ReportSceneActivation; - manager.SceneUnloaded += ReportSceneUnloaded; - manager.SceneLoaded += ReportSceneLoaded; + var director = sceneDirectors[i]; + director.ActiveSceneChanged += ReportSceneActivation; + director.SceneUnloaded += ReportSceneUnloaded; + director.SceneLoaded += ReportSceneLoaded; } } [OneTimeTearDown] public void OneTimeTeardown() { - ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; - for (int i = 0; i < sceneManagers.Length; i++) + ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; + for (int i = 0; i < sceneDirectors.Length; i++) { - var manager = sceneManagers[i]; - manager.ActiveSceneChanged -= ReportSceneActivation; - manager.SceneUnloaded -= ReportSceneUnloaded; - manager.SceneLoaded -= ReportSceneLoaded; + var director = sceneDirectors[i]; + director.ActiveSceneChanged -= ReportSceneActivation; + director.SceneUnloaded -= ReportSceneUnloaded; + director.SceneLoaded -= ReportSceneLoaded; } } @@ -68,10 +68,10 @@ public IEnumerator Constructor_AddLoadedScenes() { yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); - ISceneManager sceneManager = new AdvancedSceneManager(true); + ISceneDirector sceneDirector = new SceneDirector(true); - Assert.AreEqual(2, sceneManager.LoadedSceneCount); - Assert.AreEqual(sceneManager.TotalSceneCount, sceneManager.LoadedSceneCount); + Assert.AreEqual(2, sceneDirector.LoadedSceneCount); + Assert.AreEqual(sceneDirector.TotalSceneCount, sceneDirector.LoadedSceneCount); } [UnityTest] @@ -80,10 +80,10 @@ public IEnumerator Constructor_InitializationScenes() yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); Scene loadedScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); + ISceneDirector sceneDirector = new SceneDirector(new Scene[] { loadedScene }); - Assert.AreEqual(1, sceneManager.LoadedSceneCount); - Assert.AreEqual(sceneManager.TotalSceneCount, sceneManager.LoadedSceneCount); + Assert.AreEqual(1, sceneDirector.LoadedSceneCount); + Assert.AreEqual(sceneDirector.TotalSceneCount, sceneDirector.LoadedSceneCount); } [UnityTest] @@ -92,16 +92,16 @@ public IEnumerator InitializationScene_Unload() yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); Scene loadedScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - ISceneManager sceneManager = new AdvancedSceneManager(new Scene[] { loadedScene }); + ISceneDirector sceneDirector = new SceneDirector(new Scene[] { loadedScene }); WaitTask waitTask = default; - Assert.DoesNotThrow(() => waitTask = sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).ToWaitTask()); + Assert.DoesNotThrow(() => waitTask = sceneDirector.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).ToWaitTask()); yield return waitTask; } [UnityTest] - public IEnumerator SetActive_NotThroughManager([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public IEnumerator SetActive_NotThroughDirector([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { Scene loadedScene = default; SceneManager.sceneLoaded += assignLoadedScene; @@ -109,7 +109,7 @@ public IEnumerator SetActive_NotThroughManager([ValueSource(typeof(SceneTestEnvi yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); yield return new WaitUntil(() => loadedScene.IsValid()); - Assert.Throws(() => manager.SetActiveScene(loadedScene)); + Assert.Throws(() => director.SetActiveScene(loadedScene)); yield return SceneManager.UnloadSceneAsync(loadedScene); @@ -121,20 +121,20 @@ void assignLoadedScene(Scene scene, LoadSceneMode loadSceneMode) } [Test] - public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - Assert.False(manager.GetActiveScene().IsValid()); + Assert.False(director.GetActiveScene().IsValid()); } [UnityTest] - public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); + var loadTask = director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); yield return loadTask.ToWaitTask(); Scene loadedScene = loadTask.Result; - var managerActiveScene = manager.GetActiveScene(); + var managerActiveScene = director.GetActiveScene(); Assert.True(loadedScene.IsValid()); Assert.True(managerActiveScene.IsValid()); @@ -142,51 +142,51 @@ public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment } [Test] - public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - Assert.Throws(() => manager.GetLoadedSceneByName("not-a-real-scene")); + Assert.Throws(() => director.GetLoadedSceneByName("not-a-real-scene")); } [UnityTest] - public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - yield return manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); + yield return director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); - Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); + Assert.True(director.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } [Test] - public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - Assert.False(manager.GetLastLoadedScene().IsValid()); - Assert.False(manager.GetActiveScene().IsValid()); + Assert.False(director.GetLastLoadedScene().IsValid()); + Assert.False(director.GetActiveScene().IsValid()); } [Test] - public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - Assert.Throws(() => manager.GetLoadedSceneAt(-1)); - Assert.Throws(() => manager.GetLoadedSceneAt(1)); + Assert.Throws(() => director.GetLoadedSceneAt(-1)); + Assert.Throws(() => director.GetLoadedSceneAt(1)); } [UnityTest] - public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); - return Load_Template(manager, () => manager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); + return Load_Template(director, () => director.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return manager.LoadAsync(sceneParameters, progress).ToWaitTask(); + yield return director.LoadAsync(sceneParameters, progress).ToWaitTask(); Assert.AreEqual(1, progress.Value); } [UnityTest] - public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int length = sceneInfos.Length; @@ -196,58 +196,57 @@ public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof for (int i = 0; i < length; i++) { - var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); + var loadTask = director.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); yield return loadTask.ToWaitTask(); loadedScenes[i] = loadTask.Result; } - Assert.AreEqual(length, manager.LoadedSceneCount); - Assert.AreEqual(loadedScenes[^1], manager.GetLastLoadedScene()); + Assert.AreEqual(length, director.LoadedSceneCount); + Assert.AreEqual(loadedScenes[^1], director.GetLastLoadedScene()); for (int i = 0; i < length; i++) - Assert.AreEqual(loadedScenes[i], manager.GetLoadedSceneAt(i)); + Assert.AreEqual(loadedScenes[i], director.GetLoadedSceneAt(i)); - Assert.That(setActive ? loadedScenes[^1] == manager.GetActiveScene() : loadedScenes[^1] != manager.GetActiveScene()); + Assert.That(setActive ? loadedScenes[^1] == director.GetActiveScene() : loadedScenes[^1] != director.GetActiveScene()); Assert.AreEqual(length, _scenesLoaded); Assert.AreEqual(0, _scenesUnloaded); Assert.AreEqual(setActive ? length : 0, _scenesActivated); } [Test] - public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { var sceneName = "not-a-real-scene"; - if (manager is SceneManager || manager is AdvancedSceneManager) - LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = manager.LoadAsync(sceneName).ToWaitTask(); + LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); + var wait = director.LoadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } [UnityTest] - public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - yield return Unload_Template(manager, () => manager.LoadAsync(sceneParameters), () => manager.UnloadAsync(sceneParameters), sceneParameters.Length); + yield return Unload_Template(director, () => director.LoadAsync(sceneParameters), () => director.UnloadAsync(sceneParameters), sceneParameters.Length); } [Test] - public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { var sceneName = "not-a-real-scene"; - if (manager is not AdvancedSceneManager) + if (director is not SceneDirector) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = manager.UnloadAsync(sceneName).ToWaitTask(); + var wait = director.UnloadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } [UnityTest] - public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { - yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + yield return Transition_Template(director, () => director.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { int expectedLoadedScenes = loadingScene == null ? 1 : 2; // If there's no loading scene, the scene manager will create a temporary scene @@ -259,7 +258,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron // The temporary scene unload does not go through the ISceneManager SceneManager.sceneUnloaded += sceneUnloaded; - var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); + var task = director.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); yield return task.ToWaitTask(); @@ -267,11 +266,11 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron SceneManager.sceneUnloaded -= sceneUnloaded; - Assert.AreEqual(loadedScene, manager.GetActiveScene()); + Assert.AreEqual(loadedScene, director.GetActiveScene()); Assert.AreEqual(expectedLoadedScenes, _scenesLoaded); Assert.AreEqual(expectedUnloadedScenes, unloadedScenesCount); - yield return new WaitUntil(() => manager.TotalSceneCount == 1); + yield return new WaitUntil(() => director.TotalSceneCount == 1); void sceneUnloaded(Scene scene) { @@ -280,71 +279,71 @@ void sceneUnloaded(Scene scene) } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + var task = director.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); Scene scene = task.Result; - task = manager.UnloadAsync(scene); + task = director.UnloadAsync(scene); yield return task.ToWaitTask(); - Assert.Zero(manager.LoadedSceneCount); + Assert.Zero(director.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + var task = director.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); - task = manager.UnloadAsync(SceneBuilder.SceneNames[1]); + task = director.UnloadAsync(SceneBuilder.SceneNames[1]); yield return task.ToWaitTask(); - Assert.Zero(manager.LoadedSceneCount); + Assert.Zero(director.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + var task = director.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); - task = manager.UnloadAsync(SceneBuilder.ScenePaths[1]); + task = director.UnloadAsync(SceneBuilder.ScenePaths[1]); yield return task.ToWaitTask(); - Assert.Zero(manager.LoadedSceneCount); + Assert.Zero(director.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = manager.LoadAsync(new SceneParameters(sceneInfo)); + var task = director.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); #if UNITY_EDITOR - task = manager.UnloadAsync(1); + task = director.UnloadAsync(1); #else - task = manager.UnloadAsync(2); + task = director.UnloadAsync(2); #endif yield return task.ToWaitTask(); - Assert.Zero(manager.LoadedSceneCount); + Assert.Zero(director.LoadedSceneCount); } - public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + public IEnumerator Load_Template(ISceneDirector director, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); - manager.SceneLoaded += reportSceneLoaded; + director.SceneLoaded += reportSceneLoaded; var task = loadTask(); @@ -352,15 +351,15 @@ public IEnumerator Load_Template(ISceneManager manager, Func> yield return task.ToWaitTask(); - manager.SceneLoaded -= reportSceneLoaded; + director.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; Assert.AreEqual(1, progress.Value); Assert.AreEqual(sceneCount, loadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(sceneCount, manager.LoadedSceneCount); + Assert.AreEqual(sceneCount, director.LoadedSceneCount); if (setIndexActive >= 0) - Assert.AreEqual(manager.GetActiveScene(), loadedScenes[setIndexActive]); + Assert.AreEqual(director.GetActiveScene(), loadedScenes[setIndexActive]); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(0, _scenesUnloaded); Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); @@ -368,38 +367,38 @@ public IEnumerator Load_Template(ISceneManager manager, Func> void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); } - public IEnumerator Transition_Template(ISceneManager manager, Func> transitionTask, int sceneCount, int setIndexActive) + public IEnumerator Transition_Template(ISceneDirector director, Func> transitionTask, int sceneCount, int setIndexActive) { - yield return LoadFirstScene(manager); + yield return LoadFirstScene(director); var task = transitionTask(); yield return task.ToWaitTask(); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); - Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); + Assert.AreEqual(loadedScenes[setIndexActive], director.GetActiveScene()); - yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); + yield return new WaitUntil(() => director.TotalSceneCount == sceneCount); } - public IEnumerator Unload_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) + public IEnumerator Unload_Template(ISceneDirector director, Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); yield return load.ToWaitTask(); var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); var reportedScenes = new List(sceneCount); - manager.SceneUnloaded += reportSceneUnloaded; + director.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); yield return unload.ToWaitTask(); - manager.SceneUnloaded -= reportSceneUnloaded; + director.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; Assert.AreEqual(sceneCount, unloadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(0, manager.LoadedSceneCount); + Assert.AreEqual(0, director.LoadedSceneCount); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(sceneCount, _scenesUnloaded); @@ -423,7 +422,7 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene(ISceneManager sceneManager) => sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); + public static WaitTask LoadFirstScene(ISceneDirector sceneDirector) => sceneDirector.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); void ReportSceneActivation(Scene previousScene, Scene newScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs similarity index 77% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs index b6a8e458..1c21b984 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs @@ -10,7 +10,7 @@ namespace MyGameDevTools.SceneLoading.Tests // Note: AssetReference load scene infos cannot be created statically, since the // scenes are generated in IPrebuildSetup and don't have deterministic guids between // Unity Editor sessions. So, we must test AssetReference load scene infos "manually". - public partial class SceneManagerTests + public partial class SceneDirectorTests { AssetReference[] _assetReferences; ILoadSceneInfo[] _assetReferenceLoadSceneInfos; @@ -36,15 +36,15 @@ public void AssetReferenceSetup() } [UnityTest] - public IEnumerator Load_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) + public IEnumerator Load_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { - yield return Load(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); + yield return Load(director, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); } [UnityTest] - public IEnumerator Unload_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + public IEnumerator Unload_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) { - yield return Unload(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); + yield return Unload(director, new SceneParameters(_assetReferenceLoadSceneInfos)); } } } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs similarity index 53% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs index 1277f0fd..34850a2d 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs @@ -5,13 +5,13 @@ namespace MyGameDevTools.SceneLoading.Tests { - public class SceneManager_CancellationTests : SceneTestBase + public class SceneDirector_CancellationTests : SceneTestBase { [UnityTest] - public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = manager.LoadAsync(sceneParameters, token: tokenSource.Token).ToWaitTask(); + WaitTask waitTask = director.LoadAsync(sceneParameters, token: tokenSource.Token).ToWaitTask(); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -19,13 +19,13 @@ public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironm } [UnityTest] - public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); + WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); yield return waitTask; - waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token)); + waitTask = new(director.UnloadAsync(sceneParameters, token: tokenSource.Token)); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs new file mode 100644 index 00000000..7aacd746 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs @@ -0,0 +1,72 @@ +using NUnit.Framework; +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Tests +{ + public class SceneDirector_DisposeTests : SceneTestBase + { + // Note: These functions must create new Scene Directors to correctly test the dispose flow + static readonly Func[] _sceneDirectorCreateFuncs = new Func[] + { + () => new SceneDirector(), + }; + + [Test] + public void Dispose_Simple([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc) + { + ISceneDirector director = directorCreateFunc(); + Assert.DoesNotThrow(director.Dispose); + } + + [UnityTest] + public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + ISceneDirector director = directorCreateFunc(); + WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); + director.Dispose(); + yield return waitTask; + Assert.True(waitTask.Task.IsCanceled); + } + + [UnityTest] + public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + ISceneDirector director = directorCreateFunc(); + WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); + yield return waitTask; + + waitTask = new(director.UnloadAsync(sceneParameters)); + director.Dispose(); + yield return waitTask; + Assert.True(waitTask.Task.IsCanceled); + } + + [UnityTest] + public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneDirectorTests), nameof(SceneDirectorTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + async Awaitable Test() + { + ISceneDirector director = directorCreateFunc(); + await SceneDirectorTests.LoadFirstScene(director).Task; + + var task = director.TransitionAsync(sceneParameters, loadingScene); + director.Dispose(); + + bool canceled = false; + try + { + await task; + } + catch (OperationCanceledException) + { + canceled = true; + } + Assert.True(canceled); + } + return Test(); + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs new file mode 100644 index 00000000..72a443ec --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs @@ -0,0 +1,185 @@ +using System.Collections; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Tests +{ + public partial class SceneDirectorTests + { + readonly int[] _buildIndexes = new[] { 1, 2, 3 }; + + [UnityTest] + public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAsync(1, true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + var progress = new SimpleProgress(); + yield return Load_Template(director, () => director.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); + } +#endif + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAsync(1, 1), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Transition_Template(director, () => director.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); + } +#endif + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAsync(1, true), () => director.UnloadAsync(1), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAsync(_buildIndexes, 0), () => director.UnloadAsync(_buildIndexes), _buildIndexes.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames[1], true), () => director.UnloadAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames, 0), () => director.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + Task loadTask = Task.FromResult(default); + yield return Unload_Template(director, () => + { + loadTask = director.LoadAsync(SceneBuilder.SceneNames, 0); + return loadTask; + }, () => + { + SceneResult result = loadTask.GetAwaiter().GetResult(); + return director.UnloadAsync(result.GetScenes()); + }, SceneBuilder.SceneNames.Length); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => director.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => director.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAddressableAsync(_assetReferences[1], true), () => director.UnloadAddressableAsync(_assetReferences[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + { + yield return Unload_Template(director, () => director.LoadAddressableAsync(_assetReferences, 0), () => director.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); + } +#endif + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs deleted file mode 100644 index 02d8b242..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections; -using UnityEngine; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - public class SceneManager_DisposeTests : SceneTestBase - { - // Note: These functions must create new scene managers to correctly test the dispose flow - static readonly Func[] _sceneManagerCreateFuncs = new Func[] - { - () => new AdvancedSceneManager(), - }; - - [Test] - public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc) - { - ISceneManager manager = managerCreateFunc(); - Assert.DoesNotThrow(manager.Dispose); - } - - [UnityTest] - public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) - { - ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); - manager.Dispose(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - } - - [UnityTest] - public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) - { - ISceneManager manager = managerCreateFunc(); - WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); - yield return waitTask; - - waitTask = new(manager.UnloadAsync(sceneParameters)); - manager.Dispose(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - } - - [UnityTest] - public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - async Awaitable Test() - { - ISceneManager manager = managerCreateFunc(); - await SceneManagerTests.LoadFirstScene(manager).Task; - - var task = manager.TransitionAsync(sceneParameters, loadingScene); - manager.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - } - return Test(); - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs deleted file mode 100644 index 0f578e82..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System.Collections; -using System.Threading.Tasks; -using NUnit.Framework; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - public partial class SceneManagerTests - { - readonly int[] _buildIndexes = new[] { 1, 2, 3 }; - - [UnityTest] - public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAsync(1, true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); - } - - [UnityTest] - public IEnumerator Load_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - var progress = new SimpleProgress(); - yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); - } -#endif - - [UnityTest] - public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAsync(1, 1), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); - } -#endif - - [UnityTest] - public IEnumerator Unload_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAsync(1, true), () => manager.UnloadAsync(1), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAsync(_buildIndexes, 0), () => manager.UnloadAsync(_buildIndexes), _buildIndexes.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - Task loadTask = Task.FromResult(default); - yield return Unload_Template(manager, () => - { - loadTask = manager.LoadAsync(SceneBuilder.SceneNames, 0); - return loadTask; - }, () => - { - SceneResult result = loadTask.GetAwaiter().GetResult(); - return manager.UnloadAsync(result.GetScenes()); - }, SceneBuilder.SceneNames.Length); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true), () => manager.UnloadAddressableAsync(_assetReferences[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) - { - yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 0), () => manager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); - } -#endif - } -} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index 068fcb88..6066ba25 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -95,9 +95,9 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup new(_multipleLoadSceneInfoList[1], 1), }; - public static readonly ISceneManager[] SceneManagers = new ISceneManager[] + public static readonly ISceneDirector[] SceneDirectors = new ISceneDirector[] { - new AdvancedSceneManager(), + new SceneDirector(), }; #if UNITY_EDITOR diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index faff9570..00614cd3 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -6,17 +6,17 @@ namespace MyGameDevTools.SceneLoading.Tests { public static class SceneTestUtilities { - public static IEnumerator UnloadManagerScenes(ISceneManager sceneManager) + public static IEnumerator UnloadDirectorScenes(ISceneDirector sceneDirector) { - var lastScene = sceneManager.GetLastLoadedScene(); - while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) + var lastScene = sceneDirector.GetLastLoadedScene(); + while (sceneDirector.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneManager.UnloadAsync(lastScene)); - lastScene = sceneManager.GetLastLoadedScene(); + yield return new WaitTask(sceneDirector.UnloadAsync(lastScene)); + lastScene = sceneDirector.GetLastLoadedScene(); } - Assert.Zero(sceneManager.LoadedSceneCount); - Assert.False(sceneManager.GetActiveScene().IsValid()); + Assert.Zero(sceneDirector.LoadedSceneCount); + Assert.False(sceneDirector.GetActiveScene().IsValid()); } public static IEnumerator UnloadRemainingScenes() @@ -33,9 +33,9 @@ public static IEnumerator UnloadRemainingScenes() public static IEnumerator UnloadAllScenes() { - ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; - for (int i = 0; i < sceneManagers.Length; i++) - yield return UnloadManagerScenes(sceneManagers[i]); + ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; + for (int i = 0; i < sceneDirectors.Length; i++) + yield return UnloadDirectorScenes(sceneDirectors[i]); yield return UnloadRemainingScenes(); } diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json index 465a29dd..e0fe6fa9 100644 --- a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -4,7 +4,7 @@ { "type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "key": "IncludeAssemblies", - "value": "{\"m_Value\":\"MyGameDevTools.SceneLoading,MyGameDevTools.SceneLoading.Api\"}" + "value": "{\"m_Value\":\"MyGameDevTools.SceneLoading\"}" }, { "type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", From 51d45e506fee14d80ee45a31c42a011ec4fb8e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 25 Feb 2025 20:19:33 -0300 Subject: [PATCH 23/53] fix scene director interface file name --- .../Runtime/Interfaces/{ISceneManager.cs => ISceneDirector.cs} | 0 .../Interfaces/{ISceneManager.cs.meta => ISceneDirector.cs.meta} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/{ISceneManager.cs => ISceneDirector.cs} (100%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/{ISceneManager.cs.meta => ISceneDirector.cs.meta} (100%) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs.meta From 8666bbabb7c5d60de0ee197d47fa59b57732ae7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 25 Feb 2025 20:52:42 -0300 Subject: [PATCH 24/53] fix extensions script name --- .../com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs | 2 +- .../{SceneManagerExtensions.cs => SceneDirectorExtensions.cs} | 0 ...anagerExtensions.cs.meta => SceneDirectorExtensions.cs.meta} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/{SceneManagerExtensions.cs => SceneDirectorExtensions.cs} (100%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/{SceneManagerExtensions.cs.meta => SceneDirectorExtensions.cs.meta} (100%) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs index 516d0d36..c1e5c0aa 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs @@ -27,7 +27,7 @@ public class SceneDirector : ISceneDirector ISceneData _activeScene; /// - /// Creates an with no initial scene references. + /// Creates a with no initial scene references. /// public SceneDirector() : this(false) { } /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs.meta From 03b5e273011344cfd3cf968550c0eca7a9de7ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 26 Feb 2025 15:13:30 -0300 Subject: [PATCH 25/53] remove alias from utility class --- .../Runtime/Utilities/SceneDataUtilities.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs index 2eb7b678..0d060016 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; -using UnitySceneManager = UnityEngine.SceneManagement.SceneManager; namespace MyGameDevTools.SceneLoading { @@ -21,13 +20,13 @@ public static class SceneDataUtilities public static void LinkLoadedScenesWithSceneDataArray(ISceneData[] sceneDataArray, IList sceneDatasToExclude) { // Fill this list with all loaded scenes from the Unity Scene Manager; - int totalSceneCount = UnitySceneManager.sceneCount; + int totalSceneCount = SceneManager.sceneCount; List unmatchedScenes = new(totalSceneCount); int i; for (i = 0; i < totalSceneCount; i++) { - Scene scene = UnitySceneManager.GetSceneAt(i); + Scene scene = SceneManager.GetSceneAt(i); if (scene.isLoaded) unmatchedScenes.Add(scene); } From d0068c5cd2d8721545818385ceb85a4b7ea5e5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 26 Feb 2025 15:37:15 -0300 Subject: [PATCH 26/53] rename classes for better cohesion --- .../Runtime/AdvancedSceneManager.cs | 16 +- .../{SceneDirector.cs => CoreSceneManager.cs} | 24 +-- ...ector.cs.meta => CoreSceneManager.cs.meta} | 0 .../Runtime/Interfaces/ISceneData.cs | 4 +- .../{ISceneDirector.cs => ISceneManager.cs} | 16 +- ...Director.cs.meta => ISceneManager.cs.meta} | 0 ...xtensions.cs => SceneManagerExtensions.cs} | 174 ++++++++-------- ...cs.meta => SceneManagerExtensions.cs.meta} | 0 .../Runtime/SceneDirector_DisposeTests.cs | 72 ------- .../Runtime/SceneDirector_ExtensionTests.cs | 185 ------------------ ...eDirectorTests.cs => SceneManagerTests.cs} | 78 ++++---- ...ests.cs.meta => SceneManagerTests.cs.meta} | 0 ...cs => SceneManager_AssetReferenceTests.cs} | 10 +- ... SceneManager_AssetReferenceTests.cs.meta} | 0 ...s.cs => SceneManager_CancellationTests.cs} | 12 +- ...=> SceneManager_CancellationTests.cs.meta} | 0 .../Runtime/SceneManager_DisposeTests.cs | 72 +++++++ ...meta => SceneManager_DisposeTests.cs.meta} | 0 .../Runtime/SceneManager_ExtensionTests.cs | 185 ++++++++++++++++++ ...ta => SceneManager_ExtensionTests.cs.meta} | 0 .../Runtime/Utilities/SceneTestEnvironment.cs | 4 +- .../Runtime/Utilities/SceneTestUtilities.cs | 20 +- .../package.json | 4 +- 23 files changed, 438 insertions(+), 438 deletions(-) rename Packages/com.mygamedevtools.scene-loader/Runtime/{SceneDirector.cs => CoreSceneManager.cs} (91%) rename Packages/com.mygamedevtools.scene-loader/Runtime/{SceneDirector.cs.meta => CoreSceneManager.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/{ISceneDirector.cs => ISceneManager.cs} (94%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/{ISceneDirector.cs.meta => ISceneManager.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/{SceneDirectorExtensions.cs => SceneManagerExtensions.cs} (78%) rename Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/{SceneDirectorExtensions.cs.meta => SceneManagerExtensions.cs.meta} (100%) delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs delete mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirectorTests.cs => SceneManagerTests.cs} (78%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirectorTests.cs.meta => SceneManagerTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_AssetReferenceTests.cs => SceneManager_AssetReferenceTests.cs} (77%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_AssetReferenceTests.cs.meta => SceneManager_AssetReferenceTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_CancellationTests.cs => SceneManager_CancellationTests.cs} (53%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_CancellationTests.cs.meta => SceneManager_CancellationTests.cs.meta} (100%) create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_DisposeTests.cs.meta => SceneManager_DisposeTests.cs.meta} (100%) create mode 100644 Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{SceneDirector_ExtensionTests.cs.meta => SceneManager_ExtensionTests.cs.meta} (100%) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs index cbdd0167..73b93aee 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs @@ -12,25 +12,25 @@ namespace MyGameDevTools.SceneLoading { public static class AdvancedSceneManager { - internal static ISceneDirector Instance + internal static ISceneManager Instance { get { if (_instance == null) - throw new NullReferenceException("[AdvancedSceneManager] The static Scene Director instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); + throw new NullReferenceException("[AdvancedSceneManager] The static Scene Manager instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); return _instance; } } - static ISceneDirector _instance; + static ISceneManager _instance; [RuntimeInitializeOnLoadMethod] internal static void Initialize() { - _instance = new SceneDirector(true); + _instance = new CoreSceneManager(true); } - #region ISceneDirector + #region ISceneManager /// /// Reports that the active scene has changed, passing the previous and current active scene as parameters. ///
@@ -65,7 +65,7 @@ public static event Action SceneLoaded ///
public static int LoadedSceneCount => Instance.LoadedSceneCount; /// - /// The amount of scenes managed by the internal . + /// The amount of scenes managed by the internal . /// This includes scenes that are being unloaded. /// public static int TotalSceneCount => Instance.TotalSceneCount; @@ -146,9 +146,9 @@ public static event Action SceneLoaded public static Scene GetLoadedSceneAt(int index) => Instance.GetLoadedSceneAt(index); /// - /// Gets the last loaded scene of this . + /// Gets the last loaded scene of this . /// - /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . + /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . public static Scene GetLastLoadedScene() => Instance.GetLastLoadedScene(); /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs similarity index 91% rename from Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs index c1e5c0aa..636e15d9 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs @@ -9,9 +9,9 @@ namespace MyGameDevTools.SceneLoading { /// - /// The is capable of managing both addressable and non-addressable scene operations. + /// The is capable of managing both addressable and non-addressable scene operations. /// - public class SceneDirector : ISceneDirector + public class CoreSceneManager : ISceneManager { public event Action ActiveSceneChanged; public event Action SceneUnloaded; @@ -27,15 +27,15 @@ public class SceneDirector : ISceneDirector ISceneData _activeScene; /// - /// Creates a with no initial scene references. + /// Creates a with no initial scene references. /// - public SceneDirector() : this(false) { } + public CoreSceneManager() : this(false) { } /// - /// Creates a new with the option to add all loaded scenes to its management. - /// The advantage is that you can manage those scenes through this instead of having to + /// Creates a new with the option to add all loaded scenes to its management. + /// The advantage is that you can manage those scenes through this instead of having to /// use the Unity . /// - public SceneDirector(bool addLoadedScenes) + public CoreSceneManager(bool addLoadedScenes) { if (!addLoadedScenes) { @@ -58,19 +58,19 @@ public SceneDirector(bool addLoadedScenes) } else if (loadedSceneCount == 0) { - Debug.LogWarning("Tried to create a `SceneDirector` with all loaded scenes, but encoutered none. Did you create the Scene Director on `Awake()`? If so, try moving the call to `Start()` instead."); + Debug.LogWarning("Tried to create a Scene Manager with all loaded scenes, but encoutered none. Did you create the Scene Manager on `Awake()`? If so, try moving the call to `Start()` instead."); } } /// - /// Creates a new with the option to add a list of loaded scenes to its management. - /// The advantage is that you can manage those scenes through this instead of having to + /// Creates a new with the option to add a list of loaded scenes to its management. + /// The advantage is that you can manage those scenes through this instead of having to /// use the Unity . /// - public SceneDirector(Scene[] initializationScenes) + public CoreSceneManager(Scene[] initializationScenes) { if (initializationScenes == null || initializationScenes.Length == 0) { - throw new ArgumentException($"Trying to create an {nameof(SceneDirector)} with a null or empty array of initialization scenes. If you want to create it without any scenes, use the empty constructor instead.", nameof(initializationScenes)); + throw new ArgumentException($"Trying to create an {nameof(CoreSceneManager)} with a null or empty array of initialization scenes. If you want to create it without any scenes, use the empty constructor instead.", nameof(initializationScenes)); } int loadedSceneCount = initializationScenes.Length; diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/SceneDirector.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/CoreSceneManager.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs index 1b387866..797c0676 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneData.cs @@ -25,7 +25,7 @@ public interface ISceneData /// Manually updates the scene reference with a given scene. /// Useful for linking scenes that have not been loaded through addressable operations (that can directly link the loaded scene). ///
- /// Should not be called outside of an . + /// Should not be called outside of an . ///
void SetSceneReferenceManually(Scene scene); @@ -33,7 +33,7 @@ public interface ISceneData /// Updates the value based on the result. /// Cannot be used for non-addressable contexts, since they are not able to directly link the loaded scene. ///
- /// Should not be called outside of an . + /// Should not be called outside of an . ///
void UpdateSceneReference(); diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs similarity index 94% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs index 0a85a376..a6a93b69 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs @@ -7,9 +7,9 @@ namespace MyGameDevTools.SceneLoading { /// /// Interface to standardize scene management operations. - /// The Scene Director is responsible for scene loading operations, keeping track of its loaded scene stack and dispatching scene load events. + /// The Scene Manager is responsible for scene loading operations, keeping track of its loaded scene stack and dispatching scene load events. /// - public interface ISceneDirector : IDisposable + public interface ISceneManager : IDisposable { /// /// Reports that the active scene has changed, passing the previous and current active scene as parameters. @@ -29,12 +29,12 @@ public interface ISceneDirector : IDisposable event Action SceneLoaded; /// - /// The amount of scenes loaded through this . + /// The amount of scenes loaded through this . /// To get the total amount of loaded scenes, check . /// int LoadedSceneCount { get; } /// - /// The amount of scenes managed by this . + /// The amount of scenes managed by this . /// This includes scenes that are being unloaded. /// int TotalSceneCount { get; } @@ -101,8 +101,8 @@ public interface ISceneDirector : IDisposable Task UnloadAsync(SceneParameters sceneParameters, CancellationToken token = default); /// - /// Gets the current active scene in this instance. - /// This should point to the same scene you get via if it was loaded through this . + /// Gets the current active scene in this instance. + /// This should point to the same scene you get via if it was loaded through this . /// /// The current active scene, or an invalid scene if none of the loaded scenes are enabled as the active scene. Scene GetActiveScene(); @@ -115,9 +115,9 @@ public interface ISceneDirector : IDisposable Scene GetLoadedSceneAt(int index); /// - /// Gets the last loaded scene of this . + /// Gets the last loaded scene of this . /// - /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . + /// The last loaded scene, or an invalid scene if there are no loaded scenes in this . Scene GetLastLoadedScene(); /// diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneDirector.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/Interfaces/ISceneManager.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs similarity index 78% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs index bb7f91f7..00fce7aa 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs @@ -9,7 +9,7 @@ namespace MyGameDevTools.SceneLoading { - public static class SceneDirectorExtensions + public static class SceneManagerExtensions { /// /// Loads the target scenes. @@ -28,12 +28,12 @@ public static class SceneDirectorExtensions /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAsync(this ISceneDirector sceneDirector, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, string[] sceneNames, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -53,12 +53,12 @@ public static Task LoadAsync(this ISceneDirector sceneDirector, str /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAsync(this ISceneDirector sceneDirector, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, int[] buildIndices, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -78,11 +78,11 @@ public static Task LoadAsync(this ISceneDirector sceneDirector, int /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAsync(this ISceneDirector sceneDirector, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, string sceneName, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName), setActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -102,11 +102,11 @@ public static Task LoadAsync(this ISceneDirector sceneDirector, str /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAsync(this ISceneDirector sceneDirector, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAsync(this ISceneManager sceneManager, int buildIndex, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex), setActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } #if ENABLE_ADDRESSABLES @@ -127,12 +127,12 @@ public static Task LoadAsync(this ISceneDirector sceneDirector, int /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -152,12 +152,12 @@ public static Task LoadAddressableAsync(this ISceneDirector sceneDi /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, string[] addresses, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos, setIndexActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -177,11 +177,11 @@ public static Task LoadAddressableAsync(this ISceneDirector sceneDi /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference), setActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } /// @@ -201,17 +201,17 @@ public static Task LoadAddressableAsync(this ISceneDirector sceneDi /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all scenes loaded. - public static Task LoadAddressableAsync(this ISceneDirector sceneDirector, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task LoadAddressableAsync(this ISceneManager sceneManager, string address, bool setActive = false, IProgress progress = null, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address), setActive); - return sceneDirector.LoadAsync(sceneParams, progress, token); + return sceneManager.LoadAsync(sceneParams, progress, token); } #endif /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -232,17 +232,17 @@ public static Task LoadAddressableAsync(this ISceneDirector sceneDi /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneDirector sceneDirector, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, string[] targetSceneNames, string loadingSceneName = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetSceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -263,17 +263,17 @@ public static Task TransitionAsync(this ISceneDirector sceneDirecto /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneDirector sceneDirector, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, int[] targetBuildIndices, int loadingBuildIndex = -1, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetBuildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -291,17 +291,17 @@ public static Task TransitionAsync(this ISceneDirector sceneDirecto /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneDirector sceneDirector, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, string targetSceneName, string loadingSceneName = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoName(targetSceneName), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingSceneName) ? null : new LoadSceneInfoName(loadingSceneName); - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -319,18 +319,18 @@ public static Task TransitionAsync(this ISceneDirector sceneDirecto /// If -1, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAsync(this ISceneDirector sceneDirector, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAsync(this ISceneManager sceneManager, int targetBuildIndex, int loadingBuildIndex = -1, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoIndex(targetBuildIndex), true); ILoadSceneInfo loadingSceneInfo = loadingBuildIndex >= 0 ? new LoadSceneInfoIndex(loadingBuildIndex) : null; - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } #if ENABLE_ADDRESSABLES /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -351,17 +351,17 @@ public static Task TransitionAsync(this ISceneDirector sceneDirecto /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference[] targetAssetReferences, AssetReference loadingAssetReference = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAssetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to a group of scenes. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to a group of scenes, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -382,17 +382,17 @@ public static Task TransitionAddressableAsync(this ISceneDirector s /// The index of the scene to be activated as the active scene. It must be greater than or equal 0. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string[] targetAddresses, string loadingAddress = null, int setIndexActive = 0, CancellationToken token = default) { SceneParameters targetParams = new(targetAddresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(), setIndexActive); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -410,17 +410,17 @@ public static Task TransitionAddressableAsync(this ISceneDirector s /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, AssetReference targetAssetReference, AssetReference loadingAssetReference = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAssetReference(targetAssetReference), true); ILoadSceneInfo loadingSceneInfo = loadingAssetReference != null ? new LoadSceneInfoAssetReference(loadingAssetReference) : null; - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } /// /// Triggers a transition to the target scene. - /// It will transition from the current active scene () + /// It will transition from the current active scene () /// to the target scene, with an optional . /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. /// The complete transition flow is: @@ -438,12 +438,12 @@ public static Task TransitionAddressableAsync(this ISceneDirector s /// If null, the transition will not have an intermediate loading scene. /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. - /// A with all scenes loaded. - public static Task TransitionAddressableAsync(this ISceneDirector sceneDirector, string targetAddress, string loadingAddress = null, CancellationToken token = default) + /// A with all scenes loaded. + public static Task TransitionAddressableAsync(this ISceneManager sceneManager, string targetAddress, string loadingAddress = null, CancellationToken token = default) { SceneParameters targetParams = new(new LoadSceneInfoAddress(targetAddress), true); ILoadSceneInfo loadingSceneInfo = string.IsNullOrWhiteSpace(loadingAddress) ? null : new LoadSceneInfoAddress(loadingAddress); - return sceneDirector.TransitionAsync(targetParams, loadingSceneInfo, token); + return sceneManager.TransitionAsync(targetParams, loadingSceneInfo, token); } #endif @@ -455,15 +455,15 @@ public static Task TransitionAddressableAsync(this ISceneDirector s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, string[] sceneNames, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, string[] sceneNames, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = sceneNames.Select(name => (ILoadSceneInfo)new LoadSceneInfoName(name)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -474,15 +474,15 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, int[] buildIndices, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, int[] buildIndices, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = buildIndices.Select(index => (ILoadSceneInfo)new LoadSceneInfoIndex(index)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -493,15 +493,15 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, i /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, Scene[] scenes, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, Scene[] scenes, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = scenes.Select(scene => (ILoadSceneInfo)new LoadSceneInfoScene(scene)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -512,14 +512,14 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, S /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, string sceneName, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, string sceneName, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoName(sceneName)); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -530,14 +530,14 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, s /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, int buildIndex, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, int buildIndex, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoIndex(buildIndex)); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -548,14 +548,14 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, i /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAsync(this ISceneDirector sceneDirector, Scene scene, CancellationToken token = default) + public static Task UnloadAsync(this ISceneManager sceneManager, Scene scene, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoScene(scene)); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } #if ENABLE_ADDRESSABLES @@ -567,15 +567,15 @@ public static Task UnloadAsync(this ISceneDirector sceneDirector, S /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, AssetReference[] assetReferences, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference[] assetReferences, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = assetReferences.Select(asset => (ILoadSceneInfo)new LoadSceneInfoAssetReference(asset)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -586,15 +586,15 @@ public static Task UnloadAddressableAsync(this ISceneDirector scene /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, string[] addresses, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string[] addresses, CancellationToken token = default) { ILoadSceneInfo[] sceneInfos = addresses.Select(address => (ILoadSceneInfo)new LoadSceneInfoAddress(address)).ToArray(); SceneParameters sceneParams = new(sceneInfos); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -605,14 +605,14 @@ public static Task UnloadAddressableAsync(this ISceneDirector scene /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, AssetReference assetReference, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, AssetReference assetReference, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAssetReference(assetReference)); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } /// @@ -623,14 +623,14 @@ public static Task UnloadAddressableAsync(this ISceneDirector scene /// /// Optional token to manually cancel the operation. Note that Unity Scene Manager operations cannot be manually canceled and will continue to run. /// - /// A with all the unloaded scenes. + /// A with all the unloaded scenes. ///
/// Note that in some cases, the returned scenes might no longer have a reference to its native representation, hich means its will not point anywhere and you won't be able to perform equal comparisons between scenes. ///
- public static Task UnloadAddressableAsync(this ISceneDirector sceneDirector, string address, CancellationToken token = default) + public static Task UnloadAddressableAsync(this ISceneManager sceneManager, string address, CancellationToken token = default) { SceneParameters sceneParams = new(new LoadSceneInfoAddress(address)); - return sceneDirector.UnloadAsync(sceneParams, token); + return sceneManager.UnloadAsync(sceneParams, token); } #endif } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDirectorExtensions.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneManagerExtensions.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs deleted file mode 100644 index 7aacd746..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections; -using UnityEngine; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - public class SceneDirector_DisposeTests : SceneTestBase - { - // Note: These functions must create new Scene Directors to correctly test the dispose flow - static readonly Func[] _sceneDirectorCreateFuncs = new Func[] - { - () => new SceneDirector(), - }; - - [Test] - public void Dispose_Simple([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc) - { - ISceneDirector director = directorCreateFunc(); - Assert.DoesNotThrow(director.Dispose); - } - - [UnityTest] - public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) - { - ISceneDirector director = directorCreateFunc(); - WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); - director.Dispose(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - } - - [UnityTest] - public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) - { - ISceneDirector director = directorCreateFunc(); - WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); - yield return waitTask; - - waitTask = new(director.UnloadAsync(sceneParameters)); - director.Dispose(); - yield return waitTask; - Assert.True(waitTask.Task.IsCanceled); - } - - [UnityTest] - public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneDirectorCreateFuncs))] Func directorCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneDirectorTests), nameof(SceneDirectorTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) - { - async Awaitable Test() - { - ISceneDirector director = directorCreateFunc(); - await SceneDirectorTests.LoadFirstScene(director).Task; - - var task = director.TransitionAsync(sceneParameters, loadingScene); - director.Dispose(); - - bool canceled = false; - try - { - await task; - } - catch (OperationCanceledException) - { - canceled = true; - } - Assert.True(canceled); - } - return Test(); - } - } -} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs deleted file mode 100644 index 72a443ec..00000000 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System.Collections; -using System.Threading.Tasks; -using NUnit.Framework; -using UnityEngine.TestTools; - -namespace MyGameDevTools.SceneLoading.Tests -{ - public partial class SceneDirectorTests - { - readonly int[] _buildIndexes = new[] { 1, 2, 3 }; - - [UnityTest] - public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAsync(1, true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); - } - - [UnityTest] - public IEnumerator Load_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); - } - - [UnityTest] - public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - var progress = new SimpleProgress(); - yield return Load_Template(director, () => director.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); - } -#endif - - [UnityTest] - public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAsync(1, 1), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); - } - - [UnityTest] - public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Transition_Template(director, () => director.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); - } -#endif - - [UnityTest] - public IEnumerator Unload_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAsync(1, true), () => director.UnloadAsync(1), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAsync(_buildIndexes, 0), () => director.UnloadAsync(_buildIndexes), _buildIndexes.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames[1], true), () => director.UnloadAsync(SceneBuilder.SceneNames[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAsync(SceneBuilder.SceneNames, 0), () => director.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - Task loadTask = Task.FromResult(default); - yield return Unload_Template(director, () => - { - loadTask = director.LoadAsync(SceneBuilder.SceneNames, 0); - return loadTask; - }, () => - { - SceneResult result = loadTask.GetAwaiter().GetResult(); - return director.UnloadAsync(result.GetScenes()); - }, SceneBuilder.SceneNames.Length); - } - -#if ENABLE_ADDRESSABLES - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => director.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => director.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAddressableAsync(_assetReferences[1], true), () => director.UnloadAddressableAsync(_assetReferences[1]), 1); - } - - [UnityTest] - public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) - { - yield return Unload_Template(director, () => director.LoadAddressableAsync(_assetReferences, 0), () => director.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); - } -#endif - } -} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs similarity index 78% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 3c5df2e0..27588244 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -11,7 +11,7 @@ namespace MyGameDevTools.SceneLoading.Tests { - public partial class SceneDirectorTests : SceneTestBase + public partial class SceneManagerTests : SceneTestBase { public static readonly ILoadSceneInfo[] LoadingSceneInfos = new ILoadSceneInfo[] { @@ -32,10 +32,10 @@ public void OneTimeSetup() { SceneTestEnvironment.ValidateSceneEnvironment(); - ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; - for (int i = 0; i < sceneDirectors.Length; i++) + ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; + for (int i = 0; i < sceneManagers.Length; i++) { - var director = sceneDirectors[i]; + var director = sceneManagers[i]; director.ActiveSceneChanged += ReportSceneActivation; director.SceneUnloaded += ReportSceneUnloaded; director.SceneLoaded += ReportSceneLoaded; @@ -45,10 +45,10 @@ public void OneTimeSetup() [OneTimeTearDown] public void OneTimeTeardown() { - ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; - for (int i = 0; i < sceneDirectors.Length; i++) + ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; + for (int i = 0; i < sceneManagers.Length; i++) { - var director = sceneDirectors[i]; + var director = sceneManagers[i]; director.ActiveSceneChanged -= ReportSceneActivation; director.SceneUnloaded -= ReportSceneUnloaded; director.SceneLoaded -= ReportSceneLoaded; @@ -68,10 +68,10 @@ public IEnumerator Constructor_AddLoadedScenes() { yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); - ISceneDirector sceneDirector = new SceneDirector(true); + ISceneManager sceneManager = new CoreSceneManager(true); - Assert.AreEqual(2, sceneDirector.LoadedSceneCount); - Assert.AreEqual(sceneDirector.TotalSceneCount, sceneDirector.LoadedSceneCount); + Assert.AreEqual(2, sceneManager.LoadedSceneCount); + Assert.AreEqual(sceneManager.TotalSceneCount, sceneManager.LoadedSceneCount); } [UnityTest] @@ -80,10 +80,10 @@ public IEnumerator Constructor_InitializationScenes() yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); Scene loadedScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - ISceneDirector sceneDirector = new SceneDirector(new Scene[] { loadedScene }); + ISceneManager sceneManager = new CoreSceneManager(new Scene[] { loadedScene }); - Assert.AreEqual(1, sceneDirector.LoadedSceneCount); - Assert.AreEqual(sceneDirector.TotalSceneCount, sceneDirector.LoadedSceneCount); + Assert.AreEqual(1, sceneManager.LoadedSceneCount); + Assert.AreEqual(sceneManager.TotalSceneCount, sceneManager.LoadedSceneCount); } [UnityTest] @@ -92,16 +92,16 @@ public IEnumerator InitializationScene_Unload() yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); Scene loadedScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - ISceneDirector sceneDirector = new SceneDirector(new Scene[] { loadedScene }); + ISceneManager sceneManager = new CoreSceneManager(new Scene[] { loadedScene }); WaitTask waitTask = default; - Assert.DoesNotThrow(() => waitTask = sceneDirector.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).ToWaitTask()); + Assert.DoesNotThrow(() => waitTask = sceneManager.UnloadAsync(new SceneParameters(new LoadSceneInfoScene(loadedScene))).ToWaitTask()); yield return waitTask; } [UnityTest] - public IEnumerator SetActive_NotThroughDirector([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public IEnumerator SetActive_NotThroughDirector([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { Scene loadedScene = default; SceneManager.sceneLoaded += assignLoadedScene; @@ -121,13 +121,13 @@ void assignLoadedScene(Scene scene, LoadSceneMode loadSceneMode) } [Test] - public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { Assert.False(director.GetActiveScene().IsValid()); } [UnityTest] - public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { var loadTask = director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); @@ -142,13 +142,13 @@ public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment } [Test] - public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { Assert.Throws(() => director.GetLoadedSceneByName("not-a-real-scene")); } [UnityTest] - public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { yield return director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); @@ -156,28 +156,28 @@ public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvir } [Test] - public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { Assert.False(director.GetLastLoadedScene().IsValid()); Assert.False(director.GetActiveScene().IsValid()); } [Test] - public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { Assert.Throws(() => director.GetLoadedSceneAt(-1)); Assert.Throws(() => director.GetLoadedSceneAt(1)); } [UnityTest] - public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); return Load_Template(director, () => director.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); @@ -186,7 +186,7 @@ public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), name } [UnityTest] - public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int length = sceneInfos.Length; @@ -214,7 +214,7 @@ public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof } [Test] - public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { var sceneName = "not-a-real-scene"; LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); @@ -223,30 +223,30 @@ public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(Sc } [UnityTest] - public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { yield return Unload_Template(director, () => director.LoadAsync(sceneParameters), () => director.UnloadAsync(sceneParameters), sceneParameters.Length); } [Test] - public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) { var sceneName = "not-a-real-scene"; - if (director is not SceneDirector) + if (director is not SceneManager) LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); var wait = director.UnloadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } [UnityTest] - public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { yield return Transition_Template(director, () => director.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { int expectedLoadedScenes = loadingScene == null ? 1 : 2; // If there's no loading scene, the scene manager will create a temporary scene @@ -279,7 +279,7 @@ void sceneUnloaded(Scene scene) } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { var task = director.LoadAsync(new SceneParameters(sceneInfo)); @@ -295,7 +295,7 @@ public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnviro } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { var task = director.LoadAsync(new SceneParameters(sceneInfo)); @@ -309,7 +309,7 @@ public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnviron } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { var task = director.LoadAsync(new SceneParameters(sceneInfo)); @@ -323,7 +323,7 @@ public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnviron } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { var task = director.LoadAsync(new SceneParameters(sceneInfo)); @@ -340,7 +340,7 @@ public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnviro Assert.Zero(director.LoadedSceneCount); } - public IEnumerator Load_Template(ISceneDirector director, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + public IEnumerator Load_Template(ISceneManager director, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); director.SceneLoaded += reportSceneLoaded; @@ -367,7 +367,7 @@ public IEnumerator Load_Template(ISceneDirector director, Func void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); } - public IEnumerator Transition_Template(ISceneDirector director, Func> transitionTask, int sceneCount, int setIndexActive) + public IEnumerator Transition_Template(ISceneManager director, Func> transitionTask, int sceneCount, int setIndexActive) { yield return LoadFirstScene(director); @@ -381,7 +381,7 @@ public IEnumerator Transition_Template(ISceneDirector director, Func director.TotalSceneCount == sceneCount); } - public IEnumerator Unload_Template(ISceneDirector director, Func> loadTask, Func> unloadTask, int sceneCount) + public IEnumerator Unload_Template(ISceneManager director, Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); yield return load.ToWaitTask(); @@ -422,7 +422,7 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene(ISceneDirector sceneDirector) => sceneDirector.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); + public static WaitTask LoadFirstScene(ISceneManager sceneManager) => sceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); void ReportSceneActivation(Scene previousScene, Scene newScene) { diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirectorTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs similarity index 77% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs index 1c21b984..b6a8e458 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs @@ -10,7 +10,7 @@ namespace MyGameDevTools.SceneLoading.Tests // Note: AssetReference load scene infos cannot be created statically, since the // scenes are generated in IPrebuildSetup and don't have deterministic guids between // Unity Editor sessions. So, we must test AssetReference load scene infos "manually". - public partial class SceneDirectorTests + public partial class SceneManagerTests { AssetReference[] _assetReferences; ILoadSceneInfo[] _assetReferenceLoadSceneInfos; @@ -36,15 +36,15 @@ public void AssetReferenceSetup() } [UnityTest] - public IEnumerator Load_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) + public IEnumerator Load_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(nameof(_setIndexActiveParameterValues))] int setIndexActive) { - yield return Load(director, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); + yield return Load(manager, new SceneParameters(_assetReferenceLoadSceneInfos, setIndexActive)); } [UnityTest] - public IEnumerator Unload_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director) + public IEnumerator Unload_AssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return Unload(director, new SceneParameters(_assetReferenceLoadSceneInfos)); + yield return Unload(manager, new SceneParameters(_assetReferenceLoadSceneInfos)); } } } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_AssetReferenceTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_AssetReferenceTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs similarity index 53% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs index 34850a2d..1277f0fd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs @@ -5,13 +5,13 @@ namespace MyGameDevTools.SceneLoading.Tests { - public class SceneDirector_CancellationTests : SceneTestBase + public class SceneManager_CancellationTests : SceneTestBase { [UnityTest] - public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = director.LoadAsync(sceneParameters, token: tokenSource.Token).ToWaitTask(); + WaitTask waitTask = manager.LoadAsync(sceneParameters, token: tokenSource.Token).ToWaitTask(); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); @@ -19,13 +19,13 @@ public IEnumerator Cancellation_DuringLoad([ValueSource(typeof(SceneTestEnvironm } [UnityTest] - public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneDirectors))] ISceneDirector director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Cancellation_DuringUnload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { CancellationTokenSource tokenSource = new(); - WaitTask waitTask = director.LoadAsync(sceneParameters).ToWaitTask(); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); yield return waitTask; - waitTask = new(director.UnloadAsync(sceneParameters, token: tokenSource.Token)); + waitTask = new(manager.UnloadAsync(sceneParameters, token: tokenSource.Token)); tokenSource.Cancel(); yield return waitTask; Assert.True(waitTask.Task.IsCanceled); diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_CancellationTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_CancellationTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs new file mode 100644 index 00000000..f072d6ea --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -0,0 +1,72 @@ +using NUnit.Framework; +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Tests +{ + public class SceneManager_DisposeTests : SceneTestBase + { + // Note: These functions must create new Scene Managers to correctly test the dispose flow + static readonly Func[] _sceneManagerCreateFuncs = new Func[] + { + () => new CoreSceneManager(), + }; + + [Test] + public void Dispose_Simple([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc) + { + ISceneManager manager = managerCreateFunc(); + Assert.DoesNotThrow(manager.Dispose); + } + + [UnityTest] + public IEnumerator Dispose_DuringLoad([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + ISceneManager manager = managerCreateFunc(); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); + manager.Dispose(); + yield return waitTask; + Assert.True(waitTask.Task.IsCanceled); + } + + [UnityTest] + public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + { + ISceneManager manager = managerCreateFunc(); + WaitTask waitTask = manager.LoadAsync(sceneParameters).ToWaitTask(); + yield return waitTask; + + waitTask = new(manager.UnloadAsync(sceneParameters)); + manager.Dispose(); + yield return waitTask; + Assert.True(waitTask.Task.IsCanceled); + } + + [UnityTest] + public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + async Awaitable Test() + { + ISceneManager manager = managerCreateFunc(); + await SceneManagerTests.LoadFirstScene(manager).Task; + + var task = manager.TransitionAsync(sceneParameters, loadingScene); + manager.Dispose(); + + bool canceled = false; + try + { + await task; + } + catch (OperationCanceledException) + { + canceled = true; + } + Assert.True(canceled); + } + return Test(); + } + } +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_DisposeTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs new file mode 100644 index 00000000..0f578e82 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs @@ -0,0 +1,185 @@ +using System.Collections; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace MyGameDevTools.SceneLoading.Tests +{ + public partial class SceneManagerTests + { + readonly int[] _buildIndexes = new[] { 1, 2, 3 }; + + [UnityTest] + public IEnumerator Load_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(1, true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); + } + + [UnityTest] + public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + var progress = new SimpleProgress(); + yield return Load_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); + } +#endif + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(1, 1), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); + } + + [UnityTest] + public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Transition_Template(manager, () => manager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); + } +#endif + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(1, true), () => manager.UnloadAsync(1), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByIndex_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(_buildIndexes, 0), () => manager.UnloadAsync(_buildIndexes), _buildIndexes.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByName_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_ByScene_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + Task loadTask = Task.FromResult(default); + yield return Unload_Template(manager, () => + { + loadTask = manager.LoadAsync(SceneBuilder.SceneNames, 0); + return loadTask; + }, () => + { + SceneResult result = loadTask.GetAwaiter().GetResult(); + return manager.UnloadAsync(result.GetScenes()); + }, SceneBuilder.SceneNames.Length); + } + +#if ENABLE_ADDRESSABLES + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => manager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences[1], true), () => manager.UnloadAddressableAsync(_assetReferences[1]), 1); + } + + [UnityTest] + public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) + { + yield return Unload_Template(manager, () => manager.LoadAddressableAsync(_assetReferences, 0), () => manager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); + } +#endif + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneDirector_ExtensionTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_ExtensionTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs index 6066ba25..9cedd2a5 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestEnvironment.cs @@ -95,9 +95,9 @@ public class SceneTestEnvironment : IPrebuildSetup, IPostBuildCleanup new(_multipleLoadSceneInfoList[1], 1), }; - public static readonly ISceneDirector[] SceneDirectors = new ISceneDirector[] + public static readonly ISceneManager[] SceneManagers = new ISceneManager[] { - new SceneDirector(), + new CoreSceneManager(), }; #if UNITY_EDITOR diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs index 00614cd3..987d18cd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/Utilities/SceneTestUtilities.cs @@ -6,17 +6,17 @@ namespace MyGameDevTools.SceneLoading.Tests { public static class SceneTestUtilities { - public static IEnumerator UnloadDirectorScenes(ISceneDirector sceneDirector) + public static IEnumerator UnloadDirectorScenes(ISceneManager sceneManager) { - var lastScene = sceneDirector.GetLastLoadedScene(); - while (sceneDirector.LoadedSceneCount > 0 && lastScene.IsValid()) + var lastScene = sceneManager.GetLastLoadedScene(); + while (sceneManager.LoadedSceneCount > 0 && lastScene.IsValid()) { - yield return new WaitTask(sceneDirector.UnloadAsync(lastScene)); - lastScene = sceneDirector.GetLastLoadedScene(); + yield return new WaitTask(sceneManager.UnloadAsync(lastScene)); + lastScene = sceneManager.GetLastLoadedScene(); } - Assert.Zero(sceneDirector.LoadedSceneCount); - Assert.False(sceneDirector.GetActiveScene().IsValid()); + Assert.Zero(sceneManager.LoadedSceneCount); + Assert.False(sceneManager.GetActiveScene().IsValid()); } public static IEnumerator UnloadRemainingScenes() @@ -33,9 +33,9 @@ public static IEnumerator UnloadRemainingScenes() public static IEnumerator UnloadAllScenes() { - ISceneDirector[] sceneDirectors = SceneTestEnvironment.SceneDirectors; - for (int i = 0; i < sceneDirectors.Length; i++) - yield return UnloadDirectorScenes(sceneDirectors[i]); + ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; + for (int i = 0; i < sceneManagers.Length; i++) + yield return UnloadDirectorScenes(sceneManagers[i]); yield return UnloadRemainingScenes(); } diff --git a/Packages/com.mygamedevtools.scene-loader/package.json b/Packages/com.mygamedevtools.scene-loader/package.json index 25933883..c63cff07 100644 --- a/Packages/com.mygamedevtools.scene-loader/package.json +++ b/Packages/com.mygamedevtools.scene-loader/package.json @@ -2,7 +2,7 @@ "name": "com.mygamedevtools.scene-loader", "version": "3.1.0", "displayName": "Advanced Scene Manager", - "description": "This package simplifies scene operations: load, unload and transition. In a quick example:\n\n▐ // Unity Manager scene transition\n▐ yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n▐ LoadSceneMode.Additive);\n▐ yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n▐ LoadSceneMode.Additive);\n▐\n▐ SceneManager.SetActiveScene(\n▐ SceneManager.GetSceneByName(\"my-target-scene\"));\n▐\n▐ SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n▐ SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n▐\n▐ // Advanced Scene Management scene transition\n▐ sceneLoader.TransitionToScene(\n▐ new LoadSceneInfoName(\"my-target-scene\"),\n▐ new LoadSceneInfoName(\"my-loading-scene\"));\n\nYou can also take advantage of these features:\n\nβ–ͺ Unified API for addressable and non-addressable scenes.\nβ–ͺ Awaitable scene operations.\nβ–ͺ Modular implementation with interfaces.\nβ–ͺ Load, unload or transition to multiple scenes.", + "description": "This package simplifies scene operations: load, unload and transition. In a quick example:\n\n\u2590 // Unity Manager scene transition\n\u2590 yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n\u2590 LoadSceneMode.Additive);\n\u2590 yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n\u2590 LoadSceneMode.Additive);\n\u2590\n\u2590 SceneManager.SetActiveScene(\n\u2590 SceneManager.GetSceneByName(\"my-target-scene\"));\n\u2590\n\u2590 SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n\u2590 SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n\u2590\n\u2590 // Advanced Scene Manager scene transition\n\u2590 AdvancedSceneManager.TransitionAsync(\"my-target-scene\", \"my-loading-scene\");\n\nYou can also take advantage of these features:\n\n\u25aa Unified API for addressable and non-addressable scenes.\n\u25aa Awaitable scene operations.\n\u25aa Modular implementation with interfaces.\n\u25aa Load, unload or transition to multiple scenes.", "unity": "2021.3", "keywords": [], "author": { @@ -15,4 +15,4 @@ "licensesUrl": "https://github.com/mygamedevtools/scene-loader?tab=MIT-1-ov-file", "changelogUrl": "https://github.com/mygamedevtools/scene-loader/blob/main/CHANGELOG.md", "hideInEditor": false -} +} \ No newline at end of file From 67e810cd258fe9051657af4321ce7f81096f6ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 1 Mar 2025 12:09:43 -0300 Subject: [PATCH 27/53] fix: bump version, update license --- .gitignore | 6 +++++- LICENSE | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index ed7cf513..401a9d35 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,8 @@ crashlytics-build.properties # Temporary auto-generated Android Assets [Aa]ssets/[Ss]treamingAssets/aa.meta -[Aa]ssets/[Ss]treamingAssets/aa/* \ No newline at end of file +[Aa]ssets/[Ss]treamingAssets/aa/* + +# Website +.docusaurus +node_modules/ \ No newline at end of file diff --git a/LICENSE b/LICENSE index 33cbcce8..ad781d94 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Joao Borks +Copyright (c) 2022 MyGameDevTools Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 9ef8dade1240cb1f45388d0a3f966ac176547611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 2 Mar 2025 00:37:41 -0300 Subject: [PATCH 28/53] update docs --- .github/ISSUE_TEMPLATE/bug_report.yml | 71 +++ .github/ISSUE_TEMPLATE/feature_request.yml | 38 ++ .github/ISSUE_TEMPLATE/question.yml | 39 ++ CODE_OF_CONDUCT.md | 47 ++ CONTRIBUTING.md | 75 +++ README.md | 708 ++------------------- docs/img/banner.jpg | Bin 0 -> 86244 bytes 7 files changed, 306 insertions(+), 672 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/ISSUE_TEMPLATE/question.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/img/banner.jpg diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..09bfa0f2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,71 @@ +name: Bug Report +description: Report a bug or unexpected behavior +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + ## Bug Report + Please provide as much detail as possible to help us identify and fix the issue. + - type: input + id: summary + attributes: + label: Summary + description: A brief summary of the bug + placeholder: "Scene transition freezes..." + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Steps to reproduce the issue + placeholder: | + 1. Load scene A + 2. Transition to scene B + 3. Observe the freeze + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened? + validations: + required: true + - type: input + id: version + attributes: + label: Advanced Scene Manager Version + description: The version of the package you are using + placeholder: "e.g., 3.1.0" + validations: + required: true + - type: input + id: editorversion + attributes: + label: Unity Editor Version + description: The version of the Unity Editor you are using + placeholder: "e.g., 6000.0.40f1" + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs + description: Please attach any relevant logs or errors + render: shell + - type: checkboxes + id: terms + attributes: + label: Acknowledgement + options: + - label: I have searched the existing issues to avoid duplicates + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..96c32090 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,38 @@ +name: Feature Request +description: Suggest an idea or enhancement +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + ## Feature Request + Have a feature idea? Let us know what you'd like to see in the Advanced Scene Manager! + - type: input + id: summary + attributes: + label: Summary + description: A brief summary of the feature + placeholder: "Add support for async scene loading with progress callbacks" + validations: + required: true + - type: textarea + id: problem + attributes: + label: Problem or Use Case + description: What problem would this feature solve? How would it be useful? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed Solution + description: Describe how you'd like the feature to work + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Acknowledgement + options: + - label: I have searched the existing issues to ensure this feature hasn't been requested already + required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 00000000..edfba632 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,39 @@ +name: Question +description: Ask a question or request help +labels: ["question"] +body: + - type: markdown + attributes: + value: | + ## Question or Support Request + Need help or have a question about using the Advanced Scene Manager? Let us know! + - type: textarea + id: question + attributes: + label: Your Question + description: Clearly describe your question or the help you need + validations: + required: true + - type: input + id: version + attributes: + label: Advanced Scene Manager Version + description: The version of the package you are using + placeholder: "e.g., 3.1.0" + validations: + required: true + - type: input + id: editorversion + attributes: + label: Unity Editor Version + description: The version of the Unity Editor you are using + placeholder: "e.g., 6000.0.40f1" + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Acknowledgement + options: + - label: I have searched the documentation and existing issues + required: true diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..c41729d8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,47 @@ +# Code of Conduct + +## Our Pledge + +We, as contributors and maintainers of Advanced Scene Manager, pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We are committed to fostering an open, welcoming, and inclusive community. + +## Our Standards + +Examples of behavior that contribute to a positive environment include: + +- Being respectful and inclusive of differing viewpoints and experiences. +- Giving and gracefully accepting constructive feedback. +- Using welcoming and inclusive language. +- Focusing on what is best for the community. +- Showing empathy towards other community members. + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, or unwelcome sexual attention or advances. +- Trolling, insulting or derogatory comments, and personal or political attacks. +- Public or private harassment. +- Publishing others’ private information without explicit permission. +- Other conduct which could reasonably be considered inappropriate in a professional setting. + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct, or to ban temporarily or permanently any contributor for behaviors they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, including GitHub issues, pull requests, discussions, and any other communication channels used by the project. It also applies to public spaces when an individual is representing the project or its community. + +Examples of representing the project include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers via GitHub issues or direct contact. All complaints will be reviewed and investigated promptly and fairly. + +Project maintainers are obligated to maintain the confidentiality of the reporter of an incident. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..efd1690e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contribution Guide + +Thank you for considering contributing to Advanced Scene Manager! Whether you're fixing a bug, adding a feature, or improving the documentation, your contributions are greatly appreciated and help make the tool better for everyone. + +## How to Contribute + +There are several ways you can contribute to Advanced Scene Manager: + +### 1. Reporting Issues + +If you encounter any bugs or have feedback on features, please report them by opening an issue. When reporting an issue, please provide as much detail as possible, including: + +- Steps to reproduce the bug (if applicable) +- What behavior you expected and what actually happened +- Any relevant error messages or logs + +### 2. Submitting Code Changes + +If you'd like to submit code to fix an issue or add a feature, please follow these steps: + +#### Fork the Repository + +- Navigate to the repository on GitHub. +- Click the Fork button in the upper-right corner to create a copy of the repository under your GitHub account. + +#### Clone Your Fork + +Clone your forked repository to your local machine: + +```bash +git clone https://github.com/your-username/advanced-scene-manager.git +``` + +#### Create a New Branch + +Create a new branch for your feature or bug fix: + +```bash +git checkout -b feature-name-or-bugfix +``` + +#### Make Your Changes + +Make your changes to the code or documentation. When working on code: + +- Follow the existing coding style and conventions. +- Make sure to write unit tests for new features or bug fixes if applicable. + +For documentation changes, the documentation resides in the `docs` branch of the repository. You can switch to this branch if you're only updating the docs or contributing to new documentation. + +#### Create a Pull Request + +Open a pull request from your fork to the main repository. In the PR description, provide a clear explanation of what you've done, the issue it addresses, and any relevant details. + +- For code changes, the PR should be made against the main branch. +- For documentation changes, the PR should be made against the `docs` branch. + +This allows us to keep the documentation and code contributions in their respective branches. +Documentation changes can be submitted in the same way as code changes, by creating a PR from your fork. + +### 3. Improving Documentation + +We welcome any improvements to the documentation as well. If you spot a typo or think something could be explained better, feel free to submit a pull request with the suggested changes! + +### 4. Feature Requests + +If you have an idea for a new feature, open an issue and describe the feature in detail. Be sure to explain why you think it would be valuable for other users. If you plan to implement the feature yourself, let us know in the issue before you start so we can discuss the approach. + +## Code of Conduct + +By contributing to this project, you agree to adhere to our [Code of Conduct](./CODE_OF_CONDUCT.md). Please treat everyone with respect and kindness. + +## License + +By submitting a pull request, you agree that your contributions will be licensed under the same license as the rest of the project ([MIT License](./LICENSE)). \ No newline at end of file diff --git a/README.md b/README.md index 11437755..ee28895b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -

+

Advanced Scene Manager

+

+ Advanced Scene Manager +

+

@@ -17,703 +21,63 @@ Advanced Scene Manager

-

-Enhance your scene loading experience -

- -## Overview +## ⚑ Overview This is a Unity package to **simplify** scene operations: **load**, **unload** and **transition**. In a quick example: ```cs -// Unity Manager scene transition +AdvancedSceneManager.TransitionAsync("my-target-scene", "my-loading-scene"); +``` + +Instead of: + +```cs yield return SceneManager.LoadSceneAsync("my-loading-scene", LoadSceneMode.Additive); yield return SceneManager.LoadSceneAsync("my-target-scene", LoadSceneMode.Additive); SceneManager.SetActiveScene(SceneManager.GetSceneByName("my-target-scene")); SceneManager.UnloadSceneAsync("my-loading-scene"); SceneManager.UnloadSceneAsync("my-previous-scene"); - -// Advanced Scene Management scene transition -sceneLoader.TransitionToScene(new LoadSceneInfoName("my-target-scene"), new LoadSceneInfoName("my-loading-scene")); -``` - -You can also take advantage of these features: - -- **Unified** API for **addressable** and **non-addressable** scenes. -- **Awaitable** scene operations. -- **Modular** implementation with interfaces. -- Load, unload or transition to **multiple scenes**. - -## Migrating to `3.x` - -Refer to the [Migration Guide](https://github.com/mygamedevtools/scene-loader/wiki/Migration-Guide-3.x) at the wiki for instructions. - -## Summary - -* [Installation](#installation) - * [OpenUPM](#openupm) - * [Installing from Git](#installing-from-git) - * [Installing from tarball](#installing-from-tarball) -* [Dependencies](#dependencies) -* [Description](#description) -* [Usage](#usage) - * [The Scene Manager](#the-scene-manager) - * [Load Scene Info](#load-scene-info) - * [The Scene Loaders](#the-scene-loaders) - * [Scene Transitions](#scene-transitions) - * [Disposable and CancellationTokens](#disposable-and-cancellationtokens) -* [Practical examples](#practical-examples) - * [Creating your scene loader](#creating-your-scene-loader) - * [Loading scenes with load scene info](#loading-scenes-with-load-scene-info) -* [Creating Loading Screens](#creating-loading-screens) - * [The Loading Behavior](#the-loading-behavior) - * [The Loading States](#the-loading-states) - * [The Loading Feedback](#the-loading-feedback) - * [Loading Screen Example](#loading-screen-example) -* [Why so many interfaces?](#why-so-many-interfaces) -* [Tests](#tests) -* [Troubleshooting](#troubleshooting) - * [Error when creating an AdvancedSceneManager](#error-when-creating-an-advancedscenemanager) - * [Cannot unload a scene with a different ILoadSceneInfo](#cannot-unload-a-scene-with-a-different-iloadsceneinfo) - -## Installation - -### Open UPM - -This package is available on the [OpenUPM](https://openupm.com/packages/com.mygamedevtools.scene-loader) registry. Add the package via the [openupm-cli](https://github.com/openupm/openupm-cli): - -``` -openupm add com.mygamedevtools.scene-loader -``` - -### [Installing](https://docs.unity3d.com/Manual/upm-ui-giturl.html) from Git - -> [!NOTE] -> Requires [Git](https://git-scm.com/) installed and added to the PATH - -1. Open `Window/Package Manager`. -2. Click +. -3. Select `Install package from git URL...`. -4. Paste `https://github.com/mygamedevtools/scene-loader.git#upm` into url. -5. Click `Add`. - -### [Installing](https://docs.unity3d.com/Manual/upm-ui-tarball.html) from tarball - -1. Choose the [release](https://github.com/mygamedevtools/scene-loader/releases) you want to install and download the `com.mygamedevtools.scene-loader-.tgz` asset. -2. Open `Window/Package Manager`. -3. Click +. -4. Select `Install package from tarball...`. -5. Select the `com.mygamedevtools.scene-loader-.tgz` file you downloaded. - -## Dependencies - -The package has **no dependencies** but supports integration with some packages. -If you wish to use it with `Addressables`, `UniTask`, or `TextMeshPro`, make sure you install the packages: - -* `com.unity.addressables` >= 1.19.0 -* `com.unity.textmeshpro` >= 2.2.0 -* `com.cysharp.unitask`* >= 2.0.0 - -_*Installed via UPM or OpenUPM. Check the [package documentation](https://github.com/Cysharp/UniTask) for more details._ - -[_[back to top]_](#advanced-scene-manager) - -## Description - -Loading scenes in Unity is very simple, mostly, but when you start to deal with other systems such as [Unity Addressables](https://docs.unity3d.com/Manual/com.unity.addressables.html), it can get messy. Also, there are some common scene load scenarios that you'd usually reimplement in every project, like scene transitions. - -In this package, you'll have the possibility to standardize the scene loading process between the standard **Unity Scene Manager** and **Addressables**, while still being able to choose how to await (if you want) the operations, be it Coroutines, standard Async (through ValueTasks) or [UniTask](https://github.com/Cysharp/UniTask). - -Aside from the ordinary **Load** and **Unload** actions, the Scene Loading tools introduce the **Transition** as a new standard to control transitions between scenes with an optional intermediate "loading scene" in between. Also, starting from version `2.2` you can **Load**, **Unload**, and **Transition** to **multiple scenes** in parallel! - -[_[back to top]_](#advanced-scene-manager) - -## Usage - -Loading scenes with this package implies that the scenes **will always be loaded as Additive**. That is simply because there is no advantage in loading scenes in the **Single** load scene mode when you expect to work with multiple scenes. - -To standardize how the scenes are loaded, you'll be using `ISceneLoader`, `ISceneManager`, and `ILoadSceneInfo` objects. - -```mermaid -flowchart BT - sm([Scene Manager]) - sl([Scene Loader]) - lsi([Load Scene Info]) - - lsi -->|Load| sl - lsi -->|Unload| sl - lsi -->|Transition| sl - sl -->|Load| sm - sl -->|Unload| sm -``` - -These structures are meant to be used together. If you do not plan to use scene transitions or to have custom _awaitable_ types, you don't need to use the `ISceneLoader`. - -### The Scene Manager - -The `ISceneManager` interface exposes a few methods and events to standardize the scene load operations: - -```cs -public interface ISceneManager : IDisposable -{ - event Action ActiveSceneChanged; - event Action SceneUnloaded; - event Action SceneLoaded; - - int LoadedSceneCount { get; } - int TotalSceneCount { get; } - - void SetActiveScene(Scene scene); - - ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default); - - ValueTask LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress progress = null, CancellationToken token = default); - - ValueTask UnloadSceneAsync(ILoadSceneInfo[] sceneInfos, CancellationToken token = default); - - ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo, CancellationToken token = default); - - Scene GetActiveScene(); - - Scene GetLoadedSceneAt(int index); - - Scene GetLastLoadedScene(); - - Scene GetLoadedSceneByName(string name); -} -``` - -You can find many similarities between Unity's [SceneManager](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.html) class, and that's both for maintaining an easy learning curve as well as because some of these operations will end up calling the _Unity Scene Manager_ internally (like `SetActiveScene` for instance). -The `ILoadSceneInfo` interface is also showing up there, but we will get to that in a moment. - -The package includes the `AdvancedSceneManager` that is capable of handling both **addressable** and **non-addressable** scene operations. You can use its implementation as a reference to **build your own** Scene Manager if you need. - -The `AdvancedSceneManager` is expected to be used as a wrapper for the Unity `SceneManager`. When creating an `AdvancedSceneManager` you can decide whether you want it to manage scenes that have been loaded already or not. - -```mermaid -flowchart TB - usm([Unity Scene Manager]) - - usm --> asm([Advanced Scene Manager]) - asm --> s_a["Scene [0]"] - asm --> s_b["Scene [1]"] - asm --> s_n["Scene [n]"] -``` - -The `ISceneManager` interface defines that both `LoadSceneAsync` and `UnloadSceneAsync` methods return a `ValueTask`. -This means you can _await_ those methods if they are implemented with the _async_ keyword, or you can also subscribe to the `SceneLoaded` or `SceneUnloaded` events to receive the same `Scene` you would via the _async_ methods. - -Both these methods also receive an `ILoadSceneInfo` object. -So, instead of having multiple methods for receiving the scene's build index or the scene's name, we simply have an object instead. - -Alternatively, you can also use the `LoadScenesAsync` and `UnloadScenesAsync` methods, to perform the operations on multiple scenes in parallel. These will return a `ValueTask`. - -You can create an `AdvancedSceneManager` using three constructors: - -```cs -// Creates an advanced scene manager including all currently loaded scenes. Useful for most cases. -// Should not be called on `Awake()`, since it runs before the scene is loaded. -new AdvancedSceneManager(addLoadedScenes: true); - -// Creates an empty advanced scene manager. Useful if you are doing this before any scene loads or in a bootstrap scene. -new AdvancedSceneManager(); - -// Creates an advanced scene manager including an array of scenes. Useful when you want to include only a specific set of scenes to it. -new AdvancedSceneManager(initializationScenes: new Scene[]); -``` - -[_[back to top]_](#advanced-scene-manager) - -### Load Scene Info - -As its name states, it holds a reference to a scene to be loaded (or unloaded) and validates whether they _can_ reference a loaded scene. - -The `ILoadSceneInfo` interface simply defines: - -```cs -public interface ILoadSceneInfo -{ - LoadSceneInfoType Type { get; } - - object Reference { get; } - - bool CanBeReferenceToScene(Scene scene); -} -``` - -Since the `Reference` field can hold any type of reference, the scene manager will be responsible for deciding what to do with its value. -The `LoadSceneInfoType` is a simple enum that helps converting the `Reference` value without casting the `ILoadSceneInfo` object. -The load scene info simply holds these references, and that's why the implementations included with the package are all **readonly structs**. - -You can choose to work with **five** load scene infos: - -```mermaid -flowchart - subgraph Addressable - direction TB - assetref(LoadSceneInfoAssetReference) - address(LoadSceneInfoAddress) - end - - subgraph Unload only - scene(LoadSceneInfoScene) - end - - subgraph Non-Addressable - direction TB - name(LoadSceneInfoName) - index(LoadSceneInfoIndex) - end -``` - -* The `LoadSceneInfoName`, referencing a scene's name. -* The `LoadSceneInfoIndex`, referencing a scene's build index. -* The `LoadSceneInfoScene`, referencing a loaded scene's struct (used for unloading scenes only). -* The `LoadSceneInfoAssetReference`, referencing a scene's Addressable Asset Reference. -* The `LoadSceneInfoAddress`, referencing a scene's Addressable Address. - -You can also build your own `ILoadSceneInfo` implementation if have special needs, but that will probably require you to build a scene manager to interpret its `Reference` value as well. - -When **unloading** a scene, the `AdvancedSceneManager` will look for any of its loaded scenes that (in order of priority): -1. Have the same loaded scene handle (in the case of `LoadSceneInfoScene`). -2. Have the same `ILoadSceneInfo`. - -That means that the **preferable** way to unload scenes is through `LoadSceneInfoScene`, as it holds a **direct reference** to the target scene. -Assuming you don't have multiple scenes loaded with the same reference, it's safe to assume that the scene you want to unload is the one with the same `ILoadSceneInfo` you provided. -Except from `ILoadSceneInfoScene`, you **cannot** unload a scene with a different `ILoadSceneInfo` type. - -> [!NOTE] -> If you do have multiple scenes loaded by the same reference, unloading by its `ILoadSceneInfo` will unload the last loaded scene of that reference. - -> [!IMPORTANT] -> When unloading addressable scenes, their resources will be released by calling `Addressables.UnloadSceneAsync` internally. - -[_[back to top]_](#advanced-scene-manager) - -### The Scene Loaders - -The scene loader is an interface that you will use to load scenes in your game, as it works like a wrapper layer to the scene manager, but adds the **Scene Transition** operations. -There are two base interfaces for scene loaders: one with a reference to the `ISceneManager` that will be used, and an `async` interface to be able to `await` the load operations. - -The `ISceneLoader` interface defines: - -```cs -public interface ISceneLoader : IDisposable -{ - ISceneManager Manager { get; } - - void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); - - void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null); - - void UnloadScenes(ILoadSceneInfo[] sceneInfos); - - void UnloadScene(ILoadSceneInfo sceneInfo); - - void LoadScenes(ILoadSceneInfo[] sceneInfos, int setIndexActive = -1); - - void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false); -} -``` - -And the `ISceneLoaderAsync`: - -```cs -public interface ISceneLoaderAsync : ISceneLoader -{ - TAsyncSceneArray TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); - - TAsyncScene TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default, CancellationToken token = default); - - TAsyncSceneArray LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null, CancellationToken token = default); - - TAsyncScene LoadSceneAsync(ILoadSceneInfo sceneReference, bool setActive = false, IProgress progress = null, CancellationToken token = default); - - TAsyncSceneArray UnloadScenesAsync(ILoadSceneInfo[] sceneReferences, CancellationToken token = default); - - TAsyncScene UnloadSceneAsync(ILoadSceneInfo sceneReference, CancellationToken token = default); -} -``` - -Note that the `ISceneLoaderAsync` interface inherits from `ISceneLoader`. -The `TAsyncScene` type should return a `Scene` instance, and can be anything you mean to `await`, for example, `Task`, `ValueTask` or `UniTask`, while the `TAsyncSceneArray` should return a `Scene[]` instance, such as `Task`, `ValueTask` or `UniTask`. - -The package comes with **one** base implementations and **two** wrappers: -* The `SceneLoaderAsync`, that just like the `ISceneManager` implementations, will return `ValueTask` values. -* The `SceneLoaderCoroutine`, that uses the `SceneLoaderAsync` but returns a `WaitTask` that can be used in coroutines. -* The `SceneLoaderUniTask`, that uses the `SceneLoaderAsync` but returns `UniTask` values. - -All of them have interfaces to simplify your code: - -```cs -public interface ISceneLoaderCoroutine : ISceneLoaderAsync, WaitTask> { } - -public interface ISceneLoaderAsync : ISceneLoaderAsync, ValueTask> { } - -public interface ISceneLoaderUniTask : ISceneLoaderAsync, UniTask> { } -``` - -The `Manager` property can be used to listen to the `SceneLoaded`, `SceneUnloaded`, and `ActiveSceneChanged` events. -Both `LoadSceneAsync` and `UnloadSceneAsync` methods will simply call the `ISceneManager` equivalents, while the `LoadScene` and `UnloadScene` will do the same but without `await`. -It's important to understand that `LoadScene`, `UnloadScene`, and `TransitionToScene` will still invoke asynchronous operations, instead of blocking the execution until they are done. -You can use the `ISceneManager` events to react to the completion of those methods. - -[_[back to top]_](#advanced-scene-manager) - -### Scene Transitions - -The **Transition** is a combination of load and unload operations to effectively perform scene transitions, with or without an intermediate scene. For example, usually, if you'd want to go from scene A to scene B you would: - -1. Load the scene B. -2. Unload the scene A. - -That's only two operations, right? -What if you wanted to have a loading screen as well? -In this case, you would: - -1. Load the loading scene. -2. Load the scene B. -4. Unload the scene A. -3. Unload the loading scene. - -That's four operations now. -The `TransitionToScene` and `TransitionToSceneAsync` methods let you only provide where you want to go from the **current active scene** and if you want an intermediary scene (loading scene for example). - -Also, aside from transitioning from the current active scene, you can also use the `TransitionToSceneFromScenes` and `TransitionToSceneFromAll` alternatives: - -- `TransitionToSceneFromScenes` - unloads a given group of scenes during transition. -- `TransitionToSceneFromAll` - unloads all loaded scenes during transition. - -Just like the regular `Transition` methods, its variants also have single/multiple scene options as well as async options. - -[_[back to top]_](#advanced-scene-manager) - -### Disposable and CancellationTokens - -Both the `ISceneManager` and the `ISceneLoader` interfaces implement `IDisposable`, meaning that the Scene Managers and Loaders should implement the `Dispose()` method. -This is used with the `CancellationToken` parameters in `ISceneManager` methods to ensure that it will clear its internal data and stop async code execution during disposal. -Note that even when its methods get canceled by the `CancellationToken`, the Unity Scene Manager methods are not cancellable and therefore will continue to operate when called. - -The disposal of the implemented Scene Managers will clear its data and stop any running logic. -This is useful for shutting down the application, for example. -If you are going to manually dispose of your scene loaders or managers, prefer the following scenarios: -* You can ensure that there are no load/unload/transition operations in progress. -* You are quitting/shutting down the application or an application module. - -> [!WARNING] -> It's **not recommended** to manually cancel the `ISceneManager` operations via its `CancellationToken` parameters. -> It may result in unexpected issues such as unwanted scenes being loaded/unloaded after cancellation. - -[_[back to top]_](#advanced-scene-manager) - -## Practical Examples - -When creating your scene loader, you must first create your scene manager. -Ideally, you will not need to store the scene manager anywhere as it will be accessible through the `ISceneLoader` interface. -Also, you will need to build your scene info objects to hold references to scenes. - -### Creating your scene loader - -For the first example, let's build a scene manager and a Coroutine scene loader: - -```cs -// Make sure to add 'using MyGameDevTools.SceneLoading;' on the top of the script -ISceneManager sceneManager = new AdvancedSceneManager(); -ISceneLoader sceneLoader = new SceneLoaderCoroutine(sceneManager); -``` - -You can also define the scene loader types as their `ISceneLoaderAsync` implementations: - -```cs -ISceneManager sceneManager = new SceneManager(); - -ISceneLoaderCoroutine coroutineSceneLoader = new SceneLoaderCoroutine(sceneManager); -// Or -ISceneLoaderAsync asyncSceneLoader = new SceneLoaderAsync(sceneManager); -// Or -ISceneLoaderUniTask unitaskSceneLoader = new SceneLoaderUniTask(sceneManager); ``` -> [!NOTE] -> It is recommended that you store these object references as its interfaces to reduce coupling in your code. - -### Loading scenes with load scene info - -You'll use the load scene info objects to reference scenes. You can use these objects to define both addressable and non-addressable scenes. - -Let's assume you have included the following scenes in your **Build Settings**: - -0. Main Menu -1. Loading +## πŸš€ Features -And you have the following scenes in **addressable groups**: +- **Seamless Scene Transitions**: Transition between scenes with ease, with optional loading scenes for a smooth user experience. +- **Addressable and Non-Addressable Scene Support**: Manage both addressable and non-addressable scenes through a unified API. +- **Async/Await Support**: Fully compatible with _async/await_ for smooth, non-blocking scene operations. +- **Loading Screens**: Easily build loading screens with built-in components. +- **Modular Design** β€” Use only the components you need, fully customizable. -* Shop -* Level 1 +## πŸ“¦ Installation -You can load the scenes by using the appropriate `ILoadSceneInfo`: +Follow the full installation guide in the [documentation](https://mygamedevtools.github.io/scene-loader/docs/next/getting-started/installation). -```cs -ILoadSceneInfo mainMenuSceneInfo = new LoadSceneInfoName("Main Menu"); -ILoadSceneInfo loadingSceneInfo = new LoadSceneInfoIndex(1); -ILoadSceneInfo shopSceneInfo = new LoadSceneInfoAddress("Shop"); -// You should be able to get the scene's Asset Reference from the inspector by exposing an -// AssetReference on a MonoBehaviour or ScriptableObject. -ILoadSceneInfo levelSceneInfo = new LoadSceneInfoAssetReference(levelSceneAssetReference); - -// Loading the scene calls the same method, regardless of the load scene info type -sceneLoader.LoadScene(mainMenuSceneInfo); -sceneLoader.LoadScene(loadingSceneInfo); -sceneLoader.LoadScene(shopSceneInfo); -sceneLoader.LoadScene(levelSceneInfo); +#### Via OpenUPM: -// Or the async alternatives -await sceneLoader.LoadSceneAsync(mainMenuSceneInfo); -await sceneLoader.LoadSceneAsync(loadingSceneInfo); -await sceneLoader.LoadSceneAsync(shopSceneInfo); -await sceneLoader.LoadSceneAsync(levelSceneInfo); +```bash +# Install via OpenUPM +openupm add com.mygamedevtools.scenemanager ``` -The same logic applies for unloading scenes. Additionally, you can use the `LoadSceneInfoScene` to unload non-addressable scenes using the scene returned from `ISceneLoaderAsync.LoadSceneAsync`. - -```cs -ILoadSceneInfo mainMenuSceneInfo = new LoadSceneInfoName("Main Menu"); -ILoadSceneInfo loadingSceneInfo = new LoadSceneInfoIndex(1); -ILoadSceneInfo shopSceneInfo = new LoadSceneInfoAddress("Shop"); - -Scene levelScene = await sceneLoader.LoadSceneAsync(LoadSceneInfoAssetReference(levelSceneAssetReference)); -ILoadSceneInfo levelSceneInfo = new LoadSceneInfoScene(levelScene); - -sceneLoader.UnloadScene(mainMenuSceneInfo); -sceneLoader.UnloadScene(loadingSceneInfo); -sceneLoader.UnloadScene(shopSceneInfo); -sceneLoader.LoadScene(levelSceneInfo); - -// Or the async alternatives -await sceneLoader.UnloadSceneAsync(mainMenuSceneInfo); -await sceneLoader.UnloadSceneAsync(loadingSceneInfo); -await sceneLoader.UnloadSceneAsync(shopSceneInfo); -await sceneLoader.LoadSceneAsync(levelSceneInfo); -``` +#### Via Git URL: -Instead of using the async method, you can also register to the `ISceneManager.SceneLoaded` event: +Add this to your Packages/manifest.json: -```cs -sceneLoader.Manager.SceneLoaded += loadedScene => +```json { - ILoadSceneInfo loadedSceneInfo = new LoadSceneInfoScene(loadedScene); - sceneLoader.UnloadScene(loadedSceneInfo); + "dependencies": { + "com.mygamedevtools.scenemanager": "https://github.com/MyGameDevTools/SceneManager.git" + } } ``` -For transitions, you can combine different load scene info objects on the transition method: - -```cs -ILoadSceneInfo stageSceneInfo = new LoadSceneInfoName("Stage 1"); -ILoadSceneInfo loadingSceneInfo = new LoadSceneInfoIndex(1); - -sceneLoader.TransitionToScene(stageSceneInfo, loadingSceneInfo); - -// Or the async alternative -await sceneLoader.TransitionToSceneAsync(stageSceneInfo, loadingSceneInfo); -``` - -Whenever you need to perform scene operations on multiple scenes, you can also build `ILoadSceneInfo` arrays: - -```cs -ILoadSceneInfo[] sceneInfoGroup = new ILoadSceneInfo[] -{ - new LoadSceneInfoName("Main Menu"), - new LoadSceneInfoIndex(1), - new LoadSceneInfoAddress("Shop"), - new LoadSceneInfoAssetReference(levelSceneAssetReference) -} - -// Load -sceneLoader.LoadScenes(sceneInfoGroup); -// Unload -sceneLoader.UnloadScenes(sceneInfoGroup); -// Transition -// For multiple scenes, you must provide which scene you want to be the active scene by -// providing its index in the array. -sceneLoader.TransitionToScenes(sceneInfoGroup, 0); - -// Awaitable alternatives -await sceneLoader.LoadScenesAsync(sceneInfoGroup); -await sceneLoader.UnloadScenesAsync(sceneInfoGroup); -await sceneLoader.TransitionToScenesAsync(sceneInfoGroup, 0); -``` - -[_[back to top]_](#advanced-scene-manager) +## πŸ“š Documentation -## Creating Loading Screens - -During scene transitions, you have the option to provide an intermediate scene that can be used as loading screen. -This could be an animated splash screen or a loading progress bar, for example. -This package provides implementations to help you build your loading screens faster. - -### The Loading Behavior - -The Loading Behavior is a [MonoBehaviour] component, which you can attach to Unity [GameObjects], that receives the progress value from the scene manager. -You **need** to add a `LoadingBehavior` component to a [GameObject] in your loading scene to be able to display scene loading feedback. -It exposes its `LoadingProgress` instance, which you can use to listen to the loading events: - -```cs -public class LoadingProgress : IProgress -{ - public event LoadingStateChangeDelegate StateChanged; - public event SceneLoadProgressDelegate Progressed; - - public LoadingState State { get; } -} -``` - -The `StateChanged` event expects a `LoadingState` parameter, to report the current state of the scene loading operation, and you can query the active state at any time by retrieving the value in the `State` property. -The `Progressed` event expects a `float` parameter, ranging from 0 to 1 to report the progress of the scene loading operation. - -Back to the `LoadingBehavior`, it has a few options you can set on the Unity [Inspector](https://docs.unity3d.com/Manual/UsingTheInspector.html): - -* **Wait For Scripted Start**: enable if the loading screen will have a **transition in** effect, such as a fade in. -* **Wait For Scripted End**: enable if the loading screen will have a **transition out** effect, such as a fade out. - -### The Loading States - -The loading scene transition can be customized to delay some parts of the operation to deliver a smooth visual experience for the user. -That means we can fade in/out or use other transition effects and wait for them to complete to continue the scene loading operations. -The `LoadingState` enum reflects those states: - -```cs -public enum LoadingState -{ - WaitingToStart, - Loading, - TargetSceneLoaded, - TransitionComplete -} -``` - -These states are ordered, which means that the first state will always be `WaitingToStart` and the last will be `TransitionComplete`. -They mean: - -* `WaitingToStart`: it's waiting for a trigger to allow the scene loading to start loading. This could be if the loading scene does not instantly appear, otherwise causing weird experiences with things simply disappearing. You can transition the loading screen with a fade in or a similar effect, for example. -* `Loading`: the loading screen transition has occurred and the scene loading operation is running. During this state, the `LoadingProgress` instance will receive the progress value from the scene manager. -* `TargetSceneLoaded`: the target scene has been loaded, but the loading screen is still displaying. You can use this state to transition the loading screen out, such as a fade out or a similar effect. -* `TransitionComplete`: the target scene has been loaded and the loading screen is already out of the way. Shortly after this state, the loading scene will be unloaded. - -### The Loading Feedback - -At this point, you should already have your loading scene with a `LoadingBehavior` attached to one of your [GameObjects]. -Now you can also add some other components to display the loading progress feedback. -This package comes with **three** feedbacks: - -* `LoadingFeedbackSlider`: attach on an [UI Slider] to display the loading progress feedback as a progress bar. -* `LoadingFeedbackTextMeshPro`: attach on an [UI Text Mesh Pro] to display the loading progress feedback as text normalized from 0 to 100. -* `LoadingFeedbackText` _(also known as Legacy)_: attach on an [UI Legacy Text](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-Text.html) to display the loading progress feedback as text normalized from 0 to 100. - -You can use a combination of these feedback components in the loading scene. -Remember to assign the `LoadingBehavior` field of these components to the `LoadingBehavior` component you created before. - -Another feedback that you could make is a **fade in/out** effect. -The `LoadingFader` component does just that. -Add it to an [UI CanvasGroup] [GameObject] to control the group's alpha value during the visual transitions. -You can also set the fade time and customize the fade in/out animation curves to suit your preference. - -To use the `LoadingFader` effectively, you must **enable** both `WaitForScriptedStart` and `WaitForScriptedEnd` toggles in your `LoadingBehavior` component. - -### Loading Screen Example - -Take the following loading screen scene hierarchy as an example: - -* Canvas - ([Canvas](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-Canvas.html), [CanvasScaler](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-CanvasScaler.html), `LoadingBehavior`) - * Group - ([CanvasGroup], `LoadingFader`) - * Background - ([Image](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-Image.html)) - * Text_Message - ([TextMeshProUGUI]) - * Slider_Progress - ([Slider], `LoadingFeedbackSlider`) - * Text_Progress - ([TextMeshProUGUI], `LoadingFeedbackTextMeshPro`) - -By having this hierarchy in your loading scene, it would be able to fade in/out and display both the loading progress bar and loading progress text feedback. -As this scene has the `LoadingFader` component, remember to enable both `WaitForScriptedStart` and `WaitForScriptedEnd` toggles in the `LoadingBehavior` component. -Also, if you're not using an addressable scene manager, enable the `ReducedLoadRatio` toggle. - -You can test this scene by passing its `ILoadSceneInfo` reference as the `intermediateSceneInfo` in an `ISceneLoader.TransitionToScene` method. - -[_[back to top]_](#advanced-scene-manager) - -## Why so many interfaces? - -The idea behind the interfaces is first to decouple things and second to allow you to build your custom implementations if you require something very different from the included content. -Sometimes projects require very specific implementations, and instead of making the system extremely complex and detailed, I'd rather have it broken into many different pieces that you can replace to fit with whatever works best for you. - -## Tests - -This package includes tests to assert most use cases of the Scene Managers and Scene Loaders. -The tests do not have any effect on a runtime build of the game, they only mean to work in a development environment. - -[_[back to top]_](#advanced-scene-manager) - -## Troubleshooting - -### Error when creating an `AdvancedSceneManager` - -When creating an `AdvancedSceneManager` passing a `true` value to its constructor, as `new AdvancedSceneManager(true)`, it attempts to add all loaded scenes to its list of tracked scenes. -However, if you called that during `Awake()`, you might see the error: - -``` -ArgumentException: Attempted to get an {nameof(ISceneData)} through an invalid or unloaded scene. -``` - -This error is thrown because during `Awake()` the scene is not fully loaded and cannot be added to the list of tracked scenes. - - -Move your call to `Start()` instead. - -### Cannot unload a scene with a different `ILoadSceneInfo` - -In a case where you have loaded a scene via one type of `ILoadSceneInfo`, you can only unload it by using the same type or explicitly a `LoadSceneInfoScene`. For example: - -```cs -ILoadSceneInfo nameInfo = new LoadSceneInfoName("MyScene"); -ILoadSceneInfo indexInfo = new LoadSceneInfoIndex(3); - -sceneManager.LoadSceneAsync(nameInfo); - -// You **cannot** do this: -sceneManager.UnloadSceneAsync(indexInfo); - -// But you can do this: -sceneManager.UnoadSceneAsync(nameInfo); - -// Or, build a `LoadSceneInfoScene`. -// Alternatives: GetLoadedSceneByName(name), GetLoadedSceneAt(index), GetLastLoadedScene() or GetActiveScene() -ILoadSceneInfo sceneInfo = sceneManager.GetLoadedSceneByName("MyScene"); -sceneManager.UnloadSceneAsync(sceneInfo); -``` - -Sometimes this issue can also be avoided by performing a scene transition. If you're trying to unload the active scene to transition between scenes, you can execute the transition through the scene manager and let it handle the internal complexity. For example: - -```cs -// Instead of unloading the source scene directly: -sceneManager.LoadSceneAsync(targetSceneInfo) -sceneManager.UnloadSceneAsync(sourceSceneInfo); - -// Perform a scene transition: -sceneManager.TransitionToScene(targetSceneInfo); -``` +The full API reference, examples, and tutorials are available in the [official documentation](https://mygamedevtools.github.io/scene-loader/). -[_[back to top]_](#advanced-scene-manager) +## 🀝 Contributing ---- +We welcome contributions! Please check our [contribution guidelines](./CONTRIBUTING.md). -Don't hesitate to create [issues](https://github.com/mygamedevtools/scene-loader/issues) for suggestions and bugs. Have fun! +## πŸ“„ License -[MonoBehaviour]: https://docs.unity3d.com/Manual/class-MonoBehaviour.html -[MonoBehaviours]: https://docs.unity3d.com/Manual/class-MonoBehaviour.html -[ScriptableObject]: https://docs.unity3d.com/Manual/class-ScriptableObject.html -[GameObject]: https://docs.unity3d.com/Manual/class-GameObject.html -[GameObjects]: https://docs.unity3d.com/Manual/class-GameObject.html -[UI Text Mesh Pro]: https://docs.unity3d.com/Packages/com.unity.textmeshpro@3.0/api/TMPro.TextMeshProUGUI.html -[TextMeshProUGUI]: https://docs.unity3d.com/Packages/com.unity.textmeshpro@3.0/api/TMPro.TextMeshProUGUI.html -[UI Slider]: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-Slider.html -[Slider]: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-Slider.html -[UI Canvas Group]: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-CanvasGroup.html -[CanvasGroup]: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/class-CanvasGroup.html +This project is licensed under the [MIT License](./LICENSE). \ No newline at end of file diff --git a/docs/img/banner.jpg b/docs/img/banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..005854b8bef92613b225f4ec4af71433ab7da8ab GIT binary patch literal 86244 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�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 Date: Sun, 2 Mar 2025 00:42:16 -0300 Subject: [PATCH 29/53] improve readme --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index ee28895b..d2608e1c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -

-Advanced Scene Manager -

-

Advanced Scene Manager

@@ -72,7 +68,7 @@ Add this to your Packages/manifest.json: ## πŸ“š Documentation -The full API reference, examples, and tutorials are available in the [official documentation](https://mygamedevtools.github.io/scene-loader/). +The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://mygamedevtools.github.io/scene-loader/). ## 🀝 Contributing From f20ab0ec2cd79ae01a140264653f85d06dc10fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sun, 2 Mar 2025 00:43:59 -0300 Subject: [PATCH 30/53] fix wording in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2608e1c..3c8a7ee0 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ ## ⚑ Overview -This is a Unity package to **simplify** scene operations: **load**, **unload** and **transition**. In a quick example: +The **Advanced Scene Manager** is a Unity package to **simplify** scene operations: **load**, **unload** and **transition**. In a quick example: ```cs AdvancedSceneManager.TransitionAsync("my-target-scene", "my-loading-scene"); From a7fa1fb2a25697839b40a55ccec441e91d1d0149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 00:54:03 -0300 Subject: [PATCH 31/53] update unity to 6000.0.40f1 --- Packages/packages-lock.json | 4 ++-- ProjectSettings/EditorSettings.asset | 30 ++++++++++++++++++++++------ ProjectSettings/ProjectVersion.txt | 4 ++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 8e6c3d9d..3a155ecb 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -44,7 +44,7 @@ "com.unity.ide.rider": "3.0.31", "com.unity.editorcoroutines": "1.0.0", "com.unity.performance.profile-analyzer": "1.2.3", - "com.unity.test-framework": "1.4.5", + "com.unity.test-framework": "1.4.6", "com.unity.testtools.codecoverage": "1.2.6" } }, @@ -95,7 +95,7 @@ "url": "https://packages.unity.com" }, "com.unity.test-framework": { - "version": "1.4.5", + "version": "1.4.6", "depth": 1, "source": "registry", "dependencies": { diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset index 1e44a0a1..13bda89f 100644 --- a/ProjectSettings/EditorSettings.asset +++ b/ProjectSettings/EditorSettings.asset @@ -3,28 +3,46 @@ --- !u!159 &1 EditorSettings: m_ObjectHideFlags: 0 - serializedVersion: 11 - m_ExternalVersionControlSupport: Visible Meta Files + serializedVersion: 13 m_SerializationMode: 2 m_LineEndingsForNewScripts: 0 m_DefaultBehaviorMode: 0 m_PrefabRegularEnvironment: {fileID: 0} m_PrefabUIEnvironment: {fileID: 0} m_SpritePackerMode: 0 + m_SpritePackerCacheSize: 10 m_SpritePackerPaddingPower: 1 + m_Bc7TextureCompressor: 0 m_EtcTextureCompressorBehavior: 1 m_EtcTextureFastCompressor: 1 m_EtcTextureNormalCompressor: 2 m_EtcTextureBestCompressor: 4 m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref m_ProjectGenerationRootNamespace: - m_CollabEditorSettings: - inProgressEnabled: 1 m_EnableTextureStreamingInEditMode: 1 m_EnableTextureStreamingInPlayMode: 1 + m_EnableEditorAsyncCPUTextureLoading: 0 m_AsyncShaderCompilation: 1 - m_EnterPlayModeOptionsEnabled: 0 + m_PrefabModeAllowAutoSave: 1 + m_EnterPlayModeOptionsEnabled: 1 m_EnterPlayModeOptions: 3 - m_ShowLightmapResolutionOverlay: 1 + m_GameObjectNamingDigits: 1 + m_GameObjectNamingScheme: 0 + m_AssetNamingUsesSpace: 1 + m_InspectorUseIMGUIDefaultInspector: 0 m_UseLegacyProbeSampleCount: 0 m_SerializeInlineMappingsOnOneLine: 1 + m_DisableCookiesInLightmapper: 0 + m_AssetPipelineMode: 1 + m_RefreshImportMode: 0 + m_CacheServerMode: 0 + m_CacheServerEndpoint: + m_CacheServerNamespacePrefix: default + m_CacheServerEnableDownload: 1 + m_CacheServerEnableUpload: 1 + m_CacheServerEnableAuth: 0 + m_CacheServerEnableTls: 0 + m_CacheServerValidationMode: 2 + m_CacheServerDownloadBatchSize: 128 + m_EnableEnlightenBakedGI: 0 + m_ReferencedClipsExactNaming: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index d5ce6c02..a1aff48d 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.33f1 -m_EditorVersionWithRevision: 6000.0.33f1 (433b0a79340b) +m_EditorVersion: 6000.0.40f1 +m_EditorVersionWithRevision: 6000.0.40f1 (157d81624ddf) From 35d288b42cbfb7bfef848ee7d0260a27bb897420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 00:54:29 -0300 Subject: [PATCH 32/53] fix: add loading scene sample --- .../Samples.meta | 8 + .../Samples/LoadingSceneExamples.meta | 8 + .../LoadingSceneExamples/Animations.meta | 8 + .../Animations/Loading_Animated.meta | 8 + .../AC_LoadingAnimated.controller | 211 ++ .../AC_LoadingAnimated.controller.meta | 8 + .../LoadingAnimated@Close.anim | 198 ++ .../LoadingAnimated@Close.anim.meta | 8 + .../LoadingAnimated@Idle_Opened.anim | 191 ++ .../LoadingAnimated@Idle_Opened.anim.meta | 8 + .../LoadingAnimated@Open.anim | 198 ++ .../LoadingAnimated@Open.anim.meta | 8 + .../LoadingSceneExamples/Materials.meta | 8 + .../Materials/M_Barrel.mat | 86 + .../Materials/M_Barrel.mat.meta | 8 + .../LoadingSceneExamples/Materials/M_Box.mat | 86 + .../Materials/M_Box.mat.meta | 8 + .../Materials/M_Floor.mat | 86 + .../Materials/M_Floor.mat.meta | 8 + .../Materials/M_Night.mat | 92 + .../Materials/M_Night.mat.meta | 8 + .../LoadingSceneExamples/Materials/M_Wall.mat | 86 + .../Materials/M_Wall.mat.meta | 8 + .../Materials/M_Wall_A.mat | 86 + .../Materials/M_Wall_A.mat.meta | 8 + .../Materials/M_Wall_B.mat | 86 + .../Materials/M_Wall_B.mat.meta | 8 + .../Samples/LoadingSceneExamples/Scenes.meta | 8 + .../Scenes/Loading_Animated.unity | 678 +++++ .../Scenes/Loading_Animated.unity.meta | 7 + .../Scenes/Loading_Custom.unity | 833 +++++ .../Scenes/Loading_Custom.unity.meta | 7 + .../Scenes/Loading_Fade.unity | 1121 +++++++ .../Scenes/Loading_Fade.unity.meta | 7 + .../LoadingSceneExamples/Scenes/SceneA.unity | 2627 ++++++++++++++++ .../Scenes/SceneA.unity.meta | 7 + .../LoadingSceneExamples/Scenes/SceneB.meta | 8 + .../LoadingSceneExamples/Scenes/SceneB.unity | 2693 +++++++++++++++++ .../Scenes/SceneB.unity.meta | 7 + .../Scenes/SceneB/LightingData.asset | Bin 0 -> 17777 bytes .../Scenes/SceneB/LightingData.asset.meta | 8 + .../Scenes/SceneB/ReflectionProbe-0.exr | Bin 0 -> 186972 bytes .../Scenes/SceneB/ReflectionProbe-0.exr.meta | 117 + .../Scenes/SceneB/ReflectionProbe-1.exr | Bin 0 -> 179115 bytes .../Scenes/SceneB/ReflectionProbe-1.exr.meta | 117 + .../Samples/LoadingSceneExamples/Scripts.meta | 8 + .../LoadingSceneExamples/Scripts/Editor.meta | 8 + .../Editor/Sample.LoadingScene.Editor.asmdef | 3 + .../Sample.LoadingScene.Editor.asmdef.meta | 7 + .../Editor/SceneBuildSettingsEditor.cs | 100 + .../Editor/SceneBuildSettingsEditor.cs.meta | 2 + .../LoadingSceneExamples/Scripts/Runtime.meta | 8 + .../Scripts/Runtime/AnimatedTrigger.cs | 75 + .../Scripts/Runtime/AnimatedTrigger.cs.meta | 2 + .../Runtime/LoadingFeedbackImageFill.cs | 38 + .../Runtime/LoadingFeedbackImageFill.cs.meta | 2 + .../Runtime/Sample.LoadingScene.asmdef | 16 + .../Runtime/Sample.LoadingScene.asmdef.meta | 7 + .../Scripts/Runtime/SceneTransitionTrigger.cs | 29 + .../Runtime/SceneTransitionTrigger.cs.meta | 2 + .../Samples/LoadingSceneExamples/Sprites.meta | 8 + .../LoadingSceneExamples/Sprites/circle.png | Bin 0 -> 41519 bytes .../Sprites/circle.png.meta | 117 + .../Sprites/triangle_left.png | Bin 0 -> 27381 bytes .../Sprites/triangle_left.png.meta | 117 + .../Sprites/triangle_right.png | Bin 0 -> 27512 bytes .../Sprites/triangle_right.png.meta | 117 + .../package.json | 9 +- 68 files changed, 10453 insertions(+), 1 deletion(-) create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/LightingData.asset create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/LightingData.asset.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-0.exr create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-0.exr.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Samples.meta b/Packages/com.mygamedevtools.scene-loader/Samples.meta new file mode 100644 index 00000000..0145eef9 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5b738b42e1c3b1e49a5ef19b61ab1dbc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples.meta new file mode 100644 index 00000000..ade1f30a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 574ec9c3c6b56cc428f3d5835792b527 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations.meta new file mode 100644 index 00000000..068dd27f --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b3337ce63c299a149aa0769c2d973f1f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated.meta new file mode 100644 index 00000000..00bbb5c9 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c6ccf37b0b034444803177e80e2ccf4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller new file mode 100644 index 00000000..7daa33a6 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller @@ -0,0 +1,211 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1102 &-8902521949079758999 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Close + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: 4225177938088309335} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: 7400000, guid: c65db23636309ad42add4cfc8790375c, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!1102 &-5945705694347017557 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Idle Opened + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: 8348283624186510602} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: 7400000, guid: a2bbef94a5f31e5418bf4f78cb08a7da, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!1107 &-5840351763902026485 +AnimatorStateMachine: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Base Layer + m_ChildStates: + - serializedVersion: 1 + m_State: {fileID: -5945705694347017557} + m_Position: {x: 30, y: 170, z: 0} + - serializedVersion: 1 + m_State: {fileID: -8902521949079758999} + m_Position: {x: 30, y: 230, z: 0} + - serializedVersion: 1 + m_State: {fileID: 6396143234028859413} + m_Position: {x: 30, y: 290, z: 0} + m_ChildStateMachines: [] + m_AnyStateTransitions: [] + m_EntryTransitions: [] + m_StateMachineTransitions: {} + m_StateMachineBehaviours: [] + m_AnyStatePosition: {x: 260, y: 230, z: 0} + m_EntryPosition: {x: 50, y: 120, z: 0} + m_ExitPosition: {x: 50, y: 350, z: 0} + m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} + m_DefaultState: {fileID: -5945705694347017557} +--- !u!91 &9100000 +AnimatorController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: AC_LoadingAnimated + serializedVersion: 5 + m_AnimatorParameters: + - m_Name: IsOpen + m_Type: 4 + m_DefaultFloat: 0 + m_DefaultInt: 0 + m_DefaultBool: 1 + m_Controller: {fileID: 9100000} + m_AnimatorLayers: + - serializedVersion: 5 + m_Name: Base Layer + m_StateMachine: {fileID: -5840351763902026485} + m_Mask: {fileID: 0} + m_Motions: [] + m_Behaviours: [] + m_BlendingMode: 0 + m_SyncedLayerIndex: -1 + m_DefaultWeight: 0 + m_IKPass: 0 + m_SyncedLayerAffectsTiming: 0 + m_Controller: {fileID: 9100000} +--- !u!1101 &1637934215790774671 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: [] + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 0} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 1 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0 + m_ExitTime: 1 + m_HasExitTime: 1 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 +--- !u!1101 &4225177938088309335 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: IsOpen + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 6396143234028859413} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0 + m_ExitTime: 0.5 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 +--- !u!1102 &6396143234028859413 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Open + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: 1637934215790774671} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: 7400000, guid: 81e15d35e1c54a4498be0e2469bbd354, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!1101 &8348283624186510602 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 2 + m_ConditionEvent: IsOpen + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -8902521949079758999} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0 + m_ExitTime: 0 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller.meta new file mode 100644 index 00000000..c265338d --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/AC_LoadingAnimated.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 400552a45bd9bf845a6dc65a0b80efe7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim new file mode 100644 index 00000000..56cf1786 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim @@ -0,0 +1,198 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LoadingAnimated@Close + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.081082456 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.07207202 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_PPtrCurves: [] + m_SampleRate: 60 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: + - serializedVersion: 2 + path: 856533603 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 592561873 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0.5 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 0 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.081082456 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.5 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.07207202 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: + - time: 0.5 + functionName: InTransitionTrigger + data: + objectReferenceParameter: {fileID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim.meta new file mode 100644 index 00000000..16d3dede --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Close.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c65db23636309ad42add4cfc8790375c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim new file mode 100644 index 00000000..34dddcd4 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim @@ -0,0 +1,191 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LoadingAnimated@Idle_Opened + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.016666668 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.016666668 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_PPtrCurves: [] + m_SampleRate: 60 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: + - serializedVersion: 2 + path: 856533603 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 592561873 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0.016666668 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 1 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.016666668 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 0.016666668 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim.meta new file mode 100644 index 00000000..f245a3c9 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Idle_Opened.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2bbef94a5f31e5418bf4f78cb08a7da +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim new file mode 100644 index 00000000..10055d07 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim @@ -0,0 +1,198 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: LoadingAnimated@Open + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.081082456 + - serializedVersion: 3 + time: 0.5 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.07207202 + - serializedVersion: 3 + time: 0.5 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_PPtrCurves: [] + m_SampleRate: 60 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: + - serializedVersion: 2 + path: 856533603 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 592561873 + attribute: 1460864421 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0.5 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 0 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.081082456 + - serializedVersion: 3 + time: 0.5 + value: -1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Left + classID: 224 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.07207202 + - serializedVersion: 3 + time: 0.5 + value: 1140 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.x + path: Panel_Right + classID: 224 + script: {fileID: 0} + flags: 0 + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: + - time: 0.5 + functionName: OutTransitionTrigger + data: + objectReferenceParameter: {fileID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim.meta new file mode 100644 index 00000000..95fd065a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Animations/Loading_Animated/LoadingAnimated@Open.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81e15d35e1c54a4498be0e2469bbd354 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials.meta new file mode 100644 index 00000000..9bef01c0 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41c7267c0bf76d147ae0e2988ffd7a7d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat new file mode 100644 index 00000000..777e4e08 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Barrel + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.75 + - _GlossyReflections: 0 + - _Metallic: 0.8 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.8584906, g: 0.25597787, b: 0.20652366, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat.meta new file mode 100644 index 00000000..c900f6fe --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Barrel.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c7fa4d47884e65f4da8abc72e5dcb96a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat new file mode 100644 index 00000000..02870cc8 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Box + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.05 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.675, g: 0.45245868, b: 0.22004999, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat.meta new file mode 100644 index 00000000..941308cc --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Box.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2cae1f6280e4f78409eeb7d01a1ab00b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat new file mode 100644 index 00000000..22a58f77 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Floor + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.05 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.254717, g: 0.254717, b: 0.254717, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat.meta new file mode 100644 index 00000000..8fd8f123 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Floor.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3914cfcf95c8d774eaa76b1757b28bcf +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat new file mode 100644 index 00000000..e5613227 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat @@ -0,0 +1,92 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Night + m_Shader: {fileID: 106, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _SUNDISK_HIGH_QUALITY + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AtmosphereThickness: 3.5 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _Exposure: 0.5 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SunDisk: 2 + - _SunSize: 0.04 + - _SunSizeConvergence: 5 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _GroundColor: {r: 0.369, g: 0.349, b: 0.341, a: 1} + - _SkyTint: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat.meta new file mode 100644 index 00000000..eec3dc97 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Night.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 162b48961309d454ba4e0118c646ecca +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat new file mode 100644 index 00000000..35edb4c3 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Wall + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.05 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.85, g: 0.85, b: 0.85, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat.meta new file mode 100644 index 00000000..af4b7a51 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cdeb3ffd55a633049ae8eb687ee518f1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat new file mode 100644 index 00000000..ed8626e8 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Wall_A + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.05 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0, g: 0.32941177, b: 0.64, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat.meta new file mode 100644 index 00000000..4306376a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_A.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 24fbfe448e3667a48af7eddd9ccffbf6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat new file mode 100644 index 00000000..424e55e3 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat @@ -0,0 +1,86 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: M_Wall_B + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _GLOSSYREFLECTIONS_OFF + - _SPECULARHIGHLIGHTS_OFF + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.05 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.23921569, g: 0.72156864, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat.meta new file mode 100644 index 00000000..9c920385 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Materials/M_Wall_B.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 33b2ce6d53c5e8947a553e4540a27b13 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes.meta new file mode 100644 index 00000000..48e03c14 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0305f3c245e40c54eaed1031e3027009 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity new file mode 100644 index 00000000..8de01d4d --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity @@ -0,0 +1,678 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &452422791 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 452422792} + - component: {fileID: 452422794} + - component: {fileID: 452422793} + m_Layer: 5 + m_Name: Panel_Right + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &452422792 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452422791} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1013596372} + - {fileID: 825098956} + m_Father: {fileID: 1076835549} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 780, y: 0} + m_Pivot: {x: 1, y: 0.5} +--- !u!114 &452422793 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452422791} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23921569, g: 0.72156864, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &452422794 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 452422791} + m_CullTransparentMesh: 1 +--- !u!1 &825098955 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 825098956} + - component: {fileID: 825098959} + - component: {fileID: 825098958} + - component: {fileID: 825098957} + m_Layer: 5 + m_Name: Text_Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &825098956 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825098955} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 452422792} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: -48, y: 48} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 1, y: 0} +--- !u!114 &825098957 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825098955} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &825098958 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825098955} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 48 + m_FontStyle: 3 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 48 + m_Alignment: 2 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Now Loading... +--- !u!222 &825098959 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 825098955} + m_CullTransparentMesh: 1 +--- !u!1 &992510978 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 992510979} + - component: {fileID: 992510981} + - component: {fileID: 992510980} + m_Layer: 5 + m_Name: Triangle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &992510979 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 992510978} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1676133489} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 360, y: 0} + m_Pivot: {x: 0, y: 0.5} +--- !u!114 &992510980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 992510978} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0.32941177, b: 0.6392157, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 79a6fde258d0ee447a881166e6ecadea, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &992510981 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 992510978} + m_CullTransparentMesh: 1 +--- !u!1 &1013596371 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1013596372} + - component: {fileID: 1013596374} + - component: {fileID: 1013596373} + m_Layer: 5 + m_Name: Triangle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1013596372 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1013596371} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 452422792} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 360, y: 0} + m_Pivot: {x: 1, y: 0.5} +--- !u!114 &1013596373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1013596371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23921569, g: 0.72156864, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 893a1f4488cb89d4c84df8bece4201be, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1013596374 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1013596371} + m_CullTransparentMesh: 1 +--- !u!1 &1076835545 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1076835549} + - component: {fileID: 1076835548} + - component: {fileID: 1076835547} + - component: {fileID: 1076835546} + - component: {fileID: 1076835550} + - component: {fileID: 1076835551} + - component: {fileID: 1076835552} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1076835546 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1076835547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 2 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &1076835548 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 10 + m_TargetDisplay: 0 +--- !u!224 &1076835549 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1676133489} + - {fileID: 452422792} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &1076835550 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c075a502fec352044ac850b2ac556afe, type: 3} + m_Name: + m_EditorClassIdentifier: + waitForScriptedStart: 1 + waitForScriptedEnd: 1 +--- !u!95 &1076835551 +Animator: + serializedVersion: 7 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 400552a45bd9bf845a6dc65a0b80efe7, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_AnimatePhysics: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!114 &1076835552 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1076835545} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 86412405a5b304e44bcea539864a36ab, type: 3} + m_Name: + m_EditorClassIdentifier: + _loadingBehavior: {fileID: 1076835550} +--- !u!1 &1676133488 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1676133489} + - component: {fileID: 1676133491} + - component: {fileID: 1676133490} + m_Layer: 5 + m_Name: Panel_Left + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1676133489 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1676133488} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 992510979} + m_Father: {fileID: 1076835549} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 780, y: 0} + m_Pivot: {x: 0, y: 0.5} +--- !u!114 &1676133490 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1676133488} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0.32941177, b: 0.6392157, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1676133491 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1676133488} + m_CullTransparentMesh: 1 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1076835549} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity.meta new file mode 100644 index 00000000..16aa8969 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Animated.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3dac14043db22ff4899bdb4d66c2d448 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity new file mode 100644 index 00000000..51c26f7b --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity @@ -0,0 +1,833 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &203667518 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 203667522} + - component: {fileID: 203667521} + - component: {fileID: 203667520} + - component: {fileID: 203667519} + - component: {fileID: 203667523} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &203667519 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203667518} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &203667520 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203667518} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 2 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &203667521 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203667518} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 10 + m_TargetDisplay: 0 +--- !u!224 &203667522 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203667518} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 531249905} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &203667523 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203667518} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c075a502fec352044ac850b2ac556afe, type: 3} + m_Name: + m_EditorClassIdentifier: + waitForScriptedStart: 1 + waitForScriptedEnd: 1 +--- !u!1 &350044371 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 350044372} + - component: {fileID: 350044374} + - component: {fileID: 350044373} + - component: {fileID: 350044375} + m_Layer: 5 + m_Name: Clock + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &350044372 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350044371} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1773217052} + - {fileID: 1993542208} + m_Father: {fileID: 531249905} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: -48, y: 48} + m_SizeDelta: {x: 192, y: 192} + m_Pivot: {x: 1, y: 0} +--- !u!114 &350044373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350044371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23921569, g: 0.72156864, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 0e631649835abae4fad9a729f45bcb81, type: 3} + m_Type: 3 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 2 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &350044374 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350044371} + m_CullTransparentMesh: 1 +--- !u!114 &350044375 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 350044371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ea86e1e214840ef498f79747dcb26163, type: 3} + m_Name: + m_EditorClassIdentifier: + _loadingBehavior: {fileID: 203667523} +--- !u!1 &531249904 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 531249905} + - component: {fileID: 531249907} + - component: {fileID: 531249906} + m_Layer: 5 + m_Name: Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &531249905 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 531249904} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1900434454} + - {fileID: 350044372} + m_Father: {fileID: 203667522} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &531249906 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 531249904} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3d268aa56fe5044468ac1c18858ab207, type: 3} + m_Name: + m_EditorClassIdentifier: + loadingBehavior: {fileID: 203667523} + fadeTime: 1 + _fadeOutCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _fadeInCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!225 &531249907 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 531249904} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 +--- !u!1 &865714439 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 865714440} + - component: {fileID: 865714442} + - component: {fileID: 865714441} + m_Layer: 5 + m_Name: Text_Symbol + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &865714440 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 865714439} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1993542208} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &865714441 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 865714439} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 48 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 48 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '%' +--- !u!222 &865714442 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 865714439} + m_CullTransparentMesh: 1 +--- !u!1 &997970085 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 997970086} + - component: {fileID: 997970088} + - component: {fileID: 997970087} + - component: {fileID: 997970089} + m_Layer: 5 + m_Name: Text_Value + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &997970086 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 997970085} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1993542208} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &997970087 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 997970085} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 48 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 4 + m_MaxSize: 48 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 00 +--- !u!222 &997970088 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 997970085} + m_CullTransparentMesh: 1 +--- !u!114 &997970089 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 997970085} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 20a0de9ed473d5f4cbda13658d314b06, type: 3} + m_Name: + m_EditorClassIdentifier: + loadingBehavior: {fileID: 203667523} +--- !u!1 &1773217051 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1773217052} + - component: {fileID: 1773217054} + - component: {fileID: 1773217053} + m_Layer: 5 + m_Name: Fill + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1773217052 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1773217051} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 350044372} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -32, y: -32} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1773217053 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1773217051} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0.23137255, b: 0.44705883, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 0e631649835abae4fad9a729f45bcb81, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 2 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1773217054 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1773217051} + m_CullTransparentMesh: 1 +--- !u!1 &1900434453 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1900434454} + - component: {fileID: 1900434456} + - component: {fileID: 1900434455} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1900434454 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1900434453} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 531249905} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1900434455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1900434453} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1900434456 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1900434453} + m_CullTransparentMesh: 1 +--- !u!1 &1993542207 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1993542208} + - component: {fileID: 1993542209} + m_Layer: 5 + m_Name: Group_Progress + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1993542208 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1993542207} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 997970086} + - {fileID: 865714440} + m_Father: {fileID: 350044372} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1993542209 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1993542207} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_Spacing: 0 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 203667522} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity.meta new file mode 100644 index 00000000..87173f3d --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Custom.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e0094647c619f9c479fb11636924890e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity new file mode 100644 index 00000000..db5689a7 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity @@ -0,0 +1,1121 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &101138762 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 101138767} + - component: {fileID: 101138766} + - component: {fileID: 101138765} + - component: {fileID: 101138764} + - component: {fileID: 101138763} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &101138763 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101138762} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c075a502fec352044ac850b2ac556afe, type: 3} + m_Name: + m_EditorClassIdentifier: + waitForScriptedStart: 1 + waitForScriptedEnd: 1 +--- !u!114 &101138764 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101138762} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &101138765 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101138762} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 2 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &101138766 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101138762} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 10 + m_TargetDisplay: 0 +--- !u!224 &101138767 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 101138762} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 2029535315} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &158472101 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 158472102} + - component: {fileID: 158472104} + - component: {fileID: 158472103} + - component: {fileID: 158472105} + m_Layer: 5 + m_Name: Text_Value + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &158472102 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 158472101} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2115346373} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &158472103 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 158472101} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 24 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 2 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 00 +--- !u!222 &158472104 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 158472101} + m_CullTransparentMesh: 1 +--- !u!114 &158472105 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 158472101} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 20a0de9ed473d5f4cbda13658d314b06, type: 3} + m_Name: + m_EditorClassIdentifier: + loadingBehavior: {fileID: 101138763} +--- !u!1 &708903265 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 708903266} + - component: {fileID: 708903268} + - component: {fileID: 708903267} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &708903266 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 708903265} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2029535315} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &708903267 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 708903265} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &708903268 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 708903265} + m_CullTransparentMesh: 1 +--- !u!1 &787578539 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 787578540} + - component: {fileID: 787578542} + - component: {fileID: 787578541} + m_Layer: 5 + m_Name: Text_Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &787578540 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787578539} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1457722969} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &787578541 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787578539} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 36 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 2 + m_MaxSize: 48 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Loading Scene +--- !u!222 &787578542 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 787578539} + m_CullTransparentMesh: 1 +--- !u!1 &1387984379 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1387984380} + - component: {fileID: 1387984382} + - component: {fileID: 1387984381} + m_Layer: 5 + m_Name: Text_Symbol + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1387984380 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1387984379} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2115346373} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1387984381 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1387984379} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 24 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 2 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '%' +--- !u!222 &1387984382 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1387984379} + m_CullTransparentMesh: 1 +--- !u!1 &1457722968 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1457722969} + - component: {fileID: 1457722971} + - component: {fileID: 1457722970} + m_Layer: 5 + m_Name: Group_Progress + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1457722969 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1457722968} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 787578540} + - {fileID: 2115346373} + m_Father: {fileID: 2029535315} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1457722970 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1457722968} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &1457722971 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1457722968} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 32 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &1658017578 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1658017579} + - component: {fileID: 1658017580} + m_Layer: 5 + m_Name: Fill Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1658017579 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1658017578} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1873277544} + m_Father: {fileID: 2115346373} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1658017580 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1658017578} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 1 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1740862374 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1740862375} + - component: {fileID: 1740862378} + - component: {fileID: 1740862377} + - component: {fileID: 1740862376} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1740862375 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1740862374} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 2115346373} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1740862376 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1740862374} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 1 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1740862377 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1740862374} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0.23137255, b: 0.44705883, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1740862378 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1740862374} + m_CullTransparentMesh: 1 +--- !u!1 &1873277543 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1873277544} + - component: {fileID: 1873277546} + - component: {fileID: 1873277545} + m_Layer: 5 + m_Name: Fill + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1873277544 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873277543} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1658017579} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0.5} +--- !u!114 &1873277545 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873277543} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23921569, g: 0.72156864, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1873277546 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873277543} + m_CullTransparentMesh: 1 +--- !u!1 &2029535314 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2029535315} + - component: {fileID: 2029535317} + - component: {fileID: 2029535316} + m_Layer: 5 + m_Name: Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2029535315 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2029535314} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 708903266} + - {fileID: 1457722969} + m_Father: {fileID: 101138767} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2029535316 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2029535314} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3d268aa56fe5044468ac1c18858ab207, type: 3} + m_Name: + m_EditorClassIdentifier: + loadingBehavior: {fileID: 101138763} + fadeTime: 1 + _fadeOutCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _fadeInCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!225 &2029535317 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2029535314} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 +--- !u!1 &2115346372 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2115346373} + - component: {fileID: 2115346375} + - component: {fileID: 2115346374} + - component: {fileID: 2115346376} + m_Layer: 5 + m_Name: Slider + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2115346373 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115346372} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1740862375} + - {fileID: 1658017579} + - {fileID: 158472102} + - {fileID: 1387984380} + m_Father: {fileID: 1457722969} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2115346374 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115346372} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 128 + m_Right: 128 + m_Top: 6 + m_Bottom: 6 + m_ChildAlignment: 4 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &2115346375 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115346372} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 0 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 0 + m_TargetGraphic: {fileID: 0} + m_FillRect: {fileID: 1873277544} + m_HandleRect: {fileID: 0} + m_Direction: 0 + m_MinValue: 0 + m_MaxValue: 1 + m_WholeNumbers: 0 + m_Value: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &2115346376 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2115346372} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21e4a56a49cb1dd489d83ec7962d2fc2, type: 3} + m_Name: + m_EditorClassIdentifier: + loadingBehavior: {fileID: 101138763} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 101138767} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity.meta new file mode 100644 index 00000000..6daadd3f --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/Loading_Fade.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 72e1cc83992e7c345938b36dbc8f927a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity new file mode 100644 index 00000000..b98781d6 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity @@ -0,0 +1,2627 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &65780886 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 65780887} + - component: {fileID: 65780890} + - component: {fileID: 65780889} + - component: {fileID: 65780888} + m_Layer: 5 + m_Name: Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &65780887 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1704821105} + - {fileID: 543624002} + m_Father: {fileID: 966196647} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!225 &65780888 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 +--- !u!114 &65780889 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &65780890 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 48 + m_Right: 0 + m_Top: 48 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 24 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &72215351 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 72215352} + - component: {fileID: 72215355} + - component: {fileID: 72215354} + - component: {fileID: 72215353} + m_Layer: 0 + m_Name: Barrel_01 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &72215352 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.218, y: 0.5, z: 4.515} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!136 &72215353 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!23 &72215354 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7fa4d47884e65f4da8abc72e5dcb96a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &72215355 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &319343628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 319343629} + - component: {fileID: 319343633} + - component: {fileID: 319343632} + - component: {fileID: 319343631} + - component: {fileID: 319343630} + m_Layer: 5 + m_Name: Button_Animated + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &319343629 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1325044622} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &319343630 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &319343631 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 319343632} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Animated + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &319343632 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &319343633 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_CullTransparentMesh: 1 +--- !u!1 &476363614 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 476363615} + - component: {fileID: 476363618} + - component: {fileID: 476363617} + - component: {fileID: 476363616} + m_Layer: 0 + m_Name: Barrel_02 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &476363615 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.718, y: 0.5, z: 4.22} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!136 &476363616 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!23 &476363617 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7fa4d47884e65f4da8abc72e5dcb96a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &476363618 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &522875729 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 522875730} + - component: {fileID: 522875733} + - component: {fileID: 522875732} + - component: {fileID: 522875731} + m_Layer: 0 + m_Name: Box_02 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &522875730 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.07831686, z: -0, w: 0.9969285} + m_LocalPosition: {x: -0.388, y: 0.25, z: 3.933} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: -8.984, z: 0} +--- !u!65 &522875731 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &522875732 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &522875733 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &541502988 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 541502989} + - component: {fileID: 541502991} + - component: {fileID: 541502990} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &541502989 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541502988} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1961195941} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &541502990 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541502988} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Direct Transition +--- !u!222 &541502991 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541502988} + m_CullTransparentMesh: 1 +--- !u!1 &543624001 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 543624002} + - component: {fileID: 543624003} + m_Layer: 5 + m_Name: Body + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &543624002 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543624001} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 974881141} + - {fileID: 319343629} + - {fileID: 817812573} + - {fileID: 1961195941} + m_Father: {fileID: 65780887} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &543624003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543624001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 16 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &648910241 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 648910242} + - component: {fileID: 648910245} + - component: {fileID: 648910244} + - component: {fileID: 648910243} + m_Layer: 0 + m_Name: Box_01 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &648910242 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.10886683, z: -0, w: 0.9940564} + m_LocalPosition: {x: -1.072, y: 0.25, z: 3.633} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 12.5, z: 0} +--- !u!65 &648910243 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &648910244 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &648910245 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &715494127 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 715494129} + - component: {fileID: 715494128} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &715494128 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 715494127} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &715494129 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 715494127} + serializedVersion: 2 + m_LocalRotation: {x: 0.12708376, y: 0.8643611, z: -0.40305817, w: 0.27253202} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: 145, z: 0} +--- !u!1 &817812572 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 817812573} + - component: {fileID: 817812577} + - component: {fileID: 817812576} + - component: {fileID: 817812575} + - component: {fileID: 817812574} + m_Layer: 5 + m_Name: Button_Custom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &817812573 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1959944215} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &817812574 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &817812575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 817812576} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Custom + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &817812576 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &817812577 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_CullTransparentMesh: 1 +--- !u!1 &966196643 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 966196647} + - component: {fileID: 966196646} + - component: {fileID: 966196645} + - component: {fileID: 966196644} + - component: {fileID: 966196648} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &966196644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &966196645 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 2 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &966196646 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &966196647 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 65780887} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &966196648 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2e674cd85e71d854e945438963214e21, type: 3} + m_Name: + m_EditorClassIdentifier: + _targetScene: SceneB +--- !u!1 &974881140 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 974881141} + - component: {fileID: 974881145} + - component: {fileID: 974881144} + - component: {fileID: 974881143} + - component: {fileID: 974881142} + m_Layer: 5 + m_Name: Button_Fade + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &974881141 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1628318502} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &974881142 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &974881143 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 974881144} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Fade + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &974881144 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &974881145 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_CullTransparentMesh: 1 +--- !u!1 &1297270288 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1297270289} + - component: {fileID: 1297270292} + - component: {fileID: 1297270291} + - component: {fileID: 1297270290} + m_Layer: 0 + m_Name: Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1297270289 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 5.25} + m_LocalScale: {x: 10, y: 2, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &1297270290 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1297270291 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 24fbfe448e3667a48af7eddd9ccffbf6, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1297270292 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1325044621 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1325044622} + - component: {fileID: 1325044624} + - component: {fileID: 1325044623} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1325044622 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 319343629} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1325044623 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Animated Transition +--- !u!222 &1325044624 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_CullTransparentMesh: 1 +--- !u!1 &1408457994 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1408457995} + m_Layer: 0 + m_Name: Environment + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1408457995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1408457994} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1489239189} + - {fileID: 1297270289} + - {fileID: 648910242} + - {fileID: 522875730} + - {fileID: 1450737562} + - {fileID: 72215352} + - {fileID: 476363615} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1450737561 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1450737562} + - component: {fileID: 1450737565} + - component: {fileID: 1450737564} + - component: {fileID: 1450737563} + m_Layer: 0 + m_Name: Box_03 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1450737562 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.07831686, z: -0, w: 0.9969285} + m_LocalPosition: {x: -1.768, y: 0.25, z: 4.301} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: -8.984, z: 0} +--- !u!65 &1450737563 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1450737564 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1450737565 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1489239188 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1489239189} + - component: {fileID: 1489239192} + - component: {fileID: 1489239191} + - component: {fileID: 1489239190} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1489239189 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!64 &1489239190 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1489239191 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3914cfcf95c8d774eaa76b1757b28bcf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1489239192 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1628318501 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1628318502} + - component: {fileID: 1628318504} + - component: {fileID: 1628318503} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1628318502 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 974881141} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1628318503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Fade Transition +--- !u!222 &1628318504 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_CullTransparentMesh: 1 +--- !u!1 &1704821104 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1704821105} + - component: {fileID: 1704821106} + m_Layer: 5 + m_Name: Header + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1704821105 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1704821104} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1977277422} + m_Father: {fileID: 65780887} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1704821106 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1704821104} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 16 + m_Right: 16 + m_Top: 8 + m_Bottom: 8 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &1959944214 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1959944215} + - component: {fileID: 1959944217} + - component: {fileID: 1959944216} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1959944215 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 817812573} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1959944216 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Custom Transition +--- !u!222 &1959944217 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_CullTransparentMesh: 1 +--- !u!1 &1961195940 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1961195941} + - component: {fileID: 1961195945} + - component: {fileID: 1961195944} + - component: {fileID: 1961195943} + - component: {fileID: 1961195942} + m_Layer: 5 + m_Name: Button_Direct + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1961195941 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961195940} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 541502989} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1961195942 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961195940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &1961195943 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961195940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1961195944} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: Transition + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1961195944 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961195940} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1961195945 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961195940} + m_CullTransparentMesh: 1 +--- !u!1 &1977277421 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1977277422} + - component: {fileID: 1977277425} + - component: {fileID: 1977277424} + - component: {fileID: 1977277423} + m_Layer: 5 + m_Name: Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1977277422 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1704821105} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1977277423 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: 300 + m_MinHeight: 90 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1977277424 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 72 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 7 + m_MaxSize: 72 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Scene A +--- !u!222 &1977277425 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_CullTransparentMesh: 1 +--- !u!1 &2058983089 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2058983092} + - component: {fileID: 2058983091} + - component: {fileID: 2058983090} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2058983090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &2058983091 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &2058983092 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2104398059 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2104398062} + - component: {fileID: 2104398061} + - component: {fileID: 2104398060} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &2104398060 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + m_Enabled: 1 +--- !u!20 &2104398061 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &2104398062 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + serializedVersion: 2 + m_LocalRotation: {x: -0.0767328, y: 0.0065776585, z: -0.0005059611, w: -0.9970299} + m_LocalPosition: {x: 0.48567814, y: 1.1522692, z: 0.55634296} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2104398062} + - {fileID: 715494129} + - {fileID: 1408457995} + - {fileID: 966196647} + - {fileID: 2058983092} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity.meta new file mode 100644 index 00000000..4c575eea --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneA.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 26ad88ac19a09ee4597038542f7c085d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.meta new file mode 100644 index 00000000..45eee272 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b3e0ac649b31a3949b28a1062db22ecb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity new file mode 100644 index 00000000..62dd6d6f --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity @@ -0,0 +1,2693 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.15, g: 0.15, b: 0.15, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 2100000, guid: 162b48961309d454ba4e0118c646ecca, type: 2} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 112000000, guid: 713fb479830fe2f41a7256e290b34369, type: 2} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &65780886 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 65780887} + - component: {fileID: 65780890} + - component: {fileID: 65780889} + - component: {fileID: 65780888} + m_Layer: 5 + m_Name: Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &65780887 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1704821105} + - {fileID: 543624002} + m_Father: {fileID: 966196647} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!225 &65780888 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 +--- !u!114 &65780889 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 2 + m_VerticalFit: 2 +--- !u!114 &65780890 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 65780886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 48 + m_Right: 0 + m_Top: 48 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 24 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &72215351 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 72215352} + - component: {fileID: 72215355} + - component: {fileID: 72215354} + - component: {fileID: 72215353} + m_Layer: 0 + m_Name: Barrel_01 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &72215352 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.218, y: 0.5, z: 4.515} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!136 &72215353 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!23 &72215354 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7fa4d47884e65f4da8abc72e5dcb96a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &72215355 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 72215351} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &77173871 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 77173873} + - component: {fileID: 77173872} + m_Layer: 0 + m_Name: Reflection Probe + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!215 &77173872 +ReflectionProbe: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 77173871} + m_Enabled: 1 + serializedVersion: 2 + m_Type: 0 + m_Mode: 0 + m_RefreshMode: 0 + m_TimeSlicingMode: 0 + m_Resolution: 128 + m_UpdateFrequency: 0 + m_BoxSize: {x: 10, y: 10, z: 10} + m_BoxOffset: {x: 0, y: 0, z: 0} + m_NearClip: 0.3 + m_FarClip: 1000 + m_ShadowDistance: 100 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_IntensityMultiplier: 1 + m_BlendDistance: 1 + m_HDR: 1 + m_BoxProjection: 0 + m_RenderDynamicObjects: 0 + m_UseOcclusionCulling: 1 + m_Importance: 1 + m_CustomBakedTexture: {fileID: 0} +--- !u!4 &77173873 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 77173871} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.438, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &157672352 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 157672353} + - component: {fileID: 157672355} + - component: {fileID: 157672354} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &157672353 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 157672352} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1468409464} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &157672354 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 157672352} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Direct Transition +--- !u!222 &157672355 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 157672352} + m_CullTransparentMesh: 1 +--- !u!1 &319343628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 319343629} + - component: {fileID: 319343633} + - component: {fileID: 319343632} + - component: {fileID: 319343631} + - component: {fileID: 319343630} + m_Layer: 5 + m_Name: Button_Animated + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &319343629 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1325044622} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &319343630 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &319343631 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} + m_HighlightedColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_PressedColor: {r: 0, g: 0, b: 0, a: 1} + m_SelectedColor: {r: 0.15, g: 0.15, b: 0.15, a: 1} + m_DisabledColor: {r: 0.1, g: 0.1, b: 0.1, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 319343632} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Animated + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &319343632 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &319343633 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319343628} + m_CullTransparentMesh: 1 +--- !u!1 &476363614 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 476363615} + - component: {fileID: 476363618} + - component: {fileID: 476363617} + - component: {fileID: 476363616} + m_Layer: 0 + m_Name: Barrel_02 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &476363615 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.718, y: 0.5, z: 4.22} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!136 &476363616 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!23 &476363617 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c7fa4d47884e65f4da8abc72e5dcb96a, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &476363618 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 476363614} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &522875729 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 522875730} + - component: {fileID: 522875733} + - component: {fileID: 522875732} + - component: {fileID: 522875731} + m_Layer: 0 + m_Name: Box_02 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &522875730 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.07831686, z: -0, w: 0.9969285} + m_LocalPosition: {x: -0.388, y: 0.25, z: 3.933} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: -8.984, z: 0} +--- !u!65 &522875731 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &522875732 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &522875733 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522875729} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &543624001 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 543624002} + - component: {fileID: 543624003} + m_Layer: 5 + m_Name: Body + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &543624002 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543624001} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 974881141} + - {fileID: 319343629} + - {fileID: 817812573} + - {fileID: 1468409464} + m_Father: {fileID: 65780887} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &543624003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543624001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 16 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &648910241 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 648910242} + - component: {fileID: 648910245} + - component: {fileID: 648910244} + - component: {fileID: 648910243} + m_Layer: 0 + m_Name: Box_01 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &648910242 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: 0.10886683, z: -0, w: 0.9940564} + m_LocalPosition: {x: -1.072, y: 0.25, z: 3.633} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 12.5, z: 0} +--- !u!65 &648910243 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &648910244 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &648910245 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 648910241} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &715494127 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 715494129} + - component: {fileID: 715494128} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &715494128 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 715494127} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 0.1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &715494129 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 715494127} + serializedVersion: 2 + m_LocalRotation: {x: 0.29956153, y: 0.08312204, z: -0.9500878, w: 0.026208278} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 170, y: 145, z: 0} +--- !u!1 &817812572 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 817812573} + - component: {fileID: 817812577} + - component: {fileID: 817812576} + - component: {fileID: 817812575} + - component: {fileID: 817812574} + m_Layer: 5 + m_Name: Button_Custom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &817812573 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1959944215} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &817812574 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &817812575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} + m_HighlightedColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_PressedColor: {r: 0, g: 0, b: 0, a: 1} + m_SelectedColor: {r: 0.15, g: 0.15, b: 0.15, a: 1} + m_DisabledColor: {r: 0.1, g: 0.1, b: 0.1, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 817812576} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Custom + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &817812576 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &817812577 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 817812572} + m_CullTransparentMesh: 1 +--- !u!1 &966196643 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 966196647} + - component: {fileID: 966196646} + - component: {fileID: 966196645} + - component: {fileID: 966196644} + - component: {fileID: 966196648} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &966196644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &966196645 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1920, y: 1080} + m_ScreenMatchMode: 2 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &966196646 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &966196647 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 65780887} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &966196648 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 966196643} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2e674cd85e71d854e945438963214e21, type: 3} + m_Name: + m_EditorClassIdentifier: + _targetScene: SceneA +--- !u!1 &974881140 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 974881141} + - component: {fileID: 974881145} + - component: {fileID: 974881144} + - component: {fileID: 974881143} + - component: {fileID: 974881142} + m_Layer: 5 + m_Name: Button_Fade + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &974881141 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1628318502} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &974881142 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &974881143 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} + m_HighlightedColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_PressedColor: {r: 0, g: 0, b: 0, a: 1} + m_SelectedColor: {r: 0.15, g: 0.15, b: 0.15, a: 1} + m_DisabledColor: {r: 0.1, g: 0.1, b: 0.1, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 974881144} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: TransitionWithLoading + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Loading_Fade + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &974881144 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &974881145 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 974881140} + m_CullTransparentMesh: 1 +--- !u!1 &1297270288 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1297270289} + - component: {fileID: 1297270292} + - component: {fileID: 1297270291} + - component: {fileID: 1297270290} + m_Layer: 0 + m_Name: Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &1297270289 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 5.25} + m_LocalScale: {x: 10, y: 2, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &1297270290 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1297270291 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 33b2ce6d53c5e8947a553e4540a27b13, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1297270292 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1297270288} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1325044621 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1325044622} + - component: {fileID: 1325044624} + - component: {fileID: 1325044623} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1325044622 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 319343629} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1325044623 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Animated Transition +--- !u!222 &1325044624 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1325044621} + m_CullTransparentMesh: 1 +--- !u!1 &1408457994 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1408457995} + m_Layer: 0 + m_Name: Environment + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &1408457995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1408457994} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1489239189} + - {fileID: 1297270289} + - {fileID: 648910242} + - {fileID: 522875730} + - {fileID: 1450737562} + - {fileID: 72215352} + - {fileID: 476363615} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1450737561 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1450737562} + - component: {fileID: 1450737565} + - component: {fileID: 1450737564} + - component: {fileID: 1450737563} + m_Layer: 0 + m_Name: Box_03 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &1450737562 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0.07831686, z: -0, w: 0.9969285} + m_LocalPosition: {x: -1.768, y: 0.25, z: 4.301} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: -8.984, z: 0} +--- !u!65 &1450737563 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1450737564 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 2cae1f6280e4f78409eeb7d01a1ab00b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1450737565 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1450737561} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1468409463 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1468409464} + - component: {fileID: 1468409468} + - component: {fileID: 1468409467} + - component: {fileID: 1468409466} + - component: {fileID: 1468409465} + m_Layer: 5 + m_Name: Button_Direct + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1468409464 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1468409463} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 157672353} + m_Father: {fileID: 543624002} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1468409465 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1468409463} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 24 + m_Right: 24 + m_Top: 16 + m_Bottom: 16 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &1468409466 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1468409463} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} + m_HighlightedColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_PressedColor: {r: 0, g: 0, b: 0, a: 1} + m_SelectedColor: {r: 0.15, g: 0.15, b: 0.15, a: 1} + m_DisabledColor: {r: 0.1, g: 0.1, b: 0.1, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1468409467} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 65780888} + m_TargetAssemblyTypeName: UnityEngine.CanvasGroup, UnityEngine + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 966196648} + m_TargetAssemblyTypeName: SceneTransitionTrigger, Sample.LoadingScene + m_MethodName: Transition + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &1468409467 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1468409463} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1468409468 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1468409463} + m_CullTransparentMesh: 1 +--- !u!1 &1489239188 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1489239189} + - component: {fileID: 1489239192} + - component: {fileID: 1489239191} + - component: {fileID: 1489239190} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 64 + m_IsActive: 1 +--- !u!4 &1489239189 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1408457995} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!64 &1489239190 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1489239191 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3914cfcf95c8d774eaa76b1757b28bcf, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1489239192 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1489239188} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1628318501 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1628318502} + - component: {fileID: 1628318504} + - component: {fileID: 1628318503} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1628318502 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 974881141} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1628318503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Fade Transition +--- !u!222 &1628318504 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1628318501} + m_CullTransparentMesh: 1 +--- !u!1 &1704821104 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1704821105} + - component: {fileID: 1704821106} + m_Layer: 5 + m_Name: Header + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1704821105 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1704821104} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1977277422} + m_Father: {fileID: 65780887} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1704821106 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1704821104} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 16 + m_Right: 16 + m_Top: 8 + m_Bottom: 8 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &1959944214 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1959944215} + - component: {fileID: 1959944217} + - component: {fileID: 1959944216} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1959944215 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 817812573} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1959944216 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Custom Transition +--- !u!222 &1959944217 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1959944214} + m_CullTransparentMesh: 1 +--- !u!1 &1977277421 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1977277422} + - component: {fileID: 1977277425} + - component: {fileID: 1977277424} + - component: {fileID: 1977277423} + m_Layer: 5 + m_Name: Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1977277422 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1704821105} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1977277423 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: 300 + m_MinHeight: 90 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &1977277424 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 72 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 7 + m_MaxSize: 72 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Scene B +--- !u!222 &1977277425 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1977277421} + m_CullTransparentMesh: 1 +--- !u!1 &2058983089 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2058983092} + - component: {fileID: 2058983091} + - component: {fileID: 2058983090} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2058983090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &2058983091 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &2058983092 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2058983089} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2104398059 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2104398062} + - component: {fileID: 2104398061} + - component: {fileID: 2104398060} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &2104398060 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + m_Enabled: 1 +--- !u!20 &2104398061 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &2104398062 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2104398059} + serializedVersion: 2 + m_LocalRotation: {x: -0.0767328, y: 0.0065776585, z: -0.0005059611, w: -0.9970299} + m_LocalPosition: {x: 0.48567814, y: 1.1522692, z: 0.55634296} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2104398062} + - {fileID: 715494129} + - {fileID: 77173873} + - {fileID: 1408457995} + - {fileID: 966196647} + - {fileID: 2058983092} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity.meta new file mode 100644 index 00000000..ccd78c11 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d6dc9d379ebdf9044808e8d344a75da0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/LightingData.asset b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/LightingData.asset new file mode 100644 index 0000000000000000000000000000000000000000..7a38e2a0e6b92f094fc8706454ea15598cd2616d GIT binary patch literal 17777 zcmdU%eSB5LnaAgn5MIQJii)BT@C_8x+#rY%F+f0~M36+pqQXsbLT*WJ;=MPJ;M=t# zzM*Z=)@t1qwzcBcT6MJ|RMsuswpM9ZSGrJlYwfCAcd2cu){3s|@0od?d(Yf+pVem@y2%_`_Z1}Gh)W1D~usZ?kr<+$a2s=t@GwTPLT$<%m9R{lZutOO2VOQLLBLN2*pTi?OW_F`)9f+s)kuJn?@Yof%??}YQ>V#5Re)~odFJO#rnaSdr z+IJG}M-}myDK|SXem5YV+D8*5oIhp;d-`{bTk`w&m^kGC8iyJGn#AbueEVacE|4&4;U;lEi|7nbU9y3oO?gzL?{>hfZV^^%dry$Zy@{uu1;K&aQW>YWHzJiMtFj~$I4@deB;MZ7z-X z#d3J;sQ)&h|L+2)es9I)_rK%!GjCJ)gUkbkKgzsa;ZHMPsqp8R(|2sC`aRD)sqmMX z!;X~9|0;7@yp@vw26OtxD8+xnyi4KlGfyczR_5e(EBp}VJqkaH`Be%Z$2=Y3&VEk< zC;Octo`c7(*nVdbAFC5eb@tZ>y~GRH@_CR=_M7a}>Iiq=mzN{WP_Q)$PcrX|@R(T* zwgDH_zn^#x9y@x!)B5M@%-15`=Vjjd?rP$7oSDL~PxO5(>$_`goX;PFY-(Q}qOXnc z!KNSI-@A~8-cQ#>c!l@X8f@QBKZAVg-y1Bigzp^X-;BD6 z{r?=I{r8LGVt;N_xY(a{3K#oxQ-r(s@9$7QdOxnW93DHeKV+Xi;QHT;cwc`iJo|Ku z!o@z_s&KJSw<%og)9nfu`?NvfVxR6%xY(yV6)yJa^9mRH^aX{Befpxp#XfCRxY(z= z6fXAZZiS0|`jW!MK7Co?VxR7baHk&?P#)6nuUMXg?;PoO`2BS+qW$^dxabG1<4bYT zkFP3R^y7Yoi+=ot!bLy+QsJT>4=7ypW0S%~KQPxzwomlquM{r&@im2uetccwq8|?` zT=e4`3K#u&Na3O%TO!=q_amVnWd9!~o`c5@?}wx5&7UVC+@C*x zqi~r&PbysI&r=GQ`STrx%lvs-;WB@=DqQBzGYXgavrXYLf3_=J=FfK(F7xMEh0FZe zp>UZ$f2(krKhG&#=Fi_LT;|XBBHY>6TUbAKM!2sZ-&eTk$KNYl^y3E#7ybC5!bLxR zq;S!X=M^sc@neOHe!QS?(T^7uF8Z-c;i4ZuQMl;GPZciu@ec|Y{dh^?q8~3ST=e4~ zBiz~7`=K9XUtb}fgU7DezV1f+K=$=##3i#0yY(sASF%t46yg5*bdSPC|Mn_e^zY{i z7yWxx;i7;4tZ>o4e^I#TA8dV5`(67)|6WtL=-)3DF8cSn!bSgnrEt-|e^t2X-x~@S z{d-g4qJM8GT=ehXBHZcU7S_LC6VJh8SFC?;BYq(L`*-4!*@nx_R>&s(8;$4xh;X-l z*@HCrGy6(#dcXb(ko5OA5$@a1cN8xA`&)&J{{BwkqQAdaxajYGg^T|FLE)mm?3_Mx&t^V2!rlJT zJaB4W1@RmNu`AwR8bZ8IDAnKJUm6;bUuMGlOT!}E-(MQ8aM@ovB*I<&lU)B1#B<^L z`M(c1l=uMk|5QZ2U;o1*+^_#gg-iVpk8oH2G}r$K;sezGNaD|h+voTHs3Q4v{(m!M zll?p#+31|rm+#hB_aY7H&(THsW&QO8^J7ZzAA;?{H5Bkf@3O~U7xCk$& zGo9Rs3e+3&#}KbWfE}GL@5cV&C~(qWIwy|hgi;=V{7;DF_xo=w@j`Zl%gke;^Z9WR z?w`+BT3)CC^-_rB`dapH>6{*ac}Ml%gz+W)rTEh$-2MJw8OkU9om|8h zBv*E1lc|;UiELt4CKF`MqD9&CjJa*eY`1hAuW3wV zR^egR!seha+nWwDt`M7UQM$V&$WSSvM|q;M8oS#9)6~-uq?4_Q&iRRSS9dDenpseT zM6(mCg0@**Ey*C2wSpQ_3zDfIkv5r*WtG)e*jwD)YTRv#yPfH7Q{8QvyPf53)7|ZC zdy6|MaVI72q{N++xRVlhQsPcZ+)0T$DRC#I#!0DhQfi!(8YiX3NvUyCY9OW1(>+1k z;vm%)q=U5WYVW}gUt^Hzm}z=f)7@l)bUKkt)%T|oUCGu)?Lj{`pp-u2J#n&pB%}#%Y8Dvu^>ij%ldk)lg6#YR>e14l4KmBnW*0!KT>$NN z0kqr&&~_I<>sxV&^4AdZ84wObqNGsf!p!j{hl zt=Wb)s8g~%8Kg}%kzN^OT{J(q`C{g#Y+nQ^o3Sy`(}O99BD8oJxlAFaL^Y(^yVG5X zEM}=m^JtqkH--y%c$%6UQceAtY|v#g_SVp5l00W^m#+-EyMk=G-#%dC*+ikjTtum& z+{jD8P06)^Nn|?{85eJZ3)|aaSC+bX_i!1C@9E7tv9{23qAl5-NoM;)aWFM@eh1kM z`o@7-Bpf!N&{MXqHac8CTXLZ~wv6^Tk61G<(sJB7De9g^rphh?UEyIk6a)KU|A zxJ(XSRah}!rm`QbA|l zq>@duHc#eS$%y9up1^b^`+_zr7xl1tk{L=(J!9{SgZ54+G)lL_FsHXAu;#loriSGQ zg)O`Hyd+3dOYEDAzT)vYvj2$pE`Q~%1q! zC*3$o;dB^5{Ah*mV1A6kX)~De)5cEN(V-#LpEfgz9~*`U3xA#YaSEr+9LhgN;k21R z{P+@_7P7S1ss=kD!iU&Hds?he{;>+D#RTzj3a5{K;*|=gk8$GT6)rz&rFjx|G2`l2 z#raPRLxhFbFh5D*)0m&E@LJ}lD10XKQx!g&`9y`wk7g%Dc!gaQUV!}gvp*U(CYMh| ziw0U0E(WCeM|LiRk;k7ulZn@n=UnmpIYU5*zsZXdvX50ZzLKfa&&??D3Y1Ud_i2SM zXHGg6)&luaNP>Ah!ri7+D>${UhIq~jK11Q#n4hcgoy=z{{6*&HDSS8cI)(p&`7DM1n)z&n?`J+o;U6)tS9rxB*MD;r zK9c#o2zT$FGx)oDD$^b;WB?OQn<|Dg%Li;{2ubBar+kKOLl?c`AhHUuq$rg;xI&*_&DCQqIY{! zgu6rKuc8h#f14xRpTCzVT;}f*h0FZCRN*pz={qUx#6HOUy(|n77B2JmGYXgayG-FS ze=k?K%-<^%F7x+Fh0FYcZULwCpG#8>07jH)PZMrxP*B2rswua~;x9{gBRc zr2jO3Z)d*Bqi%i>-^iTG2s_DtFY~T2L|FJH=5EnfNF@9r=G_HkL&E7$km}!~@TZtx zrSR`EPb+*U^NhlO%si{`mzeh|d=K;03V)6H8il{byiehDs7U?Oukd%7(>f~bq<=qT zesvfkEPN0a#w7n5g%4wXt-?n#zfR%DFuz{mW0~g^elqhL6h4{x=M+AL`Hc#%Wxg)L z-Ta;fPVe8Fi02B4is$!wLUm#8&+nTH$cAWsUkceYze)Zr5ngW2f$dqv<=-0NgT3$D z+albpALaY@c7;>p+?XI)z!G-xN2}sF+m*9aXiQI9LIAFo@?-2gXfwl zCYf1+#?hAK{NB#a#fkn5pGolEFnR&!L9|thP=h^%K+^xqrwDEX91XIY(`W|mdShRd z_D?VBPUVM(#x!X2nuc=%B(i(6bGn1}cAT8xtO2JFrOvnhpPymbR$BGX?}58bZrdY; zIM#!Fgv}y~kdH;T<-_4^bE_+}gCIrco!I#%hj${}>~GylGuzF7+-ZqnBR+bhg5t$x zZKQjGH87@Y*WS$AuRc(>E_dg-^=o(I6Or6SPwxMD?VRcJAHQe9>Za!3p5PhmXO~fDV*fC>c{mU~p{_%|M zi&y`lcE_8q*M8hKe*4Guhi=>S?$qt0cTL{DW%)bjOnh(jj7|M@+eSTHQCqe2u-c#O zU9j!I>JOip_R_K2?ismv+rEYyYwvsEd$s%Kt=anG{>js)KecfB*V1=y{mS0`TNh0l zz4cGk&ptzC|2d9&o~}*1+zXMqL&8+&p1bd*w^80*fY2o=oEgot3%H?EtNN|1~k0wS^-_Jjlot6>!sk$n@CO+-N_>^p=2$|kajfT)0o zD^6Gi1O!C}To|@dbWjl#Q5ok}obUI(@4fGHpZB@X{p0t~uTx#s-RX37ov!n#&pD?$ z343&*FbD(^80LTUXmDg4*oX{|i-+t5$E+Ywkn3jwR}aL$KiJzn8zko%{lJg2LmXBmGbQx93HM9}V6Y z8x$N1`H!uiw;Uaw7#vBBiw+KqclD1CKL!bjJmwz{LHw+UWf>P38ytM}pUcyNkH&)w zB<5d@Na|DRu7?)c|Gk}pr3|15Gn5QqS*1IY(= zF<`}!z>0-o#jtpcAQnPH=yEk6_80NBP`m8)bn*O$5Z%|Rm@7ri>S9BM2dYjHqqJ{) zDGT+ebWFn{;NhxwkQ6Cd8szkJzq_n+nE z%a`xoC!DzZ{N>RTcVE6wxcl;Fde;rw_}?x+zVc2vvio08?EkHxKp=PsuScUHSR^DH zfiH20ZC%#4FkbFz{q48v%I9z2|91EE%@0pcKmT(2_wVyS=J!8?2k;W4yIN$sCr((w; z6#pz39Qx1Cfg?wvuH5LJIdJ*L%z-OUL5jF>;ELzZ&w;0{9#?**r>(6XU=w5>VDo=n zT*1MX)>crowz`8Y_p(-d4_JTlODV|E|3#22rhVtc z;};#bVvfh101X3=D=Gp!uXq1`SVx~nfzQ$ZXc%bROm|e&^Jg>NH?CZX0*e#Dj*tV| z$f1kbspJqi43%QKSPntV4r~&58##29V#dGLY`TiaWzQR}9yeMKfaXPbfDN!504?Gz zWxO3tu+a*d!)w(=&^UDX?SJ1m6tV(`K(a3*e;yFfwZ{2pO8Y;Mj}^ejJiw<4;8Rfq z4ygE_WKXIGDfeHgb5yH7Ppk8xPUl0AYxRxk^ke?Xb^09*o;c||aWd$40vjNamqA`g zeo{bQE;M+;2D#btgu!x=*^?s5<|A`>0r|-|d2^h+f(6ITHreFOeP)~A&ES(z2-XoTPch*(ZrfE53`D=1VO@xd6%T8oqaz{ht4ST0Tq#wIu zEi%ZYby+6TKCW1L(>Ce6tK-0JSpL0pTjT+A2PMK~e-;_R{!kEk&E7$RD|{CD`|k&| zb%G^=_PNVaj<(TdiRA4H(bhj%;%Og)ERARz?v^Op$5Km0+IqZY4DZ`lmg@$VB-&=Y zrMTrsx&>|HlNoJ22*RsYmG-gGQkT{RcIcM>EiU~3C;WdQfgchgeUm#vBG?^Kkv{fU zuzp5ZLTCe6sPN=Rga~-d=2XzJ5m+b!VummW-TNcx`EV{3bn?wdmiFIAOn4)fa<#jX-)?PVbrDQ{_meW~e43JfiRlPpyr2_X6H1<}H#kYo2BCLA13 z_xkmE_w(;0cvRlk??)ddJP*zNJ7KL>=_jwx_|G;Yj`(z z@b_+(j)K&A#FI2QOWipuwAXBVcpV8{EM9Q4h>2F3F>3C04W`I=5Z&=wj?HSVj?E_~ z_%3`se{6A#rE9!bI`$~;wym)7Ua0pd*`}@x+M4MuNeZSQZwQf8Nny3}%|_*AG!!e# zaWpl3jD*sZc2sqI%)&h2k_=!K0AL;`shIg#`2yc}M$-bZ%codY|5aT8ey!s9z&kkxK)? z85s{ArlqEZ=b~kqkj6SFv$_T4rzN4RB_XM-6{=s}q&sTt$arO3Fg12E=9^`a%QN%B zC*Ex{A&zdiA!El7LM-?u)`|Yq(8*=auyQ=4@u^|ugP0d56dp7t6fQpwZc+)Q|N+w@p_zwX{Z5jJ=98&Yv(Y(zfV*af0`w>&DfCy5(bm9AnjgQbmp~sCq=c1UD#O zJfcgCGp?QpadI=Ro*^&ZmTPb|R83rQ3TYfS==X>^aP`W;{f7@8xN^R6T#e(cHqxT) zz*)Ji?O+#9;FWfEdf;H#NSb_LeoUe6kk><*Kn5N19GgU55z4W zhc!J_^Ye4JTaOr4Hc9U-SdKqh5a>SO6ms3W^@u)bEn!@@Ft8$jP<|{#cWhAZ0U=KQ zf$kW{^kwoVLiLH)-De_fW2K8!0&I21V#~+u@`nPz&swS{LUoDy215ZrH0??avwtZ* zXx=g}T)y3+?>N#n1F8e^euB{fS0W4rf`=6}&6E8p+m5wg@ElBw-#8<6)m+ExKS@@Z-wg`$Qh*Cb81`cn4V2_#^y$jN2}ELR+CSd zI3FMA+wkPTH#|!+hgN1Ij~U6yjb{$MX`lXVA$#Fb=B3TWmYr=2v;Nu!emYK_O&%MT z4`sVl)PB~?Hn(LcHZ+R3Jmw!B)Ol%JfN>aT9&2K<8%qfqYJ9;OHgTQf!RJrZ84X>( zt2L8+MI_YxRp&P`HI4b$QH!WPg_0I4o5>$p%G=*mhyNnGuzKRnIDKC+! z3~{pKb#HLad((pU2-VoVswcB6#~JTUZG(~&TSspkiVFAKKl58j*Q*o8cK_CQ&SRf* zgb_W*5|DWl{6_OXmhh1u$hZKVClA?pJ(6*$&i_~@v%=9IAynFJp1f^-p=9ICKDV!H zKYqEZc7CqY!zwW8_nUW#2RgnR9eX~%_M6SF!#Cf3NV>fBHT6#8=uDwnVfRJTM~ z_q5hw{kJpwJ-z1p^Y@&H?0DC0C^dvni1s~NEnEnv1#D(lNmXMWVfNkns=^%-4 zO)FVx?Qr#=);EscUhh4(xvl%^pbp!2<>l?Ya2ziFwk_ON!tSjsiGPs4)E$h}7Fy)m zXK1ppt4?EcFeR+6OtE&u&q~wA%T!jR03MeHOu0Q|Az{G@orQY~hTy3?=X>%qyN`(w2!WQ&Z;AN=-kl@+xbul!pIXH~VM+e;&D>4~RBpM`*q8#8A}49^YJWfWyS zqp_y|WeA*oZ^{D%g9!iw4PDbklwTAZW(@#cxZoQ40)$YlW|X8bts$(Z=HqA^N%sP1k|mg@Ouh zeJWg@{ZtgflpSgWicnrS^B$2%m-IPtrqzvWY9m4C)JDR2 zjG=;P#|Z+NP2vP$&aC8dtX%3VB-O-8s_pekA0R->*r}fA5ake?9bO(DkS!70qDyjl*Uq0oSz4E;c1c14a3WyG&yZ>eO98uFqBHQbJ=tWhd38jKp*3>w-DnV`Qho+%L= z2`6#SsR@s0;G-E!%-Q)!qrFu^1+V(uD%PjBk`2xGr7e${$krTU&g*06C6!?(1@wdP zAN`J|VTG6h_{KtZMAftaI)YzqCCqpa;1Bnj$F4F%TuWt2M~$A1xBGg|oqE*vefk3W z#=V*6o#W}^$$zfhpEz=C|0(gvs8^kzyGK71P9*qVe|IHs=?7pC-E))qhV9w&(LbqJ zC^AdGzTt`q!F*q~KX)JUoPfur!AqM<{om>@Ue(y~n9w-OsL@x+I*K!mu6v%L{X#R| zO%lgRk@1p5KjgO4i%*~wNN8LcQZoYW?oY|?_*m<1&_20awzw{QY@zE_v}a5f(q^;% z$?YkZnHrpx-|o~$D342h)^Up}H<&pmn3nQ>iZhqHKMa#CAQ>ftNh6+5a@9j-~cU^ z0glU;v+I?@g=q{z8m}+f{xlIf-kKM=fHCbOepnCli_)+PmHil{+-NKu-ULR=gnvdp zFye!*ZOLZTkJ0$E=k;_|i+vXpZg)aAw$>lTyCHO_@!N;953_Z~CpO!^D?z*ze<9eHMbxFmD zv9nw0A8I49K4eRI9w%QQauURYI``RiM%LJEoZMT|9&F=nP!cp} zw2ugOt4ik9KAZ0wS^GO7;cDrFn>`<95iAb?s|Q??eNSWRsBoY?Xw9(hAF=uR7fEdu0wjF>(tbmHkO$&zsm9s;zgT!dXK_?aTrbgtNbYCPX zfeVBIYz9P6#d_c|OgaQj)4?t4xXPsWgDizzjaPu9rcO@cg|k9!%GBMB+|M&b>^X8s zG0GYHzUVW~d~tzr?p{S1MgB`U``(tcVI|ew;nhQjbvcPzn|U>f{GkssCpB~2aa74} z)^A5MqKM4V)G|yn^d(JG5T{o=LVXI;OB;mH<%J8O?F;ddDqviP8@Dg4@@@9Rxn~oD z5)%X|m4aOO3y}-L6a1n0NE0$YylDZREXkVSpEuh4AbsyUx7VB5cFE#oJ}dTYEuHNy1O6~@=u3*SlZ?<7dN?{A3<<(?$xHq6kS=O&96OM9X zta>$}9Li}m{*`79Un9$$mr2o6I><5wS$snUz=1IvX=(wDPG)aMCYNqJ$SD&*muSLb zMRHcJ;TlkfDSOX@*U!t>`Rm-#K{UY^~IqNN+(IJ?&Ue6E~&{&{DA=v-UA%EO4Qt!EGSrvHAU zd#$Y}|Bgavv_dAn-X6-1RH~Aw5-v!oUEnV8^{2sWD}f8)_*?E-K?+2ee@5m4(PDEY ztM}VwKi^-4gUNlK`2@jL;^J?l9-!qHF)2fhtp zX@Jp^cfyJcQi+4fRNl_*@YEQ@xmZhQK;HsoSuGrClHpnC1^$xCerZ@&U?^<^WO@d4 z^mZ$62=@YGEl?F6yCKNn7?lw`w@Cs42T)EAlM0Y0lhMd%zqbFt<;$MGmHfmWo)O^e z))`yU4k(F+)<29S(5w=%;Y9dqP_pv%-dTV(hQ!7>i+v@JljmbgTqDnx*xj2ywzq10 z|7{$S~J*?w6~{ft{cVuYi+LQW^hp3n}QEXv)9|6b^Ms?`5s)QxoRWzed|ll zZv|`fYiCc~yQ4WjUhIo^%wz`vvOq9MwS9xcH?-*klLdEjMUM(@mIq6~3TfgQJUpZ9 zr(}6_;wugzorWEe4dHocB5XTeoGPN5wO7(_Rfz{AyX5M8XT)OC6dSg8*gVi}*nanu zsAa62RJ0{{OVSvz^11Bx)SnfzgY;+wj8emfrRoM1SVzO_Ta@fq0Z#NJVBsh=eC4CE zUDnQIJ<27xo#pPj)3OvIxrz8BuYTI`S+?6&hkKx>6W&5Wzfw-2=2nx)6-i9MVbzjjsp8YzRciWD%({jqi3*sSfw z^l7Sfc16-)lbXU#Py7~M8VNbImm8=#mJ-w%vt3(>t~a4{GJ0Vf`Dbgig!mJG|C?qS zzd*{~`6wUC%l++|q;H2GJRnVb@Xr?3JL5msXIA6fTFtZeptK(nO5X zZv`1da!qt@rv}D4JMTMBG)W=dJIl!f?BrgRnzUF@8qAUHYv1=1Kc`LoEFdT;d<@I40^%eD&Hx@CEPBdB`HnUNuOU`9JYyhV5J&}uuJ%TQ zUIn$nu@PVL`pm;Gl@ARQO?HyTga5SHpa10@&$}_{yMONJ!rH$< z#9cWi#}^n&7P481-lG;nVmLqXm$^+AQ@CXPAg)g4#p;cNP#?0OvH)_=$@S(R$t24# z=aD+YpuF3CcI(A545E!IN-QGa54{v!MnQ%uQx46?W-?2}B`!(8a7#=dPcM5lr!1ID~_KRO_# z8^pSDl)qU5lN~_O35A9~1y*e7UYS{|XR>wv5($dWESmah-mfJo z4*cE|bp5Vr!qpp9me1$EcpDcT3;EKsc1>{p%U#pXfJO;m#yw-~7r)*bjZe73yoWup>;24)BrhHZFI*mbfvOxH_;>9;2{#&x)If~hzl^(355{&t11Y=2SVKsYab;VHoah2~uLP;(az5f9Nr80TL&^)S`-y;Xf)%J0W_b2qzj^{m`FFty?> z%Z`~`x73Jad23R)J!l8%NJ_3d}+iGpvF1-ps%$B)o;^^4fXP!4$@4NfX zk`PvDgHj|qQ&5eL>@V&mEeH)EhEVyaF}_#*X|a(eCj2nJ*)l!mY^gYk7T{BAq=tCR zoIa-}WCwZ1kmc0d%W|Nl)p$Ao_O)%1(UQwZI}f-O&uOzSrCy{UZHX`OKFLN5zSEdD zshurXENk~hiXqe@WsP%^f_qISN7#T-KT1|ah!SSuqgaO5P~*?F`F3~L-JMw*(eHPj z8_g}driXkveB(yhS$TiccQ2#PS4aB2{#>QCyREx!Nc`E2yWNM^h&tcz%tvvfq+yBN zVXk<8`>uQ{qdb1rl8m6Gj69H&s^-r^)uu}%;(NoCQYT@?8*$AF>b*)8Ryx_rj;cdq z0>ctF3!qBge6O9BZ*nlqK-Y}SJ)1%M{ z9Wk%bEHd`juf1x@jkWA&6b}1Y6mx`0z=;$L&!PM*7=1Y)pp(dR#k^svNa8gUn_0~m zT0o%kNS$4+&;V>nd_dV)z}os&cb;yD)?nf_2}WzKmks+n|0>Tu2YewwfUdyIv(YkC;`BuY9%G zS2YgM=Tyz3gIiy2lth)+-UpF@S+Nsm|QGnS~whn>o5kuP33sem8W{q_^0@jkY+PgyF%;e3`1J(N+;SDqUW?H(Jt##KykmJ`){Sx>WU&=sNNAtPsA-(0sGE;0rnMOT9zTm=i z+u3HTEA9u*To5cHm|*yviI_sS-k4X4=toZ$UA{HD87b2@#2>J)`mXn^(=`JUZMUtr ztzR7SB#D=n!8mM9^h0eggWYN=G2vPm;LE4)twN|qsloez3fJ2+gzYr&hH5c*KgOZx zvb98;Ei>gTNH^j#Y$-uoM*EKx*Qb7iQPI5-?Yx{e&1)xHZe zazaI1wBm5wb!9D#_-#a_5&B|&qL>h>{Fq~j94FT8ikcMXvCBzq`#owS87sGS?wun@ zaR7liz&iksbw{NIvfau1E#xlmOP4rqh3?v>WW<@fc>!?pVl4MYdmq+$4e=~V1U13pYoTTd{@ zCvq3LKgGDqS38|c$bxX>VXv!v^i1Ahj2H(Mt!`~d*bHb{uVxAiVn<}?l4^~zgpchV z`T~N?NdacAvZfA0qRE*oWUJyQU&vT6kk^@JIXVJFyq^@urCggZk`iNzN`r;U zp$kJ{C8Z1YF;aPTT-6NL9eG%@l8=trGs)i=9upEjBu@y6m8MRA>ie`*?o(1Km`9IR z*JRexe{xZR89dzWl?T6q5iFQaeQ8*N}v3}ycj?` z?r07$usUZLq@5yHlp;qhLyTCTn5(-Bp(Qf;L$PiRfCv~uO>B!7w*_J(=}TxHy$9|; z6g~%Z>ESc<7_s3>`eWk2l=yJHwe-I9S%vY%M_0O~h%dbhe_^J;~+i?F<1?pAQ zUJzrJQ?6ETW=oG%1>^bvIS;#}sa!0nJm78zCFGPV#sF%tq6b!E45(Fc;0PjGD&P%@ zK&&%J-wu%)NjtAH?N$pm4|}>5!6uapAw;aCad-tOEDbMr-}7zguZad0jZQOKWL^d zoHc-$9l-HXNJID-8OSX?q$nHh!Y1XjG%_iTj_|4Wm046^1DqS>9?*<@+h9mpXdYWg zUmaV}P>@l8%S^7Vnwu%qK&#$yOq%*9Ut(ec9Ysl~7`f&hdge zec6HXw~#9bt;4b&Lc-<5rTK>FuP9oWTufSnN(ug;o~E8q0eT$bQ6)41`Q|9gfp~)m zP^|^X>SLK_?BR=~NPB36y_{G|X(^avauJXpN)m_S`@HTFE0xI#Qv*R33}4zZ zHEc3D44G03JfAI4&*!JlwU__;W38?2U6FLR#q%S(zaJYizfrYo_tozpR+R8Oq;t!V zoqs);7X0Tft&{10Cptl43MuzYp*G-gCcqg3!f>oE2Ue_u zv}G5Y;hfr|6+p_Rlj1`4R zgc>=bgSdfe0toJ&68MInqFsL+OX5}kMe3SlHcVbJ<<@S9es372rtRF^#h3eDT0pWZ z(g!pOiTq$y2GUBQ*`sj=wc@~yW?y#^A~CJRl#&n=hP?9gG~r*a@0~=~P5G@V7YW)@ z`piT{QYneMMKatq`l?BF)~Ir^spC@q3Iff*#_;O(kO(-zU#vU~ye4eAeRHQZ0HNWg z+!#Y_J52=xG=&e}4^(GF0*v^Q)&zrGptyz5uVNIZoW^~*K`yzZCTlN7vYwAV`=+2Y zPKQ`$hzfJC9uru#R+bcHW=Y&~%Z;Ju#yD#Xx_embVTU_XbBP084mqT=yrfH18z=|F z$X=x}9$0=GW<|i<&@%govCitVL$zN(6G(m4ntk`Q*qv5$`#qi8|0k0D@h?PsX#=Tdu)g_$R^C`~~s!C2;9CdoNdGg+i znwkE}gA{PuRK4U}OPafDlrUGi-*^1|#FrjkIQp-i52v0k0-tiy z%Mx7Q+U~lel8cAX&2AYu^}b{uc0nInF&xJuEVhjGPsJh;Msi+oCrQ9QW-7aCZH0f5B_D-V#fuuC$c0b17C9SWjLjt;p5#*!wDpl4m|s%cG# zwN+lDx6^OgrFWp(>#Zu#(O0d8GfFl4hEo`Lf&!Fa8kT@keokv=NVf+FG)Q8oh=5+U zQofHaydi$p$S9@VJ+h8ly1Xv~-PWw-;X&>AQp2wv$C_Sth6~K5z6pZ*$gj7onrU2a z*V@_jUg8A$S7b(+HpXEjI>gr@&A&xkfKR9r#{Np$mV7X8fmESqQfy>&f)KhTd=#oo zSBOBMi9SNKiqG$iehi*`Weh=She7M`t!WzwZfgO^c`zhV?ryd%feRngxo7FDw zl8DQACk-Y0O|isi-TZzw!m9}ab#s(8DgNLQtDCdPV+)d2_jaY<+m(cudb+xM8Q+(f zCh(CDWlxDMtruh;Njb=l_RV)kzSXKVa@K^$|3QhZDOZwCVN>+Q@tFZcKq4_I7_j2U zgrJP%uL6?&LGWmGe$_gz62@JPAJL}9H_%4pLo{V_O~PYEEYNDw$FCKZ%A$68lcd*q;`w$KAReyV%|oJ&{8UKiu9 zHA8f)ilorbARsO(*=!jDgRsL^Yg%<4=;)^OZKw2Gc6lAg1!AHkmw+c{R+YkY!bm6s zQ|n>w!tTNH&fJflnuG54y+R_)&#J{3#I18;E=1LV#3E4_1Nw%>Ao;QcxEn>H_X0bx{2I?+l&1^ybzja$A6Q1}nntwM zqPh6eNuE*?vsy5~$)cE;tK#UybAJYTtIVP5aSS(Q_l#JH#mJ0KDTcptA$r|AGv>f~ z|Nmf9ua5ro61|FbdJ@00&u-_(ne$Dvj(rD!4@ldA(CJh%uy+1YXwWhWgs-Y6++qO? z-Co-|@t;Z6uih`?1BHLT`R@JL&K&S72X)Sl>R5(+2~Fxe+8HOeH4dz_8-ZW0C(UnZ zEtTH?0(?Y0mrr13WfnS9@1UClt#)?zz1ZdFkwJFL9TkvP>i+~d&JU#lF-3m>+3la` zZ1Ld+@ueIb-9@FE*(;Ylt5}T7snyH|ChUmB(jBcqjutytW$jRUxr4G<`nH?0PXgjCZR~n5wK2_1hIy~nsy8z4Cn9-R3t_v=vzn7c`~lZ(-?HfgPP`FZwhEybU|soH z9<}}CI0a|CQ4nFAOa~?$`-c)pgMx_1;=?Y=^bA*t#ULQi;lR|}m_~iSkaj4=5;4j0 zA;T$0VOSGH2Wy=x)Bu6BuZd@(`Tc4XSjWM*Z7QoSG{WUN%Zrz(3yrh-z(%2*R1K_d zG51+xZc4aou(J};46gdyNsozp$m5T+UE;36?%Jz34iJ#<6XIBdo%uFte{jhKD2FUn ztA4z4R;m?*iAOOY=wXi{IxddJ zU^TfyYjG+MbTE$AwL9^iVeswM_W0G+u6P6)WYvj2W)OQbY|&$7Wr*Ae^rK2pZ4(2P zUe}=wNL8voDbj%h2-i`-t70kBY@vaa79#L1!HPRhKB$&Dj}-4$9XHW4;k(|iIt-@V zAZ{n$55%9>Eq4qO_o?DgI{l6?qBI<%@Xm}VHT$Ac1PFEEG_4Hy>T0)VK->q>TL+o? zSciT3z98xK4d3@S*VfaO%wHaR9x_zFJ>LCmaKh-kzQC!!UPk??6&a8ob#(N5Qk2z@ zew6RC_kSCS=7-)A;Jy%6zOy(i2d{;$uL=cxtV@*3Sisvr%5}7K5WOsZDvOwpI3njG zc=`Mx!-=cNbDXxI?eXYcQI{@<@kKm4RspRO8#abDL&j3v;~i9>E!4+ZI0YvBRHi#f z&=H!wm@KXmIz8DuvTSvoVp=JXMeA57Wg%j)Op3kDE)j@i79?6=j{rVGh|8B2jfclX zNAuOL@oiA{5tImEW|6cV&DG_%8kR)OVIEBVr&++#dufy-7+;KOY-11WhLD$cdx}E+}OU_P-j2QP)KgP+iCXOG_C- zQbqS~C`$=Yp|!8la`@Vi6G*Q>t8bEv!RYq-3>>je6*+y#%0$#3aG^{qE!Raf;-ms^ zC^r|?Tsn*LQXTNh%?`4rlQZdF6){e@faHBS9oj^oox|5988-z*(xl;9GQ)=1d)aYV zQ+9l|VIsM=6VeMAfedAQ+TAxQvFM4LyntFSNRi}KvZx@?s2tsz+vxE#q(;6ZX-0D2 zMfc%mNeP*eyZVMR9!o9er{2?JPf+8joP~sT zJXho)g97U|v1_5LJw<4oqM?eIeJmFWO4IaUpe| zQ!2E(BrPsn9vSl33|A9Sci^(N?Eb5=+Jn6T-xjW%S|3M&S$rp1Gbi~pw3dNI>VC07lZ$982R`N;a3s4>KlO2u&HLEa#7*pkda|!;##T3LI zGgr_3<&>7$Fbtq53yu8Qro4#It z{(aBEB!LFS`<>%aclR8YJb3!t&C1c?o)0&-4uSw3|Iq%n`>;9g^sG>zrW|Vm>n058 zlD}mP}qU*QvxQ%=2*Hy)hqgAe5MeX`CRrj-ST0@H>-&z{vO|hS%x1VCiHGa}+ zT4MzMjSO8xbPB$~VPetN6e~9-c6u7&p=f|2)|(*eW`$EICzltzluc~lR1|kz8X>9# zTX=(=l@vBE=o8A3(63(q7LroQ*4uC~f( z4yGIonDm+p3!4km4h)dS52UVirGDz7A%gLqjm_vMIew93M?V3gq#hzrM*$WNABHqq zZ9pU$zE-fW;{9A%1fmZw43iXQalG7(4nwrrWy=#TE?KAXQFe3>VJoc&s<(!-ttEGGUbDKfv??Jk& z=x{)^EM1N+&rt9?fj^1=1%DJgo1Y9?L>eKvM}tq=Ckhl9w!vD0h(33KPyEo;lDH@EkeyjnUVcw`Gi z^xl0)H~~Wc@1^b%x1#O=g4R<5qIgrezbDQA6*Ahzn}+DH`wxL#N#zpcP9+a(t86lye><)06&@o{o_w;i*!-}qs~Wj>=Xu= z`^p0bG`g!Qa5`pxbcA^!#c+$BfCIz6Vh9q8rI{ST6=|-_fQTd_3?}B+HF>+&jq8Bv z{Ya7>N%^XS?q$jK37~6}QU2|yXcl}Gyn86e`k{cVo0Ltf73@tUi9?jd;TzEsjlGa+ zrn6j0N_q8OBS>T<*@&;if20#0u*o`Rrtgj@5e;xq^t?duQf#xo1>I21&UMi#m#MBU z&s%{K8A9+rd~-IEiuJS+V)O;*AX0Uy0?Z&*yL&}?zcm6*5m?42M+$`uzJ`q1WBKqD zzJ+4~cp{vIr$u925@j=?;v_<^39Dg4N5>F8qWvTIJ z5b(|MX6_{BNgYowXFsGJDN-N08X{s7AqHQf=!vCPkkDcvOoCy@N;!w4M2U@v z63J{nJ)7M0iwyL6k_D5XX~sl)M{m#Wk{2z=w?(9}x}xp<*#$kn%_T*3<^AZx-;bxgySuxs?Mlz0w9(7%k2lw5tb)(3-~4lzaYfdHySr;qX?Ug)AFZx; z!9ksW86uH_5bxcFWmDjcqp)l;bjKLg&vp=|?91y9WtIB;$z8fNw(c733&hCB4-t`m zg$uwqotL?KJX$PVicZOicdkE#{iZerp=wgxNnpk07Bx%Y448;Jsk)PPiYQy|n1w_! zoV)I019PW{2~ho|tGU`*bT3tHWqF8$nvgT(l8FwPFV&BwkW#uAu|5lxHiAKvSdIJ( z76?czmNK~qYQYd$fI0IopqWIkT^9Nls8&uZjM`%G#5H2~5n<~vh&0{n0i@hOl$}CI*HnQa@^w^U*hFnCi=^~^GnoP{|u6FOH~sg zR@;^6#RdQo%WZ!1b-$f0)8{rHx3}t&$}i@cuN!yvyWa`L&88Pp=1;B&F7;u2{!v`rYsgkV_Hrv!)AA z@_mvukn!tFeJiV@+b<8&9*WjKgMhSK2H7LS71wph%1pJ-M7z&UiV1L3t{s>=$qtx7H@D`lf+4OAI1Bb$yW8cEz#IC6dNaEmU2QEd4X-`y`+%sn zYqR@k7~S3=njLahCtHslj!$kTn2DAkm+N+=KFH`0tdSm86K9Nx<-}4XMr>4dgQQrWPTEdK?atQtkgs!}2g-Xa#l3er+z zik52E;?*^wnCOozP0XYW)L^9w>htD0%SeuY87tiTREQGE{|7u;28N<60IzZ|xAw0E z2M-#HZtM&d_=7C)@M*8asdbunYuaE$?MDrZZ>t2@lju@;vrM@Rov ztKD9j&KIjT%(|~+qyil_w`B!u6Pco;jXq*FMM97}Vb#f{=hTe!iz~RApy{Wd<{j)N&QTU36rs64hXwv`x?WTtPf$+=Kwclch=7Go$fzbPo_9W?JI zMt+)>{%P@FMrmlvXO|YLAyUSLnJbSTsL?=E@*W|m!^*^Jooznj>_qlrJgfHg9 z+I8=(=lu5-z|`?`_gAev+wMO!?4B$2H{CiMT=}RySAQKGS@4!RC)`V5w~$oDFQ`LH z7f2 zPEi}d+3*s}B28k4?DBgTyX6sanG=u@vWOkUEbmb|L>E>`ZI-6_*UlmrW^rG!Yl|%OAQ~+ z_=wTzO)1tP2y!dSm36Q|Sb1SlJ|RpwdUaPnKeBv(M!aU7GtS?P=bDcYn*y<0LZ71= zyHhzb-3rctltSR)#40zjrAAH3q01iwsp1b@`a~QFKy0&m)tD(g@(T| zulBb9Q^6`mOwX6xe&=<6f7y-Jr>8f5jIUh>Z?(2H4sAvCRCS)%EysJ=b#0+q0=(rK zIp@8rI}q5wceQTt-eGzEk~8{=$TN!his7ZyD9n;{Bd&ILam;#{e2V-6p-FfOen*&O zSle5Bhk6<_g>=`gE0kvT3%1|4dMmYf#3~sCTR}8Iy)Pfcd^GAjC5F8-ZXHxk&J;y@ zY4(#+x6_VOUqD|_r57Y>P%4z+$X#_oRrvRP9^klMc+(L$5zX zmWL`gW=0ATB!~B8>t!3TW3Utpgh#J3KF9>8BITcnUXbxGO&x{}K@!OJk-p9f)evc- zuw4or#38tt5x6VUh#y}rLa~FfMYxRwA=a=Qt57JD3K%=r!TOT&J{+Xl(i-V$RL~Hdo|w)gg(T8R(R&hYNTOOo2&Cxrw7d z4(Q##{hB3Q_CJXF4nV5=?|*ymy)z=Notad2Tq=8Ik82A>M#;`z*|I_zmuv}T%gWvl ziHwX2Nt(a&@jT!E|9$z~i|e!Q`<&M~?{m)UaHH;(<0|3#MDVLRXq1uC)-)(_l62YP z;6{H*bLSN~!-mTw%PnT;d|4Jxx+Z%3LJ{|t66C=@KT9Z?rOX;W4iS^DNO8bDDNPJ@ z49)_YItHS@4k3k_?2mHgCFH3S;zlOJ4ns=(?Lb8;0+m7VjYlZzS)-%vHU{34>})~? z2EQ;*f_}j;=S&^?G+vQ%ecn!-T2@DGS|;WUKK6cs@X+~Cq3A5SERQyiy{{YOf2$UD zJZfw1ojLY(OdOho2Xhs!gP+ub|yh71ImPs{A3?)1^ya`Y$Ir5OG zLsf?9Qx5LFy&IG1Y6tE|s2Pt97qrjHCgaR|?b}C2@OO~Lk;Fa3S5a9ZS}Q7y zU{HJSoP{%{Cd^3|my&=JDW+y&D6MEnfo2s^G;}T`Nr`4tt+g3uAPrHXkD&8WwI!IN zChERzb14;nWeaCl7T@MFJ8{Pq3Z<*noOv{l2=KgU)jDyq?mgzF4V*-NjL^^Pb@fL!h!w>vJ5qdL z)E$g6l{kmzbs29$NrQvH7>_RGe&~eFKuBZJqj0uUjnYc)Y^Kt7sz$COTHMs`%V1bJ zp{ZlouvE7eVI8@b!#(yDe|I`&JS$SI@M4}=+$V*vlp{h1SKcaTP<-G(Q8`O_pIoUF zb~9@9tyrjQym%dRcxTz?hO&9pr5grc{{&s4pWm}IyKk9}YUMeZS9aGf&l5x3+oA4ZQ}`&dC(JKUHa8%pB)RO1 z0&|#tM_LD;1nnRmMR-H#G(MJN%v-sSa!a~!hI>Kz2~R1-mJ{6G;L=%)bluw9n5HKnwzc~ApGJ&v+h=S0NNlmIKpWJJ_GY)T)V1%5@!^X3G zvLpW9#}$5dixq}}k~DI)qH%7jh{8fnoM1xQLS5Wpc|i%>nu|Jigq^8;+@kRdnt1zs zS~xY==tIQVZ9AB*ORO;Fz94&>5i&d;TWBd@yF#h{#1P-b3`Mv)hQd#=4N~%>*89S) z(X+1f#IW2(h{>Xc5v^24uI^AsQ5=rPElCna63v0txkqxXGrL)r${jQ^*dcs&3C%w zG@Oj65XLb%Zn3Hkaz`suBD>FGxMeQhg&f)sU2yKxaq;2Pe2?}b@-8LnaOSXZCNJGD zq*%LC!%Q~GEt(;r3)ZCoe+&;;mjiwN!;hWd=?+E`0@0ilTf-LxOi%5~4R_3K+4Gn3 zSo32J3{DR0_f4~R1B8#`3+Guz<1GuN?i8L^jwb)-gZlcaMOy1no;clRoMRHx&|{8% zDk{wNtl{%Vj~C~v2!Zotw;oeO;<}5JBf8tA2|S1A-S&I51(8lO%S}sPFi7UyjIr{U zhXL5%kKf(FF;~!ZCl6Ac zN)YjkM}HxaRPsBELwSZNA=J5r)Jrh4G$h%w7nf3Pl4w96+C0=aH2Ms2=NF35mXv5F zQd2Zur<7Jmnog)Zy;j1b(2&Pe_}sWS8@M&Z;iUsgUi>bCls#1f__#9sxK*S&L{AgN z@X3z6M4ubuMqtT8`i%LN>_s|jD2kIgaNas@D9PklykVgfQ^b!x?C!wnGULVj@*T`O z)h%jVhky?_;)!b=qO3X{{LCVTRA~}1cN063Xw`IIs7KV2tuXaS_&anA6h0>+2rTm>B0j6Pg7c1u!@teLcFA|7fBbTkvfAAh=+3+R@U( z%=|{pr@-r*hbJH9Cw+p2r?(GYo!onEZDm|J_~Xa#&x<1InLHNBDz6QBH?V_QO9!;Pg?y&b{FdERddTi(FU?a zJX#xPL#DA&!g0bm=Z=xkaFr%PLor3F?&NblbOv~o1c4+Cw1SYk2gc|x&Np0w6g7_F zBCIyIl{S>q!Y>fLkn60(#VYrNKc@OXeU|zIjfA>C?J~hOsb+Z5N;}RF#Rq1a*M#3W z-iX?ux_VUn$aHC6M0QXoDSTPKJ&K2WdnZ0Wz>8dcRP4OP_KJtaP9OE<7X*BxZ4QT@ z3D!r&Bn-1{$bGeta>EKz*GD28BHlJ65A#C?HkZl7jXsPT<2VP7@&`Vr%C8(K#NzPU zU>U={Xt)`;iqbU_rMpsax>BHe*l>O__nLO`k-R#$`aLvNJZ4LrX2bT}#(A8-l9|H} z`Sy&34N3uFV;2Yu#lyxf5jrK(S1+07#;tOw?;DFp3-<1tOT?T+K*b`StVGtZU4f|{ zAq@$bw9f=XvIn^x2jy`m78Zj%a!G0*V20epJ#jYe{sbR8I(qD4$QS*NaeT1txwa(B zTQ@xi7uoxq@e>+bh5fAh#FCmF9orT|lofvta0RS9Jsg6x#TP8IiY>yk(XaD%ocvBXZ11~Or_(y)~G4Wfi-i2^AO65}1I3=#RaE-Y*bTD)6^}>gxorjJD8-riyNh1{N{d zQXm_UKZQb1B!-MXMOzzfFj7LWMERh3pwT5%{=XwZ^}pd4QB+j)Qg=zv*-%=}#B&MRL*-rV zQh2UfZ1#-MpGa%?Z?vrS+4m=LDGJal9!l0ruATni?!RA?HRoNkVQc%U%eFhB`~E}9 zZyW*~@;dUjYUADIhULB9_t|!JEgw59<*hU4*F#YDqC2+a)kwy*&wf7Bvw!A+oTXE~ z%BdM@sCVFZ+7~^C!~#Km%(wE3B7+qnh%{U$YPuSd8w)#A-o&%MQF zxbh<1>P)x^(l&Y8$hd)QBA7HaUF@`> ziIKXaew?~b-1KB*;H~9H$0fhFUI&UV$IEk{gn30>u<2~_VE3?@bS%D>kx*CT>3)^3 zrw7BAQp=G<`{Ii*IsduTM}sLJN)C+a@sd~dImlFO^y%r6-3{`QhkhZfNu{!D{me|*!e?vCot^3`qwVeL>Wb~{ zc4x8HMM8VK1`Mh{wzk&XzmiM%TI{4Wh0^Pm?c@*mWjwmuV&U?$ zFLRd7+JAAL;K>sE)Pt+ra%F##w*Dl^Tx1fQk&*Mfw)hC>PfP^nT@$c+t@I8J#dhx- zz$XDqR31Vd{+KUe_}H2Ys1%u3ZqMx zE@|D+NA>_?N*acoA#6^E9GZoam2TEEUx6jLDh)m}K(UI)kG%iRe&HFTx`tmjxfbH%#{?h*rJ~>(b zQ4%C&==21aT0yQSmg=ISwwGF)ot>RQXjFau;QUpugV4Yz|2XxvR6apjArGw&LNoz4 z;RvPU2_iG#;Q?aT>Nf*ddPjHcpT19-|LTfn&rI0qN7WlZx$qSV8TBXO#(mxQK2Tjl zr?#oJ^v~v7XdVs?jf$Kx%`;?{e{nb}ZlbuqnIGJu@YG1a7zp+bp3a1AGILsN?^zu7 zE#Ln}*5OI^s@)_b;CQxTf3xe{6*}YE_}c`c%B{LKk!4bL6m%N2SzWxQuN19m&zi*X zwviNKX=4vAO6E(Z%*XFr;g6YfFok?&im++Bru@a-n(qmZcd(Ox%1d;`%%SoLiPRIaXY!D2YoZs z0*2d2SzWr3fty&%^r+&&R;THs-u*R_M}4%&hF*&G3Tyh$*KRcSIUa;GK-{=WNR!5J zyUFSs-SP6LJy_BB*hkZf`ZlxM)E{qe((L=%%-){Cc6Z*^%*;%;#tO4@^X0qOR1)n= zb^Xn?p>Z_{%=eA=IM>m{)xqLUs z7H|`KWIUNfZj%eWfe)O3TA1fQxe=b%YP>Zf%9zyhcuFFK^R23Vz410p00z^yyTpz0 zYs?9sN>@2HrZsxx%rMzwYlk`PL@dkYy9jBN@dhYMq|@}-G`mzaw-}Ws2zArQ3e`gI zB$dc#rSQIyq%qLn-=6`DeDYF${-e;*Msr~1F&Wa0ID+f$r^U$SoIyWjni zb*m=JD@%K4SMJMuiR{hIKW0=MA^=j|O}jg?*x+wwa!{pa$s)dpMAy;npP~5VGXr-p z!T{8sS=8O!zB}J+w+Ti0kX{t)9T*tsE2@xIT3U`mr^0!J=QewOgwq2#YXuN~0_PtU zsbYy}h*C;Q%Ebn0X}fSAEXqt)Plb5ANvFn+YjMf%Uj_$m($_1qQcqLH$x%$r`^hy40iVRk# ztE}eo3!Qy??3iw;f#`inc6!MbI}Qrf&@59*WfF!Yey3D`Dhwfy4T4s+!c>Izotmc4 z6w76WMq>49(Te&>{1sn)b|nT}qF^WEO?&K~unC-~oS6=MSz|0b_~W4MxiGrcDDIMn z?@Z+-7qcC7Wo1RnZ<8v*)mLrSRtQ%0n(iAb8s!5_)oyTz{1wU27H0NPc93RLRdzyC z{1~aZhq$?W?KyGpjj%u7?!G4BJ(>M{QQYjlzd{fhz}L{==lnw`A#)S9`wn1rxoJ^> zHW6Ta?ba;2wS`AOz{AfHzc+X~8fap#lzJw~h>!mk{x~O5EX&|Ikx+GQG0ktCvr%JD zuMU0^+bp!D#O?Rw@O$6y$)$WJLQ9#4*NCTiCsABD;d!-uo0a3w;nx9K!{nWUMQ*eX zwM_0ByXv`g2vjk6u9l(6xO)t=wWJ%;w3VeD89^mz=(1hAGyLqSEhoL;78Rc!$5pki z^Dz;3u1c}S+9h!3KYoUC*>)Ms$;nA)OVB9R9UD(W!6aa#OGHM3%F9+?WJY~Nz(xq2 zlUkBC=y*O|;dEL(2Elt~IF&9VgGz_0@~O$GNjpZEc&t}7U_awyV`+Ez*%Bj)bwLV! z{q`nKAM($H1_OPsUAv}mYWm!`0Y;wxe(h%V?%}WD;r-h8_WhAbREqwl-tj<^d)S-& z{&mEwE^EN7SKZn9?(hDdI3NNP-@S9u1Z{mPI7S6Xf}IF9iy?GJZZEeU$znMZB)22$ zGd*gy_cLhuvx<28=S3jRX zn5St7?8>2i@}K@EMCSO}@jf~j>95;?`tYj~!>LmKYuC_EbJMVaRD)zBc3tJoQE3>1Ciismvl%s2dMGax}|!YqMSkxdOj1m<@tNI91Wtbmnj1W zPPV>p_`^JlicJ$1vFl|m`bH|i+1qX(7dInYQ+qouZdReiXjBorHwN%D^6zgf*S}-! ze6ah$?x5{wxOY|zE` z38TL-D?4+9jb%NjueHK^A&y^bMXEuE?NgV$XB@X0C>iG%Pbusw(`d}y6|WqcOXHfL zUgb)OnqtwZRp@-#vvbM7HJ(YKbynepU(575umgh|$#0lv6IR=pV!F`T)dRqWF7ql^ z7{q#e1Mad^2dwdrDz?tVC|c93O2lo@8ryT-_uTzd&(SltLF|4TUHF8QTMu7TaL2ZH zf3wwN&oN)Z?RT#5#cxycs=3XMP9E*q5$sD%U$E^tZ~EjM?>jc8KlVJSZT4tv702A9 zs#{=H{MqN0e~($QMQSF*h0x|2q0M8Y{0LWs`O!P=yG^T}TOQA{HU#@645!R3%NmK# zzHb&-i5zHfDQno#x7ms1rWiwolJV=F_3`BMHo?6{+Yq6ZP$I7B!Tm#3izw;T0SnyB z1c#W2`tpHEL4c+>eX=>8<`tv#a2*eo#xUaxky&xqTLcnX1Y(m>AqRxI>U19;rm}1D zXu9A@Yx8>0y&*|q*I^L=T$Aisjd9S_Lq%Uusyhpu#11KURL(veVjZ5Ov(wRvcNqlH z^eNRh1R0ZdRghszP|+Jh1k2T2Kdl%UmX@a$p<5|&8ocLxs)0~ig{!OKc4~g!^=H{5 zS{YROUyB(kTwMlz9+#sKoiEAB$w?MWwblCsPT6a7Kq;pi(-}KhI?ugg-ACg9lBER_itBwQY zv#WltA?TDElMvvnJwyBALcP3MeUSU|&x|XW5m?b~9gn{V;XsGFD)Qx#PXpL`vDoHz z@TS0-x&+$ce}h=zX46afvJ}fiBf13!sdD1j5+MCjtBQU)>OZjxxC=C(P8p$C+(>|+7XqL`c%Jg0~|0!NJ|&kWB}ERii=+&Cb*yp7^Z2Z*UA6OuN1yonI*B>{*f37lsjP6c)ZdZxshl2sUVwUV*~}Cx-Dp}j zZMS1ISXHg(CziW2c^@3J;&%f68$mf6IhbypIhXV(58EhriIK2qF9sFhu!ZO`we&Zo zVR_c5Ly2V!6Jh?F^nCPi2UearqN7coIWpAQOOzZh*}*X1FuqrQUx;PHy=F+3)zLP? z{rpIjSwpvMmWR!nW3n;!s4>66WHx>Met@+#@O%JS;d8S%v8K8mS8VW&PG@o9>D6{~ z>hzW0JMBrviZ}Y~umR@wBe`;$pGIEWum0?3&dh#*FTM=e)MbO= zpioY}E;iAQJ`$g*wbgJ(4cKbzp_WS7Ulf=2(k$q;qMO7dB6QD3g{DbUw0hH_p7LK8 zB7HPT&tGy*TeIuO2J@^$o0ZGYerpNNdu>zltdXHv=Sh2~*=3lt=`g*l%nWysJ?V~# zM1>l%#KyQl&7ImEbTPrOkWkKb1J3LE((zAR$YM(FP!#J)$1~6|8@4>2Mkr~!^o!b#f;ECu$px|0 zM{8*roQ~_y%B2t^(P`sB{ixL8rIXDhDk&~S43lJjz-E3xeSba^`|+17?eDh{6Y^c| z-@gZM0Ph|WtOUa{h1n%cBVr7;uUA%KAV`E6d}#nok+16=&Ch_iwbxuHw}J$uygkcD zmv#iEz8;|h)3t<9u12SG8xbm51!NHdd{8iRi;MKe%g_o6>=g*^vC*AkBIpmtv)=zD zND16FtGWQT-*v+n9YmTy!RQ;NragTMisvTcz#=O;r;4b!xCoI^WIx^pLi}e-(o!3q zK1Iw0xQ!(VC?}b4)itTFkohNdS?WpwYd(1r#VFMoepBO?^NsqBYJ-nZ>sskNrVG0k z^9TG|>6Z3!#F?^9wT;o4@{Ja&-9wMfhVlZQ0n~pdeQmN;`PZH>-UI8)DA`oopfkm8 zzJc#7N*Y!}B%E(Kly4y(Fgi?9)hZ^9#~3$tw*`&Z z%W{t-I;Sngz+yLRVKtddJ#|`YGIcvpak=%2grKOF3&@G#@1^z|buOy6CGb^dcI&_b0JDo|n8)(DE*t0yE zrRv%fZGLi$B--NZc~0eAp0emGdA}(zCv%ll4;8k>sAe2$$fV?gW1PI|0A%kJlk7J% zJtUlyC-jpiRE$Q&h4U;7kF1$1_U%Vs2OP)dW8pqYn}m5=;Xih(G_{Sc-P0=mbglJ~ zHy%IYqFs(LZICnXUTd`K&5c(vJzeLTYsi{7~d?M*KuR+SxF=g~#Xo zDOKskoc`NT*{YSn=z@kxC8Seopl<;1#>t7w&wv3gj^NhR9TX!>u!&HeQbY#zvvsPC z(+0JWpDF;GCQX4<3>eZ*B@$z5RgOld!Td#^;v46`jb02Zj94{5s>jN-E1O-E!0bch z{@>Y|E~HZe{{uGJWB8vSY=g3qg-9l*=YT= z!H!`{O#S&&e%BJu{?kS0DTW9*WA%e?klk?Vbt>OC+x9mMQaq=))^qN$e}JXl zwC^?H3i--(v4#RR6H^Zl+tS9kDr2#xTHnSYabv-D%d0yHgD;M~m)F|++rx*kT~+bs;+s`)L4Xi;Hn&ugT?DRL+8vymYUnUZHtqT64w z;vnx1bv8|ljL}+^YmdsVnH0!rmwwYQ=|(AK`_z~X(=CEMztCSzhWRid_gjVoTxe-|cv((s(|s1Vt#w%@C%gCyBoqfEQ=^_Y>=!QMq( zGfMKGSDY4gEd#6_e~x%GIWn$Q)q}sbOmm$c95->Zz&6fB_5f_VN3E6Q{87QpTW&Td z)~|utJ;yQdP<;6!IqsY(+r2hF4q|H?R}M{KS4ti|>8Q{WM;=^tgz6r3-GGtbfT8rM5V{1VtvPfwA}-Dqy#L*cE7Jex z`r2qM=R@2rFRq8UFZda%dl9@WwR}~4l+)Fj2&a{vZ$TTQ*L||Jgwa|$RWLE9ruu;}v=(SnwaR4#YX9*&?G%tugUnt> z8I}aVyZ@H^$J6dq7;&@AvtpcRILEnxs zqZw{e&8_^o7w3`1$kWuamlop7%f~O%0cnsc&DO!flf!?4k&`Za(Jw-`Y*68RVmyLX zrFw9}3g;ur=>Qwc`Gs__*VJZQfrk-01x(U+W%ydkIpOjL2S8m6uKT1_!;L{8e4<6C z+CXsD6MWlo*qefa5$jcLxC`JlSE!>;kGAg9a(Zkyg|2RdvfBF};_#k_p&$3NR~XOr zId#H|FJ<3{zX$=VDMFwz$9|m{72*j=RdV1dv5Y=Ku@{^(z<@8cWbcME zSlbvy&S6Tq!(m}pyB_n7G->Dd=!*QG?HS6MTDF-pRb?|1Yzw&@9bDWEL~i;1=fncm z`%LY~L2r4Z4VsrC%pOZhkO?8WkyjwvY&25Vw z@g9xo>AAwsF%k)TKs;zQ;=m^|uQ%_}*u>ElyfBiUSKo(&8&}}(cVt6kQibO)jFYh4 zk+Clw7Yg2=hak>{8WyJ>$US!{}5#gM*rYX zAtK38(v4olQH10=_ug&H~S;6$uuvD=nS<4yfQ-POts4~cQk}3 z%lLq#zE>4R2E?eiyitaeAP|aCoEwJq_gf&_!I%es3r?lm@0Q=SRwi%* zfn;>ys~wWnlyQ^EwePrn50*bcrlEVn#eakOz4^Usi_6eeMF+IX;DAM`Q2L;wkOek9 z6_nQLwdp)H5h~RK732thEhj5zrDDNBBT>cwgg@2M8>pPU|3OI1!C-jv33#2qU4jcR z`~SBFz3yUxn5)&sut$Dbey|uoz&|>FbTM>853? zSOiQPO94-#X46N+nUlJFsNV>z{Z0C#9C*c#dMSLjA^2YLR=@qWAq9 z5B6PutWK|c#aQaOHtOkD8!A?iQ@?7PoZEkM9^Y$4h6-PIMTQICJ6@+xk}E$+%H~j( zTB>-qcy~^5p>xBX3)8uwO$^{F+iqrVQaN~ZKLEkf#&r)Da2lu6UA|WqKrnCGxym?p zVc*({e0rtrmH0br@zwdHLyx4xAX&3!%u=qbv9>~=*h09-jM+PeVt-@EBnMW|rn=Dw zj!<=o{eBbb5`)|dPppAT%Pfdf@TxJuD{z_9C0Q@K0nXBTNPkxfW?cKSqIeSWbEp4( zN5IeiqK-fg;vxyI2e?~iQa3erSj^HR=S9T!N*7;vOsrjxd$^>_c~#Aqla|aWHcneh z&o##m2;j><#u-d9Ju4B_)-=yZ-rf)SB~Sgz=JM|k)R{@I+U_60F|Kgo!-k50c7LX} z*u!4CB~fgzcYItd{)v3NJ{Ovlns@49S~_vs)ENWa``47eHar|pQyn~mqR9xg^>(j$ z(PYYl>MR1zZ^8e#+>+LSZZBDjNLd3By8*O`aK;eK2=wXlV7fNCJUw;7JR^19z1mpY zu@0VKs+7B9VNR7>RO_SHUDLvVnEOAD^4eX5F)wNDgb;`)fkpd}gvr)Ll)t39n0^8Y zyqlZrmmvE?54iq2(Lwg$pcbV7)jnxYk>BY*4u0_Zcm9K1#reN~0#5RS!5BSs$`4qR z%ubSPnhC-jDjvd@Jdx)8y%UFvOL@;VtTB)ngV_dB7?F&-(4M4f7x47$PPydXyj*+k zuEpe*AODjyi)wQ)5E|gJ;Mgr@qHy)TEE%v!3>c_Cm0D+< zUg~1ZfWU9$!;&EAJ_O{1_Wy2x==dX7%CA!4jKTF15VKMjb7Oc}*8&&Ej~syiiM4p< zkR!^7lPx1LBja&eYTZro%+#r;Ad(X;Agif}5@RzB1~zzv`u!nK@pqnl)-&D!r~dw! zVDKji@Voiu-^Yyk``h_xg`No7ps5G?N8_m@oCc=D`ev9>==;wGj2O@G8x20H5HZ~z zst)i`!neptHW?a{gvT}f+H-mWYf%8V%@?5?aZ8^;6;nI@qqP?lg)RGql%o> z0Ra{VEBm)AdjaHDO9pG*^wm zGVPt!&Fp$uXeEc|HpsKWff0fc_|FIQIaAmrkv?KB2&YH#2*vSA?!}@1i-1N|uHnt#6~*gO4+%4kZb;`71CBJ{ zl1)V@>L|j`yn*fkB^M~UQ$CPQv{+zaO1-ku)}IG8o;IX8l`xKV%}lAVW=pBC%1Hg% zbW@nWZr%l%*&x5CAR~$%FgxS??Ml)(knE@Y3QN`}Q${GdlP69&xx7N9MW|Y>QxZV`bC@lx58q%LI5!Tj1Ko~)+eM#D_+kgK8Iv$RWUO9Bi zRs6=ZJS6%#==jg>9%i6v#{Jt3_@i9G#;p-(ak#O(lvkTbP!=R;{NhmVQt-B?7DM*e}$tBWf;wBt%V&Xq}LoNzVLX`ht zJ^+Mm{oo`}FIKJEI3sn!`1Fd68B==ufsV5OLpXpN>6!j5MDv{xT|q9I-^INNWOm|z zx5w2S{>PzFG(Gh|Cc$xQMutxxo)54>{0>c4nL}DG$RVGkBV$9<*RUBHtK>QnTA4d|^;;EUW^r)^ zZ5FRywA}ah`LVjb{T@|UhOS0fy>+lydQoA5*us10`!bpt4kTw-X!~P0+%?yFVr9?X zExA;}R1@|!Y=j%rMdZ%y(2!8;oG|KDJH*R;_73*7H8`S>i#YMB?Rk~38ydR6-56}N zG^w869yT_%dpT@kR*C*}KgiZBBJilk3=Y_{GT*dmeOI5? zG-LKE?mcS8+G*x~{4>(o&k#kt{7Oi}-`EPuww}lNna$rXFmt#14)oi5O-ICCP{zf~ zE^_BOob{~Rn=>7uzesr6LVv#D=?LQ>;pvEyh~e;0Sw4N3cQF}~a0=42D#cLtI6IT* z2Pj3<4-rI`)M(xm6ubUZ%s|H?Kda@Eq)(tN$|uWMZ=Jxku$F%AfcXp0y|$R2Zwio& zbw?BjiLH$~i)L^DwXEqG_XeerqHi-P7h-7nOEexo)yU5Z5am6alXaq{8&XoH_B5MK zn~@~0K#ZPwh@iKw^MZSgt`&dR{*asKjq zjj+>+6Bo7=EZoZ47Ph|q3h3G6za*Mjirfgcq4j+%BE<87=GqbsNgY5BEE22f!T}PR z$jcJrpsjR;i{&xpbqXq8FDNG8RITq&$Y;qXSOa<f~l2#n)GoN{zs?6{-zb z(J{r;&_UlUg2@lDPw(aF1#X()`E2G(T5KP*Om{cFttQorH_1}J5dR9JEZm413~r2c zE2Cf}lb*^E_whXAZK$MNaP~5dk$@q%lHrjf)i@0Bf2E^hNUEyEY9TJ_5eoilR7sEJ z5V>B)0_{dAZ=@D*U)Cw>ygdqqAssnnJy_!yX_IKCi)KsH>C+AP>dH~(kCcBJcm?!w z;J3yV@~L@CXzO&@l0^_^1RO!U&vD$T%D2ny4S+}#_yNtdkclmnx^xJAU z?mFW+Lpjqt=L!#-z1x)uVgcTdMqjl-rsw^=xYc0sn1EdJ;M!P8BC#Geqi9JD?k=oy zTrCl$j5IsR%uSP~Z;Q69N&T%CJ(~P`>-U=KmOZL#BAc2UGiK)7c#qwynsbKct0IO( zpMPGw+2?=b(xN9G$zwTrqT*uw(16a+mFtEMW#mJTs;RAfSI_19dmY)3>Y5XCe}B&0 z^UIb-z}Qe�}-!Kvtz3rF*Sgn!J!-$(x(QK)SG06-9wg${>lOWx^pAxm;K(C4|k6 z=+(;7!O@b^ie=ywtW}-}qkC$I8*zf_#I<*$7V-8D8dW5fxPtSEcsX~p19MbJs%wSn z-M=6Oh5Gb!;o34xwPg*hdd~dZPw)qrwKctY*z99MMIq&fl#(C%l4w996k@v2)zARw z117^v%}hc5FfN25lRA?^BZ5y=5_*2sQjabc}N* z-KsgaHz*t64m@SU)<5N5zIxU_h_8Dp@nIdp$q2NmIm%a^7l~@It{Qb;+d%<=(AAx| zzp~Q!;0HrE|8Bh~+y$IxZ;!*gj1hLmjGa2n zF{G*c?OFT=CbZrc)v>ikjCw$8rpi~%<`N*P4Hg9grgi%u!4-0RrZX}LnoA(bZMWD{ zPye)GLahn(Wxo<4^x>?5cg}?&d4f$H+6!FeC5Ztdv$JY15+Yc@im`9-K9&1_@gE$H zgYRGj!H)XMmf;R(Z9rO8)*AWx2QZ7UZqPSXE@Ay60_AHJpi_b7=|J()!zVl;Ilz!Y zZ)eVWCT3-9H;?e?oR_5hTBzRO9l=ZaWK^3f#m~=@#jr?`Yh}tZ~I1h4n z{PAZIMui=jm)TXIB2l$oc>xxJ!C%Vv4TVkM%T&Y|%Oq@sa9*4J`feOd9=TKNRdw`U zYGL1g%s+iE%vlVk(X7>MD)Hww?9Tqy_RsM-_iTVEmTUq2e#I`c{D%W8<4h0=G7Qt{Zg* zfP@|~)IF9XV99I#g*p!SYJ7Wtp@)PPQ9}IzC_JcYuaIubqBIQkC#~iJ7L zFI>XS0<97pKY}6f0a~J7(AXco&EAjn5q`t~c}&nS%@Ypw4}7n)rwn^)%*iBlTuOPr zeHCF^{T^K?5S_1fa4tpTT#8!E7Tt{EJ%@71G3Fbv%2PSNJcx%b&x`u34E^we6IbV+~*RKI|q`cKxse3)fN>2S-r45SMq;V)cERwMdqx zEsJ_RD}~?e6bmKGqr?l+xNDDY|C1ZaT1sO^w-xfLynYA3mStMD`d-#|ChF7z!SeGR z*DN4FyxMW&vJTexoFN%GePzY&ZhSTkdRAz;Knav4KceVyJ0&NcX(wj{jf%G&e74yBv1t;x$yAwZw!>kL z^)SDeXJn%AQaJCX>GoE|_3GNjSTS(aeSIqPtSt^ciUsTj9G5cp$F13YFO~A+ej`KF zSSBl~Ue?I8t6a+RDAOm=qb=yxl>hVND+>!l?!ZKN?EBgymo1I&mfJVuMWoo+x~^yu z*lUQdVdrh@7NOYq_-5mx_*?u?2_*rY#~0-BT{^ZFuHqNlNI)m_WFSZ+e%Rf3)#$7# zbM^g0##QnsZ8u@-<}O?&U1m~Cgoht1|ASB$Paz8Z7^-^7_$h@LDH-qrRMBS*Lm;fg zskcp4MraqlPL+NJMVR_D_JVRRPFm3&ost~x__E<2!~+=wgb7$!FClWH$3E$sr7%(W z$`y+p3ESI%-r0hdT<4QnaKsWuT))tQ!2?n~=ti;?l!a&?RBKcOxW8YT`(M(jG|nq%CnCkzxYs zhmq*8)D@|be5YKZyH0KbyVzz2Zsig zEN2JJErQeV`?crW-5EzF& z9Jan%cHW#U+|l8??B(v27e7!@WQ{h4)iuJ#ShDGguu@-T2yio@UcP^_@czk<_c=ei z&rNrq8+@O7^geUUB#^8%irpEdLW(a#B}hWZtxID#MZhnEOL#$-mQ2i)c1X+l)pO?0 zu|JTdarC}9ERv7kG>h%TJg=T^Txe=Fp7t5DWIP(Twj|scgU$A*U@#DhdTVP}KSDaO zBi6mKYHr5e4Kzdxv!~;?#d>#>@Nf4$8Z%$T+ZqA(2M)v`P0}-!MKkc&o#wh$hq7EQan#2eKaZZ3Hw#hS_+@9vttH3` z=LnMB@mLh_hKS;_jtM=2RGE5
Uh``2@py^mG~12l49C3WbIE@%j0c4E1_dR#OC7 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 literal 0 HcmV?d00001 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-0.exr.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-0.exr.meta new file mode 100644 index 00000000..323b2483 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-0.exr.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: e44b2fada33483841b7922673545fe73 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr new file mode 100644 index 0000000000000000000000000000000000000000..26ace0ee9a318c0482d4e2f025eda29d6a7fe403 GIT binary patch literal 179115 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%0D2>UnI(3 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 + /// Cached Animation parameter hash, for quicker access. + /// + static readonly int _isOpenHash = Animator.StringToHash("IsOpen"); + + /// + /// Set this component reference in the inspector to be able to read and write loading states. + /// + [SerializeField] + LoadingBehavior _loadingBehavior; + + /// + /// The is used to notify when the target scenes have completed loading and to trigger the start and end of the Scene Transition. + /// + LoadingProgress _loadingProgress; + // We'll use the animator to play animations. + Animator _animator; + + /// + /// The Awake method is invoked right after a scene has completed loading, but still didn't activate. + /// Here we can get the references we need and trigger the "in" animation. + /// + void Awake() + { + _animator = GetComponent(); + + // Get the LoadingProgress from the LoadingBehavior + _loadingProgress = _loadingBehavior.Progress; + + // Subscribe to the LoadingCompleted event, that is broadcast when the target scenes are completely loaded + _loadingProgress.LoadingCompleted += PlayOutAnimation; + + // Start playing the "in" animation, to show a feedback that we're entering a loading state + PlayInAnimation(); + } + + /// + /// Call this method when you have finished your animation to effectively start the Scene Transition. + /// + public void InTransitionTrigger() + { + // Allow the Scene Manager to start the Scene Transition + _loadingProgress.StartTransition(); + } + + /// + /// Call this method when you have finished your animation to effectively end the Scene Transition. + /// + public void OutTransitionTrigger() + { + // Allow the Scene Manager to finish the Scene Transition + _loadingProgress.EndTransition(); + } + + /// + /// Plays the "in" transition animation for the loading screen. + /// + void PlayInAnimation() + { + _animator.SetBool(_isOpenHash, false); + } + + /// + /// Plays the "out" transition animation for the loading screen. + /// + void PlayOutAnimation() + { + _animator.SetBool(_isOpenHash, true); + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs.meta new file mode 100644 index 00000000..23241446 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 86412405a5b304e44bcea539864a36ab \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs new file mode 100644 index 00000000..e1a68c25 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs @@ -0,0 +1,38 @@ +using MyGameDevTools.SceneLoading; +using UnityEngine; +using UnityEngine.UI; + +[RequireComponent(typeof(Image))] +public class LoadingFeedbackImageFill : MonoBehaviour +{ + /// + /// Set this component reference in the inspector to be able to read the loading progress. + /// + [SerializeField] + LoadingBehavior _loadingBehavior; + + // We'll use the Image component to display the loading feedback as the fill amount. + Image _image; + + /// + /// Initialize the feedback state. + /// + void Awake() + { + _image = GetComponent(); + _image.fillAmount = 0; + } + + /// + /// Subscribe to the event to receive the loading progress of the target scenes. + /// + void Start() + { + _loadingBehavior.Progress.Progressed += UpdateSlider; + } + + /// + /// Updates the to display the loading progress feedback. + /// + void UpdateSlider(float progress) => _image.fillAmount = progress; +} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs.meta new file mode 100644 index 00000000..583fc7d1 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/LoadingFeedbackImageFill.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ea86e1e214840ef498f79747dcb26163 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef new file mode 100644 index 00000000..3888e966 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Sample.LoadingScene", + "rootNamespace": "", + "references": [ + "GUID:eee6d035ccac42b4e845b99014468585" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef.meta new file mode 100644 index 00000000..5d38ba36 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/Sample.LoadingScene.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 82fcb9e0d6410444c88a9f17063b829d +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs new file mode 100644 index 00000000..efb6ce7c --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs @@ -0,0 +1,29 @@ +using MyGameDevTools.SceneLoading; +using UnityEngine; + +public class SceneTransitionTrigger : MonoBehaviour +{ + /// + /// Target Scene name. + /// Editable via the Unity Inspector. + /// Make sure to provide a scene that has been added to the Build Settings. + /// + [SerializeField] + string _targetScene; + + /// + /// Triggers a Scene Transition to a scene with name provided by '' with a loading scene with name ''. + /// + public void TransitionWithLoading(string loadingScene) + { + AdvancedSceneManager.TransitionAsync(_targetScene, loadingScene); + } + + /// + /// Triggers a Scene Transition to a scene with name provided by '' without a loading scene. + /// + public void Transition() + { + AdvancedSceneManager.TransitionAsync(_targetScene); + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs.meta new file mode 100644 index 00000000..c8922b4c --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2e674cd85e71d854e945438963214e21 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites.meta new file mode 100644 index 00000000..c36db63c --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b73aa7ea07e12a4ab95f2968f988ec9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..7c6d80ae781bf351933ae81120e56c1af5bceae4 GIT binary patch literal 41519 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 CS_p*z literal 0 HcmV?d00001 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png.meta new file mode 100644 index 00000000..3f296b3e --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/circle.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 0e631649835abae4fad9a729f45bcb81 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png new file mode 100644 index 0000000000000000000000000000000000000000..4da3867e0bbeb8388212a2225757ee4cadf4e0a7 GIT binary patch literal 27381 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 Sman4lzy5uK0}l4mE&Lxk;J5?; literal 0 HcmV?d00001 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png.meta new file mode 100644 index 00000000..9451ff21 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_left.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 79a6fde258d0ee447a881166e6ecadea +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 0 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png new file mode 100644 index 0000000000000000000000000000000000000000..0a696f1669cfcd05bb3477ef62e335c768e27828 GIT binary patch literal 27512 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%0D`AXw8$=v%mAwgMUaHWg;*tE~QTC<5;NOm& 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 MFVHWukK*_L2U{iC+yDRo literal 0 HcmV?d00001 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png.meta new file mode 100644 index 00000000..da6c5bef --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Sprites/triangle_right.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 893a1f4488cb89d4c84df8bece4201be +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 0 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/package.json b/Packages/com.mygamedevtools.scene-loader/package.json index c63cff07..c1eba704 100644 --- a/Packages/com.mygamedevtools.scene-loader/package.json +++ b/Packages/com.mygamedevtools.scene-loader/package.json @@ -14,5 +14,12 @@ "documentationUrl": "https://github.com/mygamedevtools/scene-loader", "licensesUrl": "https://github.com/mygamedevtools/scene-loader?tab=MIT-1-ov-file", "changelogUrl": "https://github.com/mygamedevtools/scene-loader/blob/main/CHANGELOG.md", - "hideInEditor": false + "hideInEditor": false, + "samples": [ + { + "displayName": "Loading Scene Examples", + "description": "Experiment with different loading scenes for Scene Transitions. Use the sample scenes as a starting point to build your own loading scenes.", + "path": "Samples~/LoadingSceneExamples" + } + ] } \ No newline at end of file From c76ad3e08cb82495cf4c630cc75f1b5eea16b2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 13:54:33 -0300 Subject: [PATCH 33/53] fix: add material conversion to render pipelines --- .../{ScriptTemplates.meta => Rendering.meta} | 2 +- Assets/Rendering/DefaultVolumeProfile.asset | 795 +++++++++++++++ .../DefaultVolumeProfile.asset.meta} | 5 +- .../HDRPDefaultResources.meta} | 5 +- .../DefaultLookDevProfile.asset | 259 +++++ .../DefaultLookDevProfile.asset.meta | 8 + .../DefaultSettingsVolumeProfile.asset | 918 ++++++++++++++++++ .../DefaultSettingsVolumeProfile.asset.meta | 8 + .../HDRenderPipelineAsset.asset | 546 +++++++++++ .../HDRenderPipelineAsset.asset.meta | 8 + .../HDRenderPipelineGlobalSettings.asset | 824 ++++++++++++++++ .../HDRenderPipelineGlobalSettings.asset.meta | 8 + .../URPDefaultResources.meta} | 5 +- .../Universal Render Pipeline Asset.asset | 136 +++ ...Universal Render Pipeline Asset.asset.meta | 8 + ...ersal Render Pipeline Asset_Renderer.asset | 53 + ... Render Pipeline Asset_Renderer.asset.meta | 8 + ...niversalRenderPipelineGlobalSettings.asset | 257 +++++ ...salRenderPipelineGlobalSettings.asset.meta | 8 + ...__Mono Behaviour-NewBehaviourScript.cs.txt | 6 - ...riptable Object-NewScriptableObject.cs.txt | 6 - ...Scripts__Entities__System-NewSystem.cs.txt | 6 - ...s__Entities__Component-NewComponent.cs.txt | 6 - ...tities__Component-NewComponent.cs.txt.meta | 7 - ...s__Entities__Authoring-NewAuthoring.cs.txt | 13 - ...tities__Authoring-NewAuthoring.cs.txt.meta | 7 - ...es__Managed System-NewManagedSystem.cs.txt | 9 - ...anaged System-NewManagedSystem.cs.txt.meta | 7 - ...naged Component-NewManagedComponent.cs.txt | 6 - ... Component-NewManagedComponent.cs.txt.meta | 7 - .../78-My Scripts__C# Class-NewClass.cs.txt | 6 - ...-My Scripts__C# Class-NewClass.cs.txt.meta | 7 - .../79-My Scripts__C# Struct-NewStruct.cs.txt | 6 - ...y Scripts__C# Struct-NewStruct.cs.txt.meta | 7 - .../80-My Scripts__C# Enum-NewEnum.cs.txt | 4 - ...80-My Scripts__C# Enum-NewEnum.cs.txt.meta | 7 - ... Scripts__C# Interface-NewInterface.cs.txt | 6 - ...pts__C# Interface-NewInterface.cs.txt.meta | 7 - .../Editor/MaterialPipelineConverter.cs | 116 +++ .../Editor/MaterialPipelineConverter.cs.meta | 2 + .../Editor/Sample.LoadingScene.Editor.asmdef | 37 +- .../Editor/SceneBuildSettingsEditor.cs | 3 +- Packages/manifest.json | 3 + Packages/packages-lock.json | 136 +++ ProjectSettings/GraphicsSettings.asset | 22 +- ProjectSettings/HDRPProjectSettings.asset | 28 + ProjectSettings/InputManager.asset | 193 ++++ ProjectSettings/ProjectSettings.asset | 2 +- ProjectSettings/QualitySettings.asset | 233 +---- ProjectSettings/ShaderGraphSettings.asset | 18 + ProjectSettings/URPProjectSettings.asset | 15 + ProjectSettings/VFXManager.asset | 15 +- 52 files changed, 4465 insertions(+), 349 deletions(-) rename Assets/{ScriptTemplates.meta => Rendering.meta} (77%) create mode 100644 Assets/Rendering/DefaultVolumeProfile.asset rename Assets/{ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt.meta => Rendering/DefaultVolumeProfile.asset.meta} (52%) rename Assets/{ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt.meta => Rendering/HDRPDefaultResources.meta} (57%) create mode 100644 Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset create mode 100644 Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset.meta create mode 100644 Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset create mode 100644 Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset.meta create mode 100644 Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset create mode 100644 Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset.meta create mode 100644 Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset create mode 100644 Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset.meta rename Assets/{ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt.meta => Rendering/URPDefaultResources.meta} (57%) create mode 100644 Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset create mode 100644 Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset.meta create mode 100644 Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset create mode 100644 Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset.meta create mode 100644 Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset create mode 100644 Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset.meta delete mode 100644 Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt delete mode 100644 Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt delete mode 100644 Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt delete mode 100644 Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt delete mode 100644 Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt delete mode 100644 Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt delete mode 100644 Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt delete mode 100644 Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt delete mode 100644 Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt delete mode 100644 Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt delete mode 100644 Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt.meta delete mode 100644 Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt delete mode 100644 Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt.meta create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs create mode 100644 Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs.meta create mode 100644 ProjectSettings/HDRPProjectSettings.asset create mode 100644 ProjectSettings/ShaderGraphSettings.asset create mode 100644 ProjectSettings/URPProjectSettings.asset diff --git a/Assets/ScriptTemplates.meta b/Assets/Rendering.meta similarity index 77% rename from Assets/ScriptTemplates.meta rename to Assets/Rendering.meta index 827bdc12..74d6bdb2 100644 --- a/Assets/ScriptTemplates.meta +++ b/Assets/Rendering.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: cf4f05422679365499a3e8ef6ae42042 +guid: 1acbd88bd08fad84f821c442035f9cb4 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Rendering/DefaultVolumeProfile.asset b/Assets/Rendering/DefaultVolumeProfile.asset new file mode 100644 index 00000000..77077da5 --- /dev/null +++ b/Assets/Rendering/DefaultVolumeProfile.asset @@ -0,0 +1,795 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-8370080110211795471 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + skipIterations: + m_OverrideState: 1 + m_Value: 1 + threshold: + m_OverrideState: 1 + m_Value: 0.9 + intensity: + m_OverrideState: 1 + m_Value: 0 + scatter: + m_OverrideState: 1 + m_Value: 0.7 + clamp: + m_OverrideState: 1 + m_Value: 65472 + tint: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + highQualityFiltering: + m_OverrideState: 1 + m_Value: 0 + downscale: + m_OverrideState: 1 + m_Value: 0 + maxIterations: + m_OverrideState: 1 + m_Value: 6 + dirtTexture: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + dirtIntensity: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-8346100507460703878 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 221518ef91623a7438a71fef23660601, type: 3} + m_Name: WhiteBalance + m_EditorClassIdentifier: + active: 1 + temperature: + m_OverrideState: 1 + m_Value: 0 + tint: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-5574348742128233764 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 66f335fb1ffd8684294ad653bf1c7564, type: 3} + m_Name: ColorAdjustments + m_EditorClassIdentifier: + active: 1 + postExposure: + m_OverrideState: 1 + m_Value: 0 + contrast: + m_OverrideState: 1 + m_Value: 0 + colorFilter: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + hueShift: + m_OverrideState: 1 + m_Value: 0 + saturation: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-5345359279556101022 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fb60a22f311433c4c962b888d1393f88, type: 3} + m_Name: PaniniProjection + m_EditorClassIdentifier: + active: 1 + distance: + m_OverrideState: 1 + m_Value: 0 + cropToFit: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &-3894561815744533259 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 06437c1ff663d574d9447842ba0a72e4, type: 3} + m_Name: ScreenSpaceLensFlare + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + tintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + bloomMip: + m_OverrideState: 1 + m_Value: 1 + firstFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + secondaryFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + warpedFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + warpedFlareScale: + m_OverrideState: 1 + m_Value: {x: 1, y: 1} + samples: + m_OverrideState: 1 + m_Value: 1 + sampleDimmer: + m_OverrideState: 1 + m_Value: 0.5 + vignetteEffect: + m_OverrideState: 1 + m_Value: 1 + startingPosition: + m_OverrideState: 1 + m_Value: 1.25 + scale: + m_OverrideState: 1 + m_Value: 1.5 + streaksIntensity: + m_OverrideState: 1 + m_Value: 0 + streaksLength: + m_OverrideState: 1 + m_Value: 0.5 + streaksOrientation: + m_OverrideState: 1 + m_Value: 0 + streaksThreshold: + m_OverrideState: 1 + m_Value: 0.25 + resolution: + m_OverrideState: 1 + m_Value: 4 + chromaticAbberationIntensity: + m_OverrideState: 1 + m_Value: 0.5 +--- !u!114 &-3681988503604989566 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 899c54efeace73346a0a16faa3afe726, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + color: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} + center: + m_OverrideState: 1 + m_Value: {x: 0.5, y: 0.5} + intensity: + m_OverrideState: 1 + m_Value: 0 + smoothness: + m_OverrideState: 1 + m_Value: 0.2 + rounded: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-942384438019783254 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e021b4c809a781e468c2988c016ebbea, type: 3} + m_Name: ColorLookup + m_EditorClassIdentifier: + active: 1 + texture: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + contribution: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-833292944778066288 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 70afe9e12c7a7ed47911bb608a23a8ff, type: 3} + m_Name: SplitToning + m_EditorClassIdentifier: + active: 1 + shadows: + m_OverrideState: 1 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + highlights: + m_OverrideState: 1 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + balance: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-712942181991938360 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 558a8e2b6826cf840aae193990ba9f2e, type: 3} + m_Name: ShadowsMidtonesHighlights + m_EditorClassIdentifier: + active: 1 + shadows: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + midtones: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + highlights: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + shadowsStart: + m_OverrideState: 1 + m_Value: 0 + shadowsEnd: + m_OverrideState: 1 + m_Value: 0.3 + highlightsStart: + m_OverrideState: 1 + m_Value: 0.55 + highlightsEnd: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &-527798231832664840 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 29fa0085f50d5e54f8144f766051a691, type: 3} + m_Name: FilmGrain + m_EditorClassIdentifier: + active: 1 + type: + m_OverrideState: 1 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0 + response: + m_OverrideState: 1 + m_Value: 0.8 + texture: + m_OverrideState: 1 + m_Value: {fileID: 0} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DefaultVolumeProfile + m_EditorClassIdentifier: + components: + - {fileID: 7033987986701943802} + - {fileID: 8644333173934411570} + - {fileID: -3681988503604989566} + - {fileID: -527798231832664840} + - {fileID: 8846041007000823114} + - {fileID: 5713285358670820303} + - {fileID: 5474851606841886039} + - {fileID: 519842901086012108} + - {fileID: -3894561815744533259} + - {fileID: -8346100507460703878} + - {fileID: -8370080110211795471} + - {fileID: 8769794060634833573} + - {fileID: -5574348742128233764} + - {fileID: 2343884554779143547} + - {fileID: -833292944778066288} + - {fileID: -942384438019783254} + - {fileID: -5345359279556101022} + - {fileID: -712942181991938360} + - {fileID: 7074675694432682807} +--- !u!114 &519842901086012108 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c01700fd266d6914ababb731e09af2eb, type: 3} + m_Name: DepthOfField + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + gaussianStart: + m_OverrideState: 1 + m_Value: 10 + gaussianEnd: + m_OverrideState: 1 + m_Value: 30 + gaussianMaxRadius: + m_OverrideState: 1 + m_Value: 1 + highQualitySampling: + m_OverrideState: 1 + m_Value: 0 + focusDistance: + m_OverrideState: 1 + m_Value: 10 + aperture: + m_OverrideState: 1 + m_Value: 5.6 + focalLength: + m_OverrideState: 1 + m_Value: 50 + bladeCount: + m_OverrideState: 1 + m_Value: 5 + bladeCurvature: + m_OverrideState: 1 + m_Value: 1 + bladeRotation: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &2343884554779143547 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + neutralHDRRangeReductionMode: + m_OverrideState: 1 + m_Value: 2 + acesPreset: + m_OverrideState: 1 + m_Value: 3 + hueShiftAmount: + m_OverrideState: 1 + m_Value: 0 + detectPaperWhite: + m_OverrideState: 1 + m_Value: 0 + paperWhite: + m_OverrideState: 1 + m_Value: 300 + detectBrightnessLimits: + m_OverrideState: 1 + m_Value: 1 + minNits: + m_OverrideState: 1 + m_Value: 0.005 + maxNits: + m_OverrideState: 1 + m_Value: 1000 +--- !u!114 &5474851606841886039 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 81180773991d8724ab7f2d216912b564, type: 3} + m_Name: ChromaticAberration + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &5713285358670820303 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ccf1aba9553839d41ae37dd52e9ebcce, type: 3} + m_Name: MotionBlur + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + quality: + m_OverrideState: 1 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0 + clamp: + m_OverrideState: 1 + m_Value: 0.05 +--- !u!114 &7033987986701943802 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cdfbdbb87d3286943a057f7791b43141, type: 3} + m_Name: ChannelMixer + m_EditorClassIdentifier: + active: 1 + redOutRedIn: + m_OverrideState: 1 + m_Value: 100 + redOutGreenIn: + m_OverrideState: 1 + m_Value: 0 + redOutBlueIn: + m_OverrideState: 1 + m_Value: 0 + greenOutRedIn: + m_OverrideState: 1 + m_Value: 0 + greenOutGreenIn: + m_OverrideState: 1 + m_Value: 100 + greenOutBlueIn: + m_OverrideState: 1 + m_Value: 0 + blueOutRedIn: + m_OverrideState: 1 + m_Value: 0 + blueOutGreenIn: + m_OverrideState: 1 + m_Value: 0 + blueOutBlueIn: + m_OverrideState: 1 + m_Value: 100 +--- !u!114 &7074675694432682807 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6bd486065ce11414fa40e631affc4900, type: 3} + m_Name: ProbeVolumesOptions + m_EditorClassIdentifier: + active: 1 + normalBias: + m_OverrideState: 1 + m_Value: 0.05 + viewBias: + m_OverrideState: 1 + m_Value: 0.1 + scaleBiasWithMinProbeDistance: + m_OverrideState: 1 + m_Value: 0 + samplingNoise: + m_OverrideState: 1 + m_Value: 0.1 + animateSamplingNoise: + m_OverrideState: 1 + m_Value: 1 + leakReductionMode: + m_OverrideState: 1 + m_Value: 2 + minValidDotProductValue: + m_OverrideState: 1 + m_Value: 0.1 + occlusionOnlyReflectionNormalization: + m_OverrideState: 1 + m_Value: 1 + intensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + skyOcclusionIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + worldOffset: + m_OverrideState: 1 + m_Value: {x: 0, y: 0, z: 0} +--- !u!114 &8644333173934411570 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3eb4b772797da9440885e8bd939e9560, type: 3} + m_Name: ColorCurves + m_EditorClassIdentifier: + active: 1 + master: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + red: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + green: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + blue: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + hueVsHue: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + hueVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + satVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + lumVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &8769794060634833573 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c5e1dc532bcb41949b58bc4f2abfbb7e, type: 3} + m_Name: LensDistortion + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + xMultiplier: + m_OverrideState: 1 + m_Value: 1 + yMultiplier: + m_OverrideState: 1 + m_Value: 1 + center: + m_OverrideState: 1 + m_Value: {x: 0.5, y: 0.5} + scale: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &8846041007000823114 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5485954d14dfb9a4c8ead8edb0ded5b1, type: 3} + m_Name: LiftGammaGain + m_EditorClassIdentifier: + active: 1 + lift: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + gamma: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + gain: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} diff --git a/Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt.meta b/Assets/Rendering/DefaultVolumeProfile.asset.meta similarity index 52% rename from Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt.meta rename to Assets/Rendering/DefaultVolumeProfile.asset.meta index 10d788fc..dcdce9d4 100644 --- a/Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt.meta +++ b/Assets/Rendering/DefaultVolumeProfile.asset.meta @@ -1,7 +1,8 @@ fileFormatVersion: 2 -guid: 31054eadc4870474988606b245b7463e -TextScriptImporter: +guid: 7641b16591813c8478df3d5724c50315 +NativeFormatImporter: externalObjects: {} + mainObjectFileID: 11400000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt.meta b/Assets/Rendering/HDRPDefaultResources.meta similarity index 57% rename from Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt.meta rename to Assets/Rendering/HDRPDefaultResources.meta index b98ddf49..2393a755 100644 --- a/Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt.meta +++ b/Assets/Rendering/HDRPDefaultResources.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 -guid: 29f71f35823cc314392a406933983d0e -TextScriptImporter: +guid: f68504a66c4b5c44898c2236d35c467d +folderAsset: yes +DefaultImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset b/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset new file mode 100644 index 00000000..0dd9b433 --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset @@ -0,0 +1,259 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DefaultLookDevProfile + m_EditorClassIdentifier: + components: + - {fileID: 8761387877531654226} + - {fileID: 1902828633788537306} + - {fileID: 1880163708194025631} + - {fileID: 2340290907100754200} +--- !u!114 &1880163708194025631 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9008a067f4d626c4d8bc4bc48f04bb89, type: 3} + m_Name: AmbientOcclusion + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 0 + m_Value: 1 + rayTracing: + m_OverrideState: 0 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0.5 + directLightingStrength: + m_OverrideState: 0 + m_Value: 0 + radius: + m_OverrideState: 1 + m_Value: 1 + spatialBilateralAggressiveness: + m_OverrideState: 0 + m_Value: 0.15 + temporalAccumulation: + m_OverrideState: 0 + m_Value: 1 + ghostingReduction: + m_OverrideState: 0 + m_Value: 0.5 + blurSharpness: + m_OverrideState: 0 + m_Value: 0.1 + layerMask: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Bits: 4294967295 + specularOcclusion: + m_OverrideState: 0 + m_Value: 0.5 + occluderMotionRejection: + m_OverrideState: 0 + m_Value: 1 + receiverMotionRejection: + m_OverrideState: 0 + m_Value: 1 + m_StepCount: + m_OverrideState: 0 + m_Value: 6 + m_FullResolution: + m_OverrideState: 0 + m_Value: 0 + m_MaximumRadiusInPixels: + m_OverrideState: 0 + m_Value: 40 + m_BilateralUpsample: + m_OverrideState: 0 + m_Value: 1 + m_DirectionCount: + m_OverrideState: 0 + m_Value: 2 + m_RayLength: + m_OverrideState: 0 + m_Value: 3 + m_SampleCount: + m_OverrideState: 0 + m_Value: 2 + m_Denoise: + m_OverrideState: 0 + m_Value: 1 + m_DenoiserRadius: + m_OverrideState: 0 + m_Value: 0.5 +--- !u!114 &1902828633788537306 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ddcec8a8eb2d684d833ac8f5d26aebd, type: 3} + m_Name: HDShadowSettings + m_EditorClassIdentifier: + active: 1 + maxShadowDistance: + m_OverrideState: 1 + m_Value: 25 + directionalTransmissionMultiplier: + m_OverrideState: 0 + m_Value: 1 + cascadeShadowSplitCount: + m_OverrideState: 1 + m_Value: 2 + cascadeShadowSplit0: + m_OverrideState: 0 + m_Value: 0.05 + cascadeShadowSplit1: + m_OverrideState: 0 + m_Value: 0.15 + cascadeShadowSplit2: + m_OverrideState: 0 + m_Value: 0.3 + cascadeShadowBorder0: + m_OverrideState: 0 + m_Value: 0 + cascadeShadowBorder1: + m_OverrideState: 0 + m_Value: 0 + cascadeShadowBorder2: + m_OverrideState: 0 + m_Value: 0 + cascadeShadowBorder3: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &2340290907100754200 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24f077503be6ae942a1e1245dbd53ea9, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 0 + m_Value: 3 + threshold: + m_OverrideState: 0 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0.1 + scatter: + m_OverrideState: 0 + m_Value: 0.7 + tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + dirtTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + dirtIntensity: + m_OverrideState: 0 + m_Value: 0 + anamorphic: + m_OverrideState: 0 + m_Value: 1 + m_Resolution: + m_OverrideState: 0 + m_Value: 2 + m_HighQualityPrefiltering: + m_OverrideState: 0 + m_Value: 0 + m_HighQualityFiltering: + m_OverrideState: 0 + m_Value: 1 +--- !u!114 &8761387877531654226 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f086a068d4c5889438831b3ae9afc11c, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 1 + useFullACES: + m_OverrideState: 0 + m_Value: 0 + toeStrength: + m_OverrideState: 0 + m_Value: 0 + toeLength: + m_OverrideState: 0 + m_Value: 0.5 + shoulderStrength: + m_OverrideState: 0 + m_Value: 0 + shoulderLength: + m_OverrideState: 0 + m_Value: 0.5 + shoulderAngle: + m_OverrideState: 0 + m_Value: 0 + gamma: + m_OverrideState: 0 + m_Value: 1 + lutTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + lutContribution: + m_OverrideState: 0 + m_Value: 1 + neutralHDRRangeReductionMode: + m_OverrideState: 0 + m_Value: 2 + acesPreset: + m_OverrideState: 0 + m_Value: 3 + fallbackMode: + m_OverrideState: 0 + m_Value: 1 + hueShiftAmount: + m_OverrideState: 0 + m_Value: 0 + detectPaperWhite: + m_OverrideState: 0 + m_Value: 0 + paperWhite: + m_OverrideState: 0 + m_Value: 300 + detectBrightnessLimits: + m_OverrideState: 0 + m_Value: 1 + minNits: + m_OverrideState: 0 + m_Value: 0.005 + maxNits: + m_OverrideState: 0 + m_Value: 1000 diff --git a/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset.meta b/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset.meta new file mode 100644 index 00000000..f62e11e2 --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/DefaultLookDevProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3837bee00f735443a9ca15a1f874148 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset b/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset new file mode 100644 index 00000000..f8c0519e --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset @@ -0,0 +1,918 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-8770122170507510650 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a76fd08475e21554b8f284f723dd7cf8, type: 3} + m_Name: WaterRendering + m_EditorClassIdentifier: + active: 1 + enable: + m_OverrideState: 1 + m_Value: 1 + triangleSize: + m_OverrideState: 0 + m_Value: 30 + ambientProbeDimmer: + m_OverrideState: 0 + m_Value: 1 +--- !u!114 &-7089757308646879465 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bcf384b154398e341b6b29969c078198, type: 3} + m_Name: MotionBlur + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 1 + m_Value: 1 + intensity: + m_OverrideState: 1 + m_Value: 0.5 + maximumVelocity: + m_OverrideState: 0 + m_Value: 200 + minimumVelocity: + m_OverrideState: 0 + m_Value: 2 + cameraMotionBlur: + m_OverrideState: 0 + m_Value: 1 + specialCameraClampMode: + m_OverrideState: 0 + m_Value: 0 + cameraVelocityClamp: + m_OverrideState: 0 + m_Value: 0.05 + cameraTranslationVelocityClamp: + m_OverrideState: 0 + m_Value: 0.05 + cameraRotationVelocityClamp: + m_OverrideState: 0 + m_Value: 0.03 + depthComparisonExtent: + m_OverrideState: 0 + m_Value: 1 + m_SampleCount: + m_OverrideState: 1 + m_Value: 8 +--- !u!114 &-6026464391438864705 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a7ff42a8c5be6646ad3975f3a54c1eb, type: 3} + m_Name: DiffusionProfileList + m_EditorClassIdentifier: + active: 1 + diffusionProfiles: + m_OverrideState: 1 + m_Value: + - {fileID: 11400000, guid: 404820c4cf36ad944862fa59c56064f0, type: 2} + - {fileID: 11400000, guid: 2384dbf2c1c420f45a792fbc315fbfb1, type: 2} +--- !u!114 &-1016694868962581565 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 56b145d2b9ee1ac4f846968484e7485a, type: 3} + m_Name: ContactShadows + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 0 + m_Value: 1 + enable: + m_OverrideState: 1 + m_Value: 1 + length: + m_OverrideState: 0 + m_Value: 0.15 + opacity: + m_OverrideState: 0 + m_Value: 1 + distanceScaleFactor: + m_OverrideState: 0 + m_Value: 0.5 + maxDistance: + m_OverrideState: 0 + m_Value: 50 + minDistance: + m_OverrideState: 0 + m_Value: 0 + fadeDistance: + m_OverrideState: 0 + m_Value: 5 + fadeInDistance: + m_OverrideState: 0 + m_Value: 0 + rayBias: + m_OverrideState: 0 + m_Value: 0.2 + thicknessScale: + m_OverrideState: 0 + m_Value: 0.15 + m_SampleCount: + m_OverrideState: 0 + m_Value: 10 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DefaultSettingsVolumeProfile + m_EditorClassIdentifier: + components: + - {fileID: 7686318427622180703} + - {fileID: -1016694868962581565} + - {fileID: 7502528774814404555} + - {fileID: 7542669330009093999} + - {fileID: 1501199423866068322} + - {fileID: 5315503232242033309} + - {fileID: 1932259527246508038} + - {fileID: 448115243408767295} + - {fileID: -7089757308646879465} + - {fileID: -8770122170507510650} + - {fileID: 4981354747274665315} + - {fileID: 5305602202033311358} + - {fileID: 2138017992340590289} +--- !u!114 &448115243408767295 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59b6606ef2548734bb6d11b9d160bc7e, type: 3} + m_Name: HDRISky + m_EditorClassIdentifier: + active: 1 + rotation: + m_OverrideState: 0 + m_Value: 0 + skyIntensityMode: + m_OverrideState: 0 + m_Value: 0 + exposure: + m_OverrideState: 1 + m_Value: 11 + multiplier: + m_OverrideState: 0 + m_Value: 1 + upperHemisphereLuxValue: + m_OverrideState: 1 + m_Value: 0.4660715 + upperHemisphereLuxColor: + m_OverrideState: 1 + m_Value: {x: 0.18750614, y: 0.29181972, z: 0.5} + desiredLuxValue: + m_OverrideState: 0 + m_Value: 20000 + updateMode: + m_OverrideState: 0 + m_Value: 0 + updatePeriod: + m_OverrideState: 0 + m_Value: 0 + includeSunInBaking: + m_OverrideState: 0 + m_Value: 0 + hdriSky: + m_OverrideState: 1 + m_Value: {fileID: 8900000, guid: 8253d41e6e8b11a4cbe77a4f8f82934d, type: 3} + distortionMode: + m_OverrideState: 0 + m_Value: 0 + flowmap: + m_OverrideState: 0 + m_Value: {fileID: 0} + upperHemisphereOnly: + m_OverrideState: 0 + m_Value: 1 + scrollOrientation: + m_OverrideState: 0 + m_Value: + mode: 1 + customValue: 0 + additiveValue: 0 + multiplyValue: 1 + scrollSpeed: + m_OverrideState: 0 + m_Value: + mode: 1 + customValue: 100 + additiveValue: 0 + multiplyValue: 1 + sunInitialRotation: + m_OverrideState: 0 + m_Value: -Infinity + lockSun: + m_OverrideState: 0 + m_Value: 0 + enableBackplate: + m_OverrideState: 0 + m_Value: 0 + backplateType: + m_OverrideState: 0 + m_Value: 0 + groundLevel: + m_OverrideState: 0 + m_Value: 0 + scale: + m_OverrideState: 0 + m_Value: {x: 32, y: 32} + projectionDistance: + m_OverrideState: 0 + m_Value: 16 + plateRotation: + m_OverrideState: 0 + m_Value: 0 + plateTexRotation: + m_OverrideState: 0 + m_Value: 0 + plateTexOffset: + m_OverrideState: 0 + m_Value: {x: 0, y: 0} + blendAmount: + m_OverrideState: 0 + m_Value: 0 + shadowTint: + m_OverrideState: 0 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + pointLightShadow: + m_OverrideState: 0 + m_Value: 0 + dirLightShadow: + m_OverrideState: 0 + m_Value: 0 + rectLightShadow: + m_OverrideState: 0 + m_Value: 0 + m_SkyVersion: 1 + enableDistortion: + m_OverrideState: 0 + m_Value: 0 + procedural: + m_OverrideState: 0 + m_Value: 1 + scrollDirection: + m_OverrideState: 0 + m_Value: 0 + m_ObsoleteScrollSpeed: + m_OverrideState: 0 + m_Value: 1 +--- !u!114 &1501199423866068322 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 24f077503be6ae942a1e1245dbd53ea9, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 1 + m_Value: 1 + threshold: + m_OverrideState: 0 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0.2 + scatter: + m_OverrideState: 0 + m_Value: 0.7 + tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + dirtTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + dirtIntensity: + m_OverrideState: 0 + m_Value: 0 + anamorphic: + m_OverrideState: 0 + m_Value: 1 + m_Resolution: + m_OverrideState: 1 + m_Value: 2 + m_HighQualityPrefiltering: + m_OverrideState: 1 + m_Value: 0 + m_HighQualityFiltering: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &1932259527246508038 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0d7593b3a9277ac4696b20006c21dde2, type: 3} + m_Name: VisualEnvironment + m_EditorClassIdentifier: + active: 1 + skyType: + m_OverrideState: 1 + m_Value: 1 + cloudType: + m_OverrideState: 0 + m_Value: 0 + skyAmbientMode: + m_OverrideState: 0 + m_Value: 0 + planetRadius: + m_OverrideState: 0 + m_Value: 6378.1 + renderingSpace: + m_OverrideState: 0 + m_Value: 0 + centerMode: + m_OverrideState: 0 + m_Value: 0 + planetCenter: + m_OverrideState: 0 + m_Value: {x: 0, y: -6378.1, z: 0} + windOrientation: + m_OverrideState: 0 + m_Value: 0 + windSpeed: + m_OverrideState: 0 + m_Value: 100 + fogType: + m_OverrideState: 0 + m_Value: 0 + m_Version: 1 +--- !u!114 &2138017992340590289 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a7ff42a8c5be6646ad3975f3a54c1eb, type: 3} + m_Name: DiffusionProfileList + m_EditorClassIdentifier: + active: 1 + diffusionProfiles: + m_OverrideState: 1 + m_Value: + - {fileID: 11400000, guid: 404820c4cf36ad944862fa59c56064f0, type: 2} + - {fileID: 11400000, guid: 2384dbf2c1c420f45a792fbc315fbfb1, type: 2} +--- !u!114 &4981354747274665315 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d877ec3e844f2ca46830012e8e79319b, type: 3} + m_Name: PhysicallyBasedSky + m_EditorClassIdentifier: + active: 1 + rotation: + m_OverrideState: 0 + m_Value: 0 + skyIntensityMode: + m_OverrideState: 0 + m_Value: 0 + exposure: + m_OverrideState: 0 + m_Value: 0 + multiplier: + m_OverrideState: 0 + m_Value: 1 + upperHemisphereLuxValue: + m_OverrideState: 0 + m_Value: 1 + upperHemisphereLuxColor: + m_OverrideState: 0 + m_Value: {x: 0, y: 0, z: 0} + desiredLuxValue: + m_OverrideState: 0 + m_Value: 20000 + updateMode: + m_OverrideState: 0 + m_Value: 0 + updatePeriod: + m_OverrideState: 0 + m_Value: 0 + includeSunInBaking: + m_OverrideState: 0 + m_Value: 0 + type: + m_OverrideState: 0 + m_Value: 1 + atmosphericScattering: + m_OverrideState: 0 + m_Value: 1 + renderingMode: + m_OverrideState: 0 + m_Value: 0 + material: + m_OverrideState: 1 + m_Value: {fileID: -876546973899608171, guid: 02532cbb810fb404db49da84f1efe41e, type: 3} + airDensityR: + m_OverrideState: 0 + m_Value: 0.04534 + airDensityG: + m_OverrideState: 0 + m_Value: 0.10237241 + airDensityB: + m_OverrideState: 0 + m_Value: 0.23264056 + airTint: + m_OverrideState: 0 + m_Value: {r: 0.9, g: 0.9, b: 1, a: 1} + airMaximumAltitude: + m_OverrideState: 0 + m_Value: 55261.973 + aerosolDensity: + m_OverrideState: 0 + m_Value: 0.01192826 + aerosolTint: + m_OverrideState: 0 + m_Value: {r: 0.9, g: 0.9, b: 0.9, a: 1} + aerosolMaximumAltitude: + m_OverrideState: 0 + m_Value: 8289.296 + aerosolAnisotropy: + m_OverrideState: 0 + m_Value: 0.8 + ozoneDensityDimmer: + m_OverrideState: 0 + m_Value: 1 + ozoneMinimumAltitude: + m_OverrideState: 0 + m_Value: 10000 + ozoneLayerWidth: + m_OverrideState: 0 + m_Value: 30000 + groundTint: + m_OverrideState: 0 + m_Value: {r: 0.12156863, g: 0.105882354, b: 0.09411765, a: 1} + groundColorTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + groundEmissionTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + groundEmissionMultiplier: + m_OverrideState: 0 + m_Value: 1 + planetRotation: + m_OverrideState: 0 + m_Value: {x: 0, y: 0, z: 0} + spaceEmissionTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + spaceEmissionMultiplier: + m_OverrideState: 0 + m_Value: 1 + spaceRotation: + m_OverrideState: 0 + m_Value: {x: 0, y: 0, z: 0} + colorSaturation: + m_OverrideState: 0 + m_Value: 1 + alphaSaturation: + m_OverrideState: 0 + m_Value: 1 + alphaMultiplier: + m_OverrideState: 0 + m_Value: 1 + horizonTint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + zenithTint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + horizonZenithShift: + m_OverrideState: 0 + m_Value: 0 + m_SkyVersion: 3 + m_ObsoleteEarthPreset: + m_OverrideState: 0 + m_Value: 1 + planetaryRadius: + m_OverrideState: 0 + m_Value: 6378100 + planetCenterPosition: + m_OverrideState: 0 + m_Value: {x: 0, y: -6378100, z: 0} +--- !u!114 &5305602202033311358 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8c604242b4dd4c8caa4d1944b94189e0, type: 3} + m_Name: HighQualityLineRenderingVolumeComponent + m_EditorClassIdentifier: + active: 1 + enable: + m_OverrideState: 1 + m_Value: 1 + compositionMode: + m_OverrideState: 1 + m_Value: 0 + clusterCount: + m_OverrideState: 1 + m_Value: 24 + sortingQuality: + m_OverrideState: 1 + m_Value: 1 + tileOpacityThreshold: + m_OverrideState: 1 + m_Value: 0.95 + writeDepthAlphaThreshold: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &5315503232242033309 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d08ce26990eb1a4a9177b860541e702, type: 3} + m_Name: Exposure + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 1 + meteringMode: + m_OverrideState: 0 + m_Value: 2 + luminanceSource: + m_OverrideState: 0 + m_Value: 1 + fixedExposure: + m_OverrideState: 0 + m_Value: 0 + compensation: + m_OverrideState: 0 + m_Value: 0 + limitMin: + m_OverrideState: 0 + m_Value: -10 + limitMax: + m_OverrideState: 0 + m_Value: 10 + curveMap: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: -10 + value: -10 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 20 + value: 20 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + limitMinCurveMap: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: -10 + value: -12 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 20 + value: 18 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + limitMaxCurveMap: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: -10 + value: -8 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 20 + value: 22 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + adaptationMode: + m_OverrideState: 0 + m_Value: 1 + adaptationSpeedDarkToLight: + m_OverrideState: 0 + m_Value: 3 + adaptationSpeedLightToDark: + m_OverrideState: 0 + m_Value: 1 + weightTextureMask: + m_OverrideState: 0 + m_Value: {fileID: 0} + histogramPercentages: + m_OverrideState: 0 + m_Value: {x: 40, y: 90} + histogramUseCurveRemapping: + m_OverrideState: 0 + m_Value: 0 + targetMidGray: + m_OverrideState: 0 + m_Value: 0 + centerAroundExposureTarget: + m_OverrideState: 0 + m_Value: 0 + proceduralCenter: + m_OverrideState: 0 + m_Value: {x: 0.5, y: 0.5} + proceduralRadii: + m_OverrideState: 0 + m_Value: {x: 0.3, y: 0.3} + maskMinIntensity: + m_OverrideState: 0 + m_Value: -30 + maskMaxIntensity: + m_OverrideState: 0 + m_Value: 30 + proceduralSoftness: + m_OverrideState: 0 + m_Value: 0.5 +--- !u!114 &7502528774814404555 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9008a067f4d626c4d8bc4bc48f04bb89, type: 3} + m_Name: AmbientOcclusion + m_EditorClassIdentifier: + active: 1 + quality: + m_OverrideState: 0 + m_Value: 1 + rayTracing: + m_OverrideState: 0 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0.5 + directLightingStrength: + m_OverrideState: 0 + m_Value: 0 + radius: + m_OverrideState: 1 + m_Value: 1.5 + spatialBilateralAggressiveness: + m_OverrideState: 0 + m_Value: 0.15 + temporalAccumulation: + m_OverrideState: 0 + m_Value: 1 + ghostingReduction: + m_OverrideState: 0 + m_Value: 0.5 + blurSharpness: + m_OverrideState: 0 + m_Value: 0.1 + layerMask: + m_OverrideState: 0 + m_Value: + serializedVersion: 2 + m_Bits: 4294967295 + specularOcclusion: + m_OverrideState: 0 + m_Value: 0.5 + occluderMotionRejection: + m_OverrideState: 0 + m_Value: 1 + receiverMotionRejection: + m_OverrideState: 0 + m_Value: 1 + m_StepCount: + m_OverrideState: 0 + m_Value: 6 + m_FullResolution: + m_OverrideState: 0 + m_Value: 0 + m_MaximumRadiusInPixels: + m_OverrideState: 0 + m_Value: 40 + m_BilateralUpsample: + m_OverrideState: 0 + m_Value: 1 + m_DirectionCount: + m_OverrideState: 0 + m_Value: 2 + m_RayLength: + m_OverrideState: 0 + m_Value: 3 + m_SampleCount: + m_OverrideState: 0 + m_Value: 2 + m_Denoise: + m_OverrideState: 0 + m_Value: 1 + m_DenoiserRadius: + m_OverrideState: 0 + m_Value: 0.5 +--- !u!114 &7542669330009093999 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f086a068d4c5889438831b3ae9afc11c, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 2 + useFullACES: + m_OverrideState: 0 + m_Value: 0 + toeStrength: + m_OverrideState: 0 + m_Value: 0 + toeLength: + m_OverrideState: 0 + m_Value: 0.5 + shoulderStrength: + m_OverrideState: 0 + m_Value: 0 + shoulderLength: + m_OverrideState: 0 + m_Value: 0.5 + shoulderAngle: + m_OverrideState: 0 + m_Value: 0 + gamma: + m_OverrideState: 0 + m_Value: 1 + lutTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + lutContribution: + m_OverrideState: 0 + m_Value: 1 + neutralHDRRangeReductionMode: + m_OverrideState: 0 + m_Value: 2 + acesPreset: + m_OverrideState: 0 + m_Value: 3 + fallbackMode: + m_OverrideState: 0 + m_Value: 1 + hueShiftAmount: + m_OverrideState: 0 + m_Value: 0 + detectPaperWhite: + m_OverrideState: 0 + m_Value: 0 + paperWhite: + m_OverrideState: 0 + m_Value: 300 + detectBrightnessLimits: + m_OverrideState: 0 + m_Value: 1 + minNits: + m_OverrideState: 0 + m_Value: 0.005 + maxNits: + m_OverrideState: 0 + m_Value: 1000 +--- !u!114 &7686318427622180703 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ddcec8a8eb2d684d833ac8f5d26aebd, type: 3} + m_Name: HDShadowSettings + m_EditorClassIdentifier: + active: 1 + interCascadeBorders: 1 + maxShadowDistance: + m_OverrideState: 1 + m_Value: 150 + directionalTransmissionMultiplier: + m_OverrideState: 0 + m_Value: 1 + cascadeShadowSplitCount: + m_OverrideState: 0 + m_Value: 4 + cascadeShadowSplit0: + m_OverrideState: 0 + m_Value: 0.05 + cascadeShadowSplit1: + m_OverrideState: 0 + m_Value: 0.15 + cascadeShadowSplit2: + m_OverrideState: 0 + m_Value: 0.3 + cascadeShadowBorder0: + m_OverrideState: 1 + m_Value: 0.06905067 + cascadeShadowBorder1: + m_OverrideState: 1 + m_Value: 0.05086228 + cascadeShadowBorder2: + m_OverrideState: 0 + m_Value: 0 + cascadeShadowBorder3: + m_OverrideState: 0 + m_Value: 0 diff --git a/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset.meta b/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset.meta new file mode 100644 index 00000000..0bc1f5ae --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a821dc928355c04091e259c62eaa534 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset new file mode 100644 index 00000000..f6a8cc0e --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset @@ -0,0 +1,546 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cf1dab834d4ec34195b920ea7bbf9ec, type: 3} + m_Name: HDRenderPipelineAsset + m_EditorClassIdentifier: + m_RenderPipelineSettings: + supportShadowMask: 1 + supportSSR: 0 + supportSSRTransparent: 0 + supportSSAO: 1 + supportSSGI: 0 + supportSubsurfaceScattering: 1 + sssSampleBudget: + m_Values: 140000002800000050000000 + m_SchemaId: + m_Id: With3Levels + sssDownsampleSteps: + m_Values: 000000000000000000000000 + m_SchemaId: + m_Id: With3Levels + supportVolumetrics: 1 + supportVolumetricClouds: 0 + supportLightLayers: 0 + renderingLayerMaskBuffer: 0 + supportWater: 0 + waterSimulationResolution: 128 + supportWaterExclusion: 1 + supportWaterDecals: 1 + waterDecalAtlasSize: 1024 + maximumWaterDecalCount: 48 + waterScriptInteractionsMode: 0 + waterFullCPUSimulation: 0 + supportComputeThickness: 0 + computeThicknessResolution: 1 + computeThicknessLayerMask: + serializedVersion: 2 + m_Bits: 0 + supportDistortion: 1 + supportTransparentBackface: 1 + supportTransparentDepthPrepass: 1 + supportTransparentDepthPostpass: 1 + colorBufferFormat: 74 + supportCustomPass: 1 + customBufferFormat: 8 + supportedLitShaderMode: 2 + planarReflectionResolution: + m_Values: 000100000004000000080000 + m_SchemaId: + m_Id: With3Levels + cubeReflectionResolution: + m_Values: 800000000001000000020000 + m_SchemaId: + m_Id: With3Levels + supportDecals: 1 + supportDecalLayers: 0 + supportSurfaceGradient: 1 + decalNormalBufferHP: 0 + supportHighQualityLineRendering: 0 + highQualityLineRenderingMemoryBudget: 128 + msaaSampleCount: 1 + supportMotionVectors: 1 + supportScreenSpaceLensFlare: 1 + supportDataDrivenLensFlare: 1 + supportDitheringCrossFade: 0 + supportRuntimeAOVAPI: 0 + supportTerrainHole: 0 + lightProbeSystem: 1 + oldLightProbeSystem: 0 + probeVolumeMemoryBudget: 1024 + supportProbeVolumeGPUStreaming: 0 + supportProbeVolumeDiskStreaming: 0 + probeVolumeSHBands: 1 + supportProbeVolumeScenarios: 0 + supportProbeVolumeScenarioBlending: 1 + probeVolumeBlendingMemoryBudget: 128 + supportRayTracing: 0 + supportVFXRayTracing: 0 + supportedRayTracingMode: 3 + lightLoopSettings: + cookieAtlasSize: 2048 + cookieFormat: 74 + cookieAtlasLastValidMip: 0 + cookieTexArraySize: 1 + planarReflectionAtlasSize: 0 + reflectionProbeCacheSize: 0 + reflectionCubemapSize: 0 + maxEnvLightsOnScreen: 0 + reflectionCacheCompressed: 0 + reflectionProbeFormat: 74 + reflectionProbeTexCacheSize: 4096 + reflectionProbeTexLastValidCubeMip: 3 + reflectionProbeTexLastValidPlanarMip: 0 + reflectionProbeDecreaseResToFit: 1 + skyReflectionSize: 256 + skyLightingOverrideLayerMask: + serializedVersion: 2 + m_Bits: 0 + supportFabricConvolution: 0 + maxDirectionalLightsOnScreen: 16 + maxPunctualLightsOnScreen: 512 + maxAreaLightsOnScreen: 64 + maxCubeReflectionOnScreen: 32 + maxPlanarReflectionOnScreen: 8 + maxDecalsOnScreen: 512 + maxLightsPerClusterCell: 8 + maxLocalVolumetricFogSize: 0 + maxLocalVolumetricFogOnScreen: 256 + hdShadowInitParams: + maxShadowRequests: 128 + directionalShadowsDepthBits: 32 + punctualShadowFilteringQuality: 1 + directionalShadowFilteringQuality: 1 + areaShadowFilteringQuality: 0 + punctualLightShadowAtlas: + shadowAtlasResolution: 4096 + shadowAtlasDepthBits: 32 + useDynamicViewportRescale: 1 + areaLightShadowAtlas: + shadowAtlasResolution: 4096 + shadowAtlasDepthBits: 32 + useDynamicViewportRescale: 1 + cachedPunctualLightShadowAtlas: 2048 + cachedAreaLightShadowAtlas: 1024 + allowDirectionalMixedCachedShadows: 0 + shadowResolutionDirectional: + m_Values: 00010000000200000004000000080000 + m_SchemaId: + m_Id: With4Levels + shadowResolutionPunctual: + m_Values: 00010000000200000004000000080000 + m_SchemaId: + m_Id: With4Levels + shadowResolutionArea: + m_Values: 00010000000200000004000000080000 + m_SchemaId: + m_Id: With4Levels + maxDirectionalShadowMapResolution: 2048 + maxPunctualShadowMapResolution: 2048 + maxAreaShadowMapResolution: 2048 + supportScreenSpaceShadows: 0 + maxScreenSpaceShadowSlots: 4 + screenSpaceShadowBufferFormat: 48 + decalSettings: + drawDistance: 1000 + atlasWidth: 4096 + atlasHeight: 4096 + transparentTextureResolution: + m_Values: 000100000002000000040000 + m_SchemaId: + m_Id: With3Levels + perChannelMask: 0 + postProcessSettings: + m_LutSize: 32 + lutFormat: 48 + bufferFormat: 74 + dynamicResolutionSettings: + enabled: 0 + useMipBias: 0 + advancedUpscalersByPriority: 02 + DLSSPerfQualitySetting: 0 + DLSSInjectionPoint: 0 + TAAUInjectionPoint: 0 + STPInjectionPoint: 0 + defaultInjectionPoint: 2 + DLSSUseOptimalSettings: 1 + DLSSSharpness: 0.5 + FSR2EnableSharpness: 0 + FSR2Sharpness: 0 + FSR2UseOptimalSettings: 0 + FSR2QualitySetting: 0 + FSR2InjectionPoint: 0 + fsrOverrideSharpness: 0 + fsrSharpness: 0.92 + maxPercentage: 100 + minPercentage: 100 + dynResType: 1 + upsampleFilter: 1 + forceResolution: 0 + forcedPercentage: 100 + lowResTransparencyMinimumThreshold: 0 + rayTracingHalfResThreshold: 50 + lowResSSGIMinimumThreshold: 0 + lowResVolumetricCloudsMinimumThreshold: 50 + enableDLSS: 0 + lowresTransparentSettings: + enabled: 1 + checkerboardDepthBuffer: 1 + upsampleType: 1 + xrSettings: + singlePass: 1 + occlusionMesh: 1 + cameraJitter: 0 + allowMotionBlur: 0 + postProcessQualitySettings: + NearBlurSampleCount: 030000000500000008000000 + NearBlurMaxRadius: + - 2 + - 4 + - 7 + FarBlurSampleCount: 04000000070000000e000000 + FarBlurMaxRadius: + - 5 + - 8 + - 13 + DoFResolution: 040000000200000001000000 + DoFHighQualityFiltering: 000101 + DoFPhysicallyBased: 000000 + AdaptiveSamplingWeight: + - 0.5 + - 0.75 + - 2 + LimitManualRangeNearBlur: 000000 + MotionBlurSampleCount: 04000000080000000c000000 + BloomRes: 040000000200000002000000 + BloomHighQualityFiltering: 000101 + BloomHighQualityPrefiltering: 000001 + ChromaticAberrationMaxSamples: 03000000060000000c000000 + lightSettings: + useContactShadow: + m_Values: 000001 + m_SchemaId: + m_Id: With3Levels + maximumLODLevel: + m_Values: 000000000000000000000000 + m_SchemaId: + m_Id: With3Levels + lodBias: + m_Values: + - 1 + - 1 + - 1 + m_SchemaId: + m_Id: With3Levels + lightingQualitySettings: + AOStepCount: 040000000600000010000000 + AOFullRes: 000001 + AOMaximumRadiusPixels: 200000002800000050000000 + AOBilateralUpsample: 000101 + AODirectionCount: 010000000200000004000000 + ContactShadowSampleCount: 060000000a00000010000000 + SSRMaxRaySteps: 100000002000000040000000 + SSGIRaySteps: 200000004000000080000000 + SSGIDenoise: 010101 + SSGIHalfResDenoise: 010000 + SSGIDenoiserRadius: + - 0.75 + - 0.5 + - 0.5 + SSGISecondDenoise: 010101 + RTAORayLength: + - 0.5 + - 3 + - 20 + RTAOSampleCount: 010000000200000008000000 + RTAODenoise: 010101 + RTAODenoiserRadius: + - 0.25 + - 0.5 + - 0.65 + RTGIRayLength: + - 50 + - 50 + - 50 + RTGIFullResolution: 000001 + RTGIRaySteps: 200000003000000040000000 + RTGIDenoise: 010101 + RTGIHalfResDenoise: 010000 + RTGIDenoiserRadius: + - 1 + - 1 + - 1 + RTGISecondDenoise: 010101 + RTRMinSmoothness: + - 0.6 + - 0.4 + - 0 + RTRSmoothnessFadeStart: + - 0.7 + - 0.5 + - 0 + RTRRayLength: + - 50 + - 50 + - 50 + RTRFullResolution: 000001 + RTRRayMaxIterations: 200000003000000040000000 + RTRDenoise: 010101 + RTRDenoiserRadiusDimmer: + - 0.75 + - 0.75 + - 1 + RTRDenoiserAntiFlicker: + - 1 + - 1 + - 1 + Fog_ControlMode: 000000000000000000000000 + Fog_Budget: + - 0.166 + - 0.33 + - 0.666 + Fog_DepthRatio: + - 0.666 + - 0.666 + - 0.5 + gpuResidentDrawerSettings: + mode: 0 + smallMeshScreenPercentage: 0 + enableOcclusionCullingInCameras: 0 + useDepthPrepassForOccluders: 1 + m_ObsoleteLightLayerName0: + m_ObsoleteLightLayerName1: + m_ObsoleteLightLayerName2: + m_ObsoleteLightLayerName3: + m_ObsoleteLightLayerName4: + m_ObsoleteLightLayerName5: + m_ObsoleteLightLayerName6: + m_ObsoleteLightLayerName7: + m_ObsoleteDecalLayerName0: + m_ObsoleteDecalLayerName1: + m_ObsoleteDecalLayerName2: + m_ObsoleteDecalLayerName3: + m_ObsoleteDecalLayerName4: + m_ObsoleteDecalLayerName5: + m_ObsoleteDecalLayerName6: + m_ObsoleteDecalLayerName7: + m_ObsoleteSupportRuntimeDebugDisplay: 0 + allowShaderVariantStripping: 1 + enableSRPBatcher: 1 + availableMaterialQualityLevels: -1 + m_DefaultMaterialQualityLevel: 4 + diffusionProfileSettings: {fileID: 0} + m_VolumeProfile: {fileID: 0} + virtualTexturingSettings: + streamingCpuCacheSizeInMegaBytes: 256 + streamingMipPreloadTexturesPerFrame: 0 + streamingPreloadMipCount: 1 + streamingGpuCacheSettings: + - format: 0 + sizeInMegaBytes: 128 + m_UseRenderGraph: 1 + m_CompositorCustomVolumeComponentsList: + m_InjectionPoint: 1 + m_CustomPostProcessTypesAsString: [] + m_Version: 25 + m_ObsoleteFrameSettings: + overrides: 0 + enableShadow: 0 + enableContactShadows: 0 + enableShadowMask: 0 + enableSSR: 0 + enableSSAO: 0 + enableSubsurfaceScattering: 0 + enableTransmission: 0 + enableAtmosphericScattering: 0 + enableVolumetrics: 0 + enableReprojectionForVolumetrics: 0 + enableLightLayers: 0 + enableExposureControl: 1 + diffuseGlobalDimmer: 0 + specularGlobalDimmer: 0 + shaderLitMode: 0 + enableDepthPrepassWithDeferredRendering: 0 + enableTransparentPrepass: 0 + enableMotionVectors: 0 + enableObjectMotionVectors: 0 + enableDecals: 0 + enableRoughRefraction: 0 + enableTransparentPostpass: 0 + enableDistortion: 0 + enablePostprocess: 0 + enableOpaqueObjects: 0 + enableTransparentObjects: 0 + enableRealtimePlanarReflection: 0 + enableMSAA: 0 + enableAsyncCompute: 0 + runLightListAsync: 0 + runSSRAsync: 0 + runSSAOAsync: 0 + runContactShadowsAsync: 0 + runVolumeVoxelizationAsync: 0 + lightLoopSettings: + overrides: 0 + enableDeferredTileAndCluster: 0 + enableComputeLightEvaluation: 0 + enableComputeLightVariants: 0 + enableComputeMaterialVariants: 0 + enableFptlForForwardOpaque: 0 + enableBigTilePrepass: 0 + isFptlEnabled: 0 + m_ObsoleteBakedOrCustomReflectionFrameSettings: + overrides: 0 + enableShadow: 0 + enableContactShadows: 0 + enableShadowMask: 0 + enableSSR: 0 + enableSSAO: 0 + enableSubsurfaceScattering: 0 + enableTransmission: 0 + enableAtmosphericScattering: 0 + enableVolumetrics: 0 + enableReprojectionForVolumetrics: 0 + enableLightLayers: 0 + enableExposureControl: 1 + diffuseGlobalDimmer: 0 + specularGlobalDimmer: 0 + shaderLitMode: 0 + enableDepthPrepassWithDeferredRendering: 0 + enableTransparentPrepass: 0 + enableMotionVectors: 0 + enableObjectMotionVectors: 0 + enableDecals: 0 + enableRoughRefraction: 0 + enableTransparentPostpass: 0 + enableDistortion: 0 + enablePostprocess: 0 + enableOpaqueObjects: 0 + enableTransparentObjects: 0 + enableRealtimePlanarReflection: 0 + enableMSAA: 0 + enableAsyncCompute: 0 + runLightListAsync: 0 + runSSRAsync: 0 + runSSAOAsync: 0 + runContactShadowsAsync: 0 + runVolumeVoxelizationAsync: 0 + lightLoopSettings: + overrides: 0 + enableDeferredTileAndCluster: 0 + enableComputeLightEvaluation: 0 + enableComputeLightVariants: 0 + enableComputeMaterialVariants: 0 + enableFptlForForwardOpaque: 0 + enableBigTilePrepass: 0 + isFptlEnabled: 0 + m_ObsoleteRealtimeReflectionFrameSettings: + overrides: 0 + enableShadow: 0 + enableContactShadows: 0 + enableShadowMask: 0 + enableSSR: 0 + enableSSAO: 0 + enableSubsurfaceScattering: 0 + enableTransmission: 0 + enableAtmosphericScattering: 0 + enableVolumetrics: 0 + enableReprojectionForVolumetrics: 0 + enableLightLayers: 0 + enableExposureControl: 1 + diffuseGlobalDimmer: 0 + specularGlobalDimmer: 0 + shaderLitMode: 0 + enableDepthPrepassWithDeferredRendering: 0 + enableTransparentPrepass: 0 + enableMotionVectors: 0 + enableObjectMotionVectors: 0 + enableDecals: 0 + enableRoughRefraction: 0 + enableTransparentPostpass: 0 + enableDistortion: 0 + enablePostprocess: 0 + enableOpaqueObjects: 0 + enableTransparentObjects: 0 + enableRealtimePlanarReflection: 0 + enableMSAA: 0 + enableAsyncCompute: 0 + runLightListAsync: 0 + runSSRAsync: 0 + runSSAOAsync: 0 + runContactShadowsAsync: 0 + runVolumeVoxelizationAsync: 0 + lightLoopSettings: + overrides: 0 + enableDeferredTileAndCluster: 0 + enableComputeLightEvaluation: 0 + enableComputeLightVariants: 0 + enableComputeMaterialVariants: 0 + enableFptlForForwardOpaque: 0 + enableBigTilePrepass: 0 + isFptlEnabled: 0 + m_ObsoleteDefaultVolumeProfile: {fileID: 0} + m_ObsoleteDefaultLookDevProfile: {fileID: 0} + m_ObsoleteFrameSettingsMovedToDefaultSettings: + bitDatas: + data1: 0 + data2: 0 + lodBias: 0 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 0 + sssCustomDownsampleSteps: 0 + msaaMode: 0 + materialQuality: 0 + m_ObsoleteBakedOrCustomReflectionFrameSettingsMovedToDefaultSettings: + bitDatas: + data1: 0 + data2: 0 + lodBias: 0 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 0 + sssCustomDownsampleSteps: 0 + msaaMode: 0 + materialQuality: 0 + m_ObsoleteRealtimeReflectionFrameSettingsMovedToDefaultSettings: + bitDatas: + data1: 0 + data2: 0 + lodBias: 0 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 0 + sssCustomDownsampleSteps: 0 + msaaMode: 0 + materialQuality: 0 + m_ObsoleteBeforeTransparentCustomPostProcesses: [] + m_ObsoleteBeforePostProcessCustomPostProcesses: [] + m_ObsoleteAfterPostProcessCustomPostProcesses: [] + m_ObsoleteBeforeTAACustomPostProcesses: [] + m_ObsoleteShaderVariantLogLevel: 0 + m_ObsoleteLensAttenuation: 0 + m_ObsoleteDiffusionProfileSettingsList: [] + m_PrefilterUseLegacyLightmaps: 0 diff --git a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset.meta b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset.meta new file mode 100644 index 00000000..51ef9d35 --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineAsset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dbb49b2436f43c6418efe37545e99ed8 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset new file mode 100644 index 00000000..d5a880cc --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset @@ -0,0 +1,824 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 781cc897cf8675041a751163b51f97dd, type: 3} + m_Name: HDRenderPipelineGlobalSettings + m_EditorClassIdentifier: + m_CustomPostProcessOrdersSettings: + m_Version: 0 + m_BeforeTransparentCustomPostProcesses: + m_InjectionPoint: 0 + m_CustomPostProcessTypesAsString: [] + m_BeforeTAACustomPostProcesses: + m_InjectionPoint: 3 + m_CustomPostProcessTypesAsString: [] + m_BeforePostProcessCustomPostProcesses: + m_InjectionPoint: 1 + m_CustomPostProcessTypesAsString: [] + m_AfterPostProcessBlursCustomPostProcesses: + m_InjectionPoint: 4 + m_CustomPostProcessTypesAsString: [] + m_AfterPostProcessCustomPostProcesses: + m_InjectionPoint: 2 + m_CustomPostProcessTypesAsString: [] + beforeTransparentCustomPostProcesses: [] + beforePostProcessCustomPostProcesses: [] + afterPostProcessBlursCustomPostProcesses: [] + afterPostProcessCustomPostProcesses: [] + beforeTAACustomPostProcesses: [] + m_ShaderStrippingSetting: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + m_ShaderVariantLogLevel: 0 + m_SupportRuntimeDebugDisplay: 0 + m_ExportShaderVariants: 1 + m_StripDebugVariants: 0 + DLSSProjectId: 000000 + useDLSSCustomProjectId: 0 + supportProbeVolumes: 0 + autoRegisterDiffusionProfiles: 1 + analyticDerivativeEmulation: 0 + analyticDerivativeDebugOutput: 0 + lensAttenuationMode: 0 + colorGradingSpace: 0 + m_ObsoleteDiffusionProfileSettingsList: [] + specularFade: 0 + rendererListCulling: 0 + m_ObsoleteDefaultVolumeProfile: {fileID: 0} + m_ObsoleteLookDevVolumeProfile: {fileID: 0} + m_ObsoleteRenderingPathDefaultCameraFrameSettings: + bitDatas: + data1: 5770166122053453 + data2: 12934340311651418136 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_ObsoleteRenderingPathDefaultBakedOrCustomReflectionFrameSettings: + bitDatas: + data1: 4643523019153229 + data2: 12898309406071980048 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_ObsoleteRenderingPathDefaultRealtimeReflectionFrameSettings: + bitDatas: + data1: 4638910381585229 + data2: 12898310333516513304 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_ObsoleteRenderingPath: + m_Version: 0 + m_Camera: + bitDatas: + data1: 5770166122053453 + data2: 12934340311651418136 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_CustomOrBakedReflection: + bitDatas: + data1: 4643523019153229 + data2: 12898309406071980048 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_RealtimeReflection: + bitDatas: + data1: 4638910381585229 + data2: 12898310333516513304 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_Settings: + m_SettingsList: + m_List: + - rid: 3368384739993452858 + - rid: 3368384739993452859 + - rid: 3368384739993452860 + - rid: 3368384739993452861 + - rid: 3368384739993452862 + - rid: 3368384739993452863 + - rid: 3368384739993452864 + - rid: 3368384739993452865 + - rid: 3368384739993452866 + - rid: 3368384739993452867 + - rid: 3368384739993452868 + - rid: 3368384739993452869 + - rid: 3368384739993452870 + - rid: 3368384739993452871 + - rid: 3368384739993452872 + - rid: 3368384739993452873 + - rid: 3368384739993452874 + - rid: 3368384739993452875 + - rid: 3368384739993452876 + - rid: 3368384739993452877 + - rid: 3368384739993452878 + - rid: 3368384739993452879 + - rid: 3368384739993452880 + - rid: 3368384739993452881 + - rid: 3368384739993452882 + - rid: 3368384739993452883 + - rid: 3368384739993452884 + - rid: 3368384739993452885 + - rid: 3368384739993452886 + - rid: 3368384739993452887 + - rid: 3368384739993452888 + - rid: 3368384739993452889 + - rid: 3368384739993452890 + m_RuntimeSettings: + m_List: [] + renderingLayerNames: + - Default + lightLayerName0: + lightLayerName1: + lightLayerName2: + lightLayerName3: + lightLayerName4: + lightLayerName5: + lightLayerName6: + lightLayerName7: + decalLayerName0: + decalLayerName1: + decalLayerName2: + decalLayerName3: + decalLayerName4: + decalLayerName5: + decalLayerName6: + decalLayerName7: + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_Version: 14 + references: + version: 2 + RefIds: + - rid: 3368384739993452858 + type: {class: HDRPRayTracingResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_ReflectionRayTracingRT: {fileID: 4807578003741378534, guid: 1a500e5079fba734aa90fe92e70ea131, type: 3} + m_ReflectionRayTracingCS: {fileID: 7200000, guid: 591207652a75a4844a89c0b9f45a61f2, type: 3} + m_ReflectionBilateralFilterCS: {fileID: 7200000, guid: 07c445e7aa373284a9cc1584ca9b3f84, type: 3} + m_ShadowRayTracingRT: {fileID: 4807578003741378534, guid: 6f93cb4dc095de14993f8d2baa972d5b, type: 3} + m_ContactShadowRayTracingRT: {fileID: 4807578003741378534, guid: acaf840af875ab541b8f10069b7444c8, type: 3} + m_ShadowRayTracingCS: {fileID: 7200000, guid: fc95b5dff16ba594896e211a389c03fc, type: 3} + m_ShadowFilterCS: {fileID: 7200000, guid: f71fd853a538bf74e9e5a7228fc14dae, type: 3} + m_ForwardRayTracing: {fileID: 4807578003741378534, guid: d3a89a2d3f73b3e4da6f191e844fe68c, type: 3} + m_LightClusterBuildCS: {fileID: 7200000, guid: c0625ea908b52854bbf1d456e34026e4, type: 3} + m_LightClusterDebugS: {fileID: 4800000, guid: c4d81c6e573560444bb1ea11ae4acfcb, type: 3} + m_LightClusterDebugCS: {fileID: 7200000, guid: d48a3a5496d98a44c89f335934805d10, type: 3} + m_IndirectDiffuseRayTracingOffRT: {fileID: 4807578003741378534, guid: fbcaf423d9f8e3843b2c046420608293, type: 3} + m_IndirectDiffuseRayTracingL1RT: {fileID: 4807578003741378534, guid: 653044b9878c5764e818b20399112284, type: 3} + m_IndirectDiffuseRaytracingL2RT: {fileID: 4807578003741378534, guid: 866a72c4868acec4088b0956b9ca73f9, type: 3} + m_IndirectDiffuseRayTracingCS: {fileID: 7200000, guid: c5ad968b7cd39114d85dd860b3809087, type: 3} + m_AoRayTracingRT: {fileID: 4807578003741378534, guid: 82dc8cd069971d2488c502b0f32b94fb, type: 3} + m_AoRayTracingCS: {fileID: 7200000, guid: 10c05366baf9b0a44a827f3ef890b9e6, type: 3} + m_SubSurfaceRayTracingRT: {fileID: 4807578003741378534, guid: b29a18f967c92364492508dddf78cff7, type: 3} + m_SubSurfaceRayTracingCS: {fileID: 7200000, guid: 4e5684a8dba46fe42a47642f9b0a6b89, type: 3} + m_SimpleDenoiserCS: {fileID: 7200000, guid: 74a980f1da9a4f842996035350fe756c, type: 3} + m_ReflectionDenoiserCS: {fileID: 7200000, guid: 1b12fb238086d0f49983b4aa72768349, type: 3} + m_DiffuseShadowDenoiserCS: {fileID: 7200000, guid: 9af806eab5889a74dad838edc9b07d07, type: 3} + m_ReblurPreBlurCS: {fileID: 7200000, guid: 0be88ddf5240d49468d9159340465bfd, type: 3} + m_ReblurTemporalAccumulationCS: {fileID: 7200000, guid: 11794ae415a38c747ba65d57d1bb60f9, type: 3} + m_ReblurMipGenerationCS: {fileID: 7200000, guid: 44195ddb6d9240646847cbf4f38dfa98, type: 3} + m_ReblurHistoryFixCS: {fileID: 7200000, guid: 4cc204b99166a9c40819bc04927c4feb, type: 3} + m_ReblurBlurCS: {fileID: 7200000, guid: cff077c60ac76074893014e2f49e3159, type: 3} + m_ReblurPostBlurCS: {fileID: 7200000, guid: 965700f9b9e0fec4bb31415ae91f0e09, type: 3} + m_ReblurCopyHistoryCS: {fileID: 7200000, guid: 0d5230c403883b84cbf9d1d3b9e57beb, type: 3} + m_ReblurTemporalStabilizationCS: {fileID: 7200000, guid: 4feaa605aeff33840b659850ce6bfcc2, type: 3} + m_GBufferRayTracingRT: {fileID: 4807578003741378534, guid: e4c61a77b91f35845bbb546b848b18e5, type: 3} + m_DeferredRayTracingCS: {fileID: 7200000, guid: 6e5ef632062bc484f812c7976f450ed1, type: 3} + m_PathTracingRT: {fileID: 4807578003741378534, guid: c4f4525a058009a409fea974f9ad8d03, type: 3} + m_PathTracingSkySamplingDataCS: {fileID: 7200000, guid: 8ef71a4b666992544ac5575a0e599a68, type: 3} + m_RayMarchingCS: {fileID: 7200000, guid: 78d9a89700295a4418d0921bf27e1857, type: 3} + m_RayBinningCS: {fileID: 7200000, guid: cddcb515ffe9a914893d6d8fc1d85454, type: 3} + m_CountTracedRaysCS: {fileID: 7200000, guid: e1f3fa867f1dfbd4ab7dd4d39d2b96d8, type: 3} + m_ReflectionFilterMappingTexture: {fileID: 2800000, guid: 82eec49626a00b047ba86244607816c8, type: 3} + m_RtasDebugRT: {fileID: 4807578003741378534, guid: 7f98079d20376fd4f8590d58be99ab0d, type: 3} + - rid: 3368384739993452859 + type: {class: RenderingPathFrameSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_Camera: + bitDatas: + data1: 5770166122053453 + data2: 12934340311651418136 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_CustomOrBakedReflection: + bitDatas: + data1: 4643523019153229 + data2: 12898309406071980048 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + m_RealtimeReflection: + bitDatas: + data1: 4638910381585229 + data2: 12898310333516513304 + lodBias: 1 + lodBiasMode: 0 + lodBiasQualityLevel: 0 + maximumLODLevel: 0 + maximumLODLevelMode: 0 + maximumLODLevelQualityLevel: 0 + sssQualityMode: 0 + sssQualityLevel: 0 + sssCustomSampleBudget: 20 + sssCustomDownsampleSteps: 0 + msaaMode: 1 + materialQuality: 0 + - rid: 3368384739993452860 + type: {class: HDRenderPipelineEditorTextures, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_MoonAlbedo: {fileID: 2800000, guid: cce9f0cf7e606e547a7317aedb4ad6d9, type: 3} + - rid: 3368384739993452861 + type: {class: WaterSystemGlobalSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 1 + m_EnableMaskAndCurrentWaterDecals: 0 + - rid: 3368384739993452862 + type: {class: HDRenderPipelineEditorShaders, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_GpuInlineDebugDrawerLine: {fileID: 4800000, guid: 039c5248164c71b4aa6d780131c1bfaf, type: 3} + m_AutodeskInteractive: {fileID: 4800000, guid: 7252379db4c18b641b517f2c91bb57e1, type: 3} + m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: ee2ce0be66f45d9449d71ba9b49c2acd, type: 3} + m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 29c4adff654862b40a2e9fb2015a42c3, type: 3} + m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 4819724840ee9444f9da841b477038ce, type: 3} + m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: d81c74dd5f463104ca482aa23ef2c798, type: 3} + - rid: 3368384739993452863 + type: {class: AnalyticDerivativeSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_AnalyticDerivativeEmulation: 0 + m_AnalyticDerivativeDebugOutput: 0 + - rid: 3368384739993452864 + type: {class: CustomPostProcessOrdersSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_BeforeTransparentCustomPostProcesses: + m_InjectionPoint: 0 + m_CustomPostProcessTypesAsString: [] + m_BeforeTAACustomPostProcesses: + m_InjectionPoint: 3 + m_CustomPostProcessTypesAsString: [] + m_BeforePostProcessCustomPostProcesses: + m_InjectionPoint: 1 + m_CustomPostProcessTypesAsString: [] + m_AfterPostProcessBlursCustomPostProcesses: + m_InjectionPoint: 4 + m_CustomPostProcessTypesAsString: [] + m_AfterPostProcessCustomPostProcesses: + m_InjectionPoint: 2 + m_CustomPostProcessTypesAsString: [] + - rid: 3368384739993452865 + type: {class: DiffusionProfileDefaultSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_AutoRegisterDiffusionProfiles: 0 + - rid: 3368384739993452866 + type: {class: LensSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_LensAttenuationMode: 0 + - rid: 3368384739993452867 + type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_DynamicRenderPassCulling: 0 + - rid: 3368384739993452868 + type: {class: HDRenderPipelineRuntimeMaterials, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_PBRSkyMaterial: {fileID: -876546973899608171, guid: 02532cbb810fb404db49da84f1efe41e, type: 3} + m_AreaLightMaterial: {fileID: 2100000, guid: ef5f65c980e25304098a95e28f3bd20b, type: 2} + m_AreaLightCookieMaterial: {fileID: 2100000, guid: 78c6825c5d9c3664f9879ae8609618c7, type: 2} + - rid: 3368384739993452869 + type: {class: HDRenderPipelineEditorAssets, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: f940a8037e6cda542891dc1aac1fa4e8, type: 2} + m_LookDevDefaultLookDevVolumeProfile: {fileID: 11400000, guid: 254c4fe87beb7be4fa72e1681edbed02, type: 2} + m_DefaultDiffusionProfileSettingsList: + - {fileID: 11400000, guid: 404820c4cf36ad944862fa59c56064f0, type: 2} + - {fileID: 11400000, guid: 2384dbf2c1c420f45a792fbc315fbfb1, type: 2} + - rid: 3368384739993452870 + type: {class: VolumetricCloudsRuntimeResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_VolumetricCloudsCS: {fileID: 7200000, guid: f911a8577fa9a4546a6b255bcf888baf, type: 3} + m_VolumetricCloudsTraceCS: {fileID: 7200000, guid: 66eaa9becc91a8646a88c15375af8b86, type: 3} + m_VolumetricCloudsTraceShadowsCS: {fileID: 7200000, guid: f350c5c3b41fd1b408aac9076f96610e, type: 3} + m_VolumetricCloudsShadowFilterCS: {fileID: 7200000, guid: 771ea9a52996c024095906ac37a8a71f, type: 3} + m_VolumetricCloudMapGeneratorCS: {fileID: 7200000, guid: 6b22771f0aa98744cb09f455a5a818cb, type: 3} + m_VolumetricCloudsCombinePS: {fileID: 4800000, guid: 12f1a69ddf916f042ae6ce8a994506f3, type: 3} + m_CloudLutRainAO: {fileID: 2800000, guid: e0bcfddf26ed5584ba3d8b94d3200114, type: 3} + m_WorleyNoise128RGBA: {fileID: 11700000, guid: 1fe54a721d0e2504e89f121c723404a8, type: 3} + m_WorleyNoise32RGB: {fileID: 11700000, guid: ec156c314a242914dbb706f73ad78cf2, type: 3} + m_PerlinNoise32RGB: {fileID: 11700000, guid: d1aae012f8a4f23478471851f17ff915, type: 3} + - rid: 3368384739993452871 + type: {class: ColorGradingSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_ColorGradingSpace: 0 + - rid: 3368384739993452872 + type: {class: SpecularFadeSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_SpecularFade: 0 + - rid: 3368384739993452873 + type: {class: HDRenderPipelineRuntimeAssets, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_DefaultDiffusionProfile: {fileID: 11400000, guid: 2b7005ba3a4d8474b8cdc34141ad766e, type: 2} + m_ComputeMaterialLibrary: {fileID: 11400000, guid: 833ab0ec618db411699ea8cb1a221d0d, type: 2} + m_EmissiveCylinderMesh: {fileID: 2534964839176971238, guid: accb6d90f0d50fe4ca0f68159b4323de, type: 3} + m_EmissiveQuadMesh: {fileID: 4300000, guid: 1d5a8595286f94f4bb54171d49f473c3, type: 3} + m_SphereMesh: {fileID: 4300000, guid: 9e0af751bc36ea146940ba245193e28c, type: 3} + - rid: 3368384739993452874 + type: {class: HDRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_DebugFontTex: {fileID: 2800000, guid: a3ad2df0e49aaa341a3b3a80f93b3f66, type: 3} + m_ColorGradient: {fileID: 2800000, guid: 4ea52e665573c1644bf05dd9b11fd2a4, type: 3} + m_MatcapTex: {fileID: 2800000, guid: e655445a13b501944a2641ea144edda5, type: 3} + m_BlueNoise16LTex: + - {fileID: 2800000, guid: efa2ea5416a18da46b64f1266464ffc7, type: 3} + - {fileID: 2800000, guid: 0330b95d1d741fc4281eac4aec9d2eae, type: 3} + - {fileID: 2800000, guid: 8a51abfa06f36a24e8621796aa6cd4b3, type: 3} + - {fileID: 2800000, guid: 29f15236a89d7d748abaa25d8f69f614, type: 3} + - {fileID: 2800000, guid: 6abadf255584bba4c944b1e00436ef03, type: 3} + - {fileID: 2800000, guid: 979eec7b1833b0441a2cc73bf8db2544, type: 3} + - {fileID: 2800000, guid: 8f520abb155364c46b0f0748ef34ec0d, type: 3} + - {fileID: 2800000, guid: 8b7bdf66a62cb51409d47548bb0d542f, type: 3} + - {fileID: 2800000, guid: fed7135c4936ff947b1477236ec392cd, type: 3} + - {fileID: 2800000, guid: 3c2108b42cf27e3479d8587367508c6f, type: 3} + - {fileID: 2800000, guid: b6fa54cec31997445a1b5fd8e2887484, type: 3} + - {fileID: 2800000, guid: 79f42a2cc0e32614ba4e0fee3e0f88b9, type: 3} + - {fileID: 2800000, guid: a75de30c08d74744c9e973e42c2e00e5, type: 3} + - {fileID: 2800000, guid: c6c47a7f59293a847a8471bb74b9a262, type: 3} + - {fileID: 2800000, guid: 55e474b0d2c992240aed7e3bcbebb78a, type: 3} + - {fileID: 2800000, guid: b987ab952dc89bc439eebfaf7b977f51, type: 3} + - {fileID: 2800000, guid: f242013130364874486ad0854d54b5d9, type: 3} + - {fileID: 2800000, guid: 5e40f3339a0a5be4ea4442562c53575a, type: 3} + - {fileID: 2800000, guid: 6f6e861d2ff8cd641b424245a18393a0, type: 3} + - {fileID: 2800000, guid: 96b4b7db9e972c54db03d280a7924fb8, type: 3} + - {fileID: 2800000, guid: f8c387db83f623d4c875b355974b1398, type: 3} + - {fileID: 2800000, guid: ba5d54ee870713c41a40c8435ad4fdea, type: 3} + - {fileID: 2800000, guid: 98de916e94bbf4541981fe7c1bd7008f, type: 3} + - {fileID: 2800000, guid: e013b0f34384ea242b2366eafe8d66b4, type: 3} + - {fileID: 2800000, guid: 08e7f74e876f85247ad1104f35322e19, type: 3} + - {fileID: 2800000, guid: eaed38d1a2336e14b8fd351f65d3eddb, type: 3} + - {fileID: 2800000, guid: 9b47ce76307ef714d9c08f1f7d37a173, type: 3} + - {fileID: 2800000, guid: 4cf893d4f07705d40a404330fb6694d5, type: 3} + - {fileID: 2800000, guid: 4ba6dd9a348fff64aba90f736da533bd, type: 3} + - {fileID: 2800000, guid: faedd3bf25384dc47b38a94a658e19fc, type: 3} + - {fileID: 2800000, guid: cb7d595d4b67de146abf1b1f4d45f417, type: 3} + - {fileID: 2800000, guid: a836cbb14cfefd54a8b9ca37d6aadde6, type: 3} + m_BlueNoise16RGBTex: + - {fileID: 2800000, guid: b232903ea527aba4786ab9a725e610e9, type: 3} + - {fileID: 2800000, guid: fe6c6d7fed228ae4c9034639926613ff, type: 3} + - {fileID: 2800000, guid: 1dae10311eb6da5428b4247f883f9f0c, type: 3} + - {fileID: 2800000, guid: 668a0101474cc3149bdf7b69bdaad1eb, type: 3} + - {fileID: 2800000, guid: a3a352512b3774b44aeeb7414aafce58, type: 3} + - {fileID: 2800000, guid: f3767acdf061ed14380a360366ffe91c, type: 3} + - {fileID: 2800000, guid: a0d5f1353077a9d4d9bf0fdfbc07d718, type: 3} + - {fileID: 2800000, guid: 5a195bcf888979144a5db9a99c43a747, type: 3} + - {fileID: 2800000, guid: 8d79e4efe64973b4ab5c6e3982b15772, type: 3} + - {fileID: 2800000, guid: eaf67a58951a945428cb394e81ed3765, type: 3} + - {fileID: 2800000, guid: 287dda93fa25eea4fbb9f7f5ef014718, type: 3} + - {fileID: 2800000, guid: 4cb7c602f368c2d44b42c51c353e5b2c, type: 3} + - {fileID: 2800000, guid: 3fa94aebb9c04c54aa0cebde90c210ff, type: 3} + - {fileID: 2800000, guid: aa35bbfe9eac94d49bb95cd8804c51a7, type: 3} + - {fileID: 2800000, guid: ba3b2a48f5297c74eb3b4b2771629d60, type: 3} + - {fileID: 2800000, guid: 17165acde01c02f4bb45d0ffd25d5158, type: 3} + - {fileID: 2800000, guid: 280a79ac7e2b6e940a7199b8f7e10407, type: 3} + - {fileID: 2800000, guid: b75a320b602f27c4ab28904a10142a98, type: 3} + - {fileID: 2800000, guid: 226149deca448e745a7c377133e6ca7f, type: 3} + - {fileID: 2800000, guid: 059fba768df29964e9f07bd4fffb5776, type: 3} + - {fileID: 2800000, guid: 9dee14979276d81489a17afa605f3030, type: 3} + - {fileID: 2800000, guid: 3963568f414ac1545b64e5f1ff5daf5d, type: 3} + - {fileID: 2800000, guid: a96a5d146fa164d4ebd67318a957a75a, type: 3} + - {fileID: 2800000, guid: b5fa2a735b9278349a91f3dbb77691c0, type: 3} + - {fileID: 2800000, guid: d3c864eb1f6e4b34c91d1931ad0064a3, type: 3} + - {fileID: 2800000, guid: 97f308a7009457545a975a9a498499ce, type: 3} + - {fileID: 2800000, guid: daa405d7e1e253a40952bed9e9ca63cc, type: 3} + - {fileID: 2800000, guid: 4dbadef8044229d47b9a391147dad1c4, type: 3} + - {fileID: 2800000, guid: 7ce9507d3d1997743b39f335a7f868fd, type: 3} + - {fileID: 2800000, guid: 7641a2b116fafd64d9c3d6459fdfe801, type: 3} + - {fileID: 2800000, guid: c6a5e40e6746fef4fa486e8f620ee8d4, type: 3} + - {fileID: 2800000, guid: fd4189357c6dfb94fa2d36afbce72086, type: 3} + m_OwenScrambledRGBATex: {fileID: 2800000, guid: b0fe077c1ee7d80428f3d8dfa28a027d, type: 3} + m_OwenScrambled256Tex: {fileID: 2800000, guid: 2a205358e67aa9e4a94a128ac9362f4e, type: 3} + m_ScramblingTex: {fileID: 2800000, guid: bf25cd6288e2c8d43854a61a8496a830, type: 3} + m_RankingTile1SPP: {fileID: 2800000, guid: f2fe0251f704c4c478a8063775cffedb, type: 3} + m_ScramblingTile1SPP: {fileID: 2800000, guid: 6185473f62ad3e74da4acac5d482917a, type: 3} + m_RankingTile8SPP: {fileID: 2800000, guid: af4bd638a4b3eb14781e6441adcdfbb9, type: 3} + m_ScramblingTile8SPP: {fileID: 2800000, guid: 152f8b933250a7b448fc2d4d301b9944, type: 3} + m_RankingTile256SPP: {fileID: 2800000, guid: 1e604a266c415cd46b36d97cd9220aa8, type: 3} + m_ScramblingTile256SPP: {fileID: 2800000, guid: 882fb55d7b3e7c94598a318df9376e32, type: 3} + m_EyeCausticLUT: {fileID: 11700000, guid: d4ec12283a044584794485916f4142a9, type: 3} + m_HairAttenuationLUT: {fileID: 11700000, guid: d37662e2b254e594abf839dddc5ab653, type: 2} + m_HairAzimuthalScatteringLUT: {fileID: 11700000, guid: d217deac7ff61094080126811521ab5b, type: 2} + m_HairLongitudinalScatteringLUT: {fileID: 11700000, guid: 0da412d38ea6ba3459322abe6984ca9b, type: 2} + m_FilmGrainTex: + - {fileID: 2800000, guid: 284a1ac236869fa4eacf377d73c7dff8, type: 3} + - {fileID: 2800000, guid: bd74961b009b93145a998ae93a5fc186, type: 3} + - {fileID: 2800000, guid: 58c1a5135746f854e8841c70a4b588b9, type: 3} + - {fileID: 2800000, guid: bdc6fb6e37de5824bb06e17ac19a8a1d, type: 3} + - {fileID: 2800000, guid: e4d8303457ba4854090965d854a7a741, type: 3} + - {fileID: 2800000, guid: 75e19bf5d3ef41d489aa05586243b58b, type: 3} + - {fileID: 2800000, guid: 6cafd4bed3e420a45a5702d61df0762c, type: 3} + - {fileID: 2800000, guid: a187955d1d88a954cb32c3c4e5f0aeda, type: 3} + - {fileID: 2800000, guid: 3f3cb0f4924d7a241b82a9081875f30d, type: 3} + - {fileID: 2800000, guid: a35bdcb2008832646b3c8d2eb11e38a9, type: 3} + m_SMAASearchTex: {fileID: 2800000, guid: dc95d70472e232b438d0fd38651e7ec2, type: 3} + m_SMAAAreaTex: {fileID: 2800000, guid: 92e0d85ab4eca874098e7fcf6f8f674e, type: 3} + m_DefaultHDRISky: {fileID: 8900000, guid: 8253d41e6e8b11a4cbe77a4f8f82934d, type: 3} + m_DefaultCloudMap: {fileID: 2800000, guid: 57a33fc2476a01644865bfde5f06e2f4, type: 3} + - rid: 3368384739993452875 + type: {class: HDRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_DefaultMaterial: {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17, type: 2} + m_DefaultParticleMaterial: {fileID: 2100000, guid: b739a3f02ff77bf48b7636e64c3e3b4c, type: 2} + m_DefaultTerrainMaterial: {fileID: 2100000, guid: 22ff8771d87ef27429e670136399094b, type: 2} + m_DefaultMirrorMat: {fileID: 2100000, guid: 6b17274157b33bc45b6a40e7d4ff51fe, type: 2} + m_DefaultDecalMat: {fileID: 2100000, guid: 500e733574922d04ea961553b1b26a63, type: 2} + m_GUITextureBlit2SRGB: {fileID: 2100000, guid: 6e95c04e4e686554e8bed96ee69f690c, type: 2} + - rid: 3368384739993452876 + type: {class: HDRPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_VolumeProfile: {fileID: 11400000, guid: 0a821dc928355c04091e259c62eaa534, type: 2} + - rid: 3368384739993452877 + type: {class: WaterSystemRuntimeResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_WaterMaterial: {fileID: -876546973899608171, guid: 3fda5e465882bec4d8e64161b681806c, type: 3} + m_WaterExclusionMaterial: {fileID: 2100000, guid: 1e520c84f7fd17c46af5586f6632155c, type: 2} + m_WaterDecalMaterial: {fileID: -876546973899608171, guid: 7e2c0d424490bfc4698c37245b8c63ed, type: 3} + m_WaterSimulationCS: {fileID: 7200000, guid: 32ac7f445960a854595586a600c24034, type: 3} + m_FourierTransformCS: {fileID: 7200000, guid: bc2ee21836a0b5147900ef35a6e1f508, type: 3} + m_WaterEvaluationCS: {fileID: 7200000, guid: c24e765a2bbaace4d9a0ecec600e1967, type: 3} + m_WaterPS: {fileID: -6465566751694194690, guid: 3fda5e465882bec4d8e64161b681806c, type: 3} + m_WaterLightingCS: {fileID: 7200000, guid: 05d00ad19f202ee4891fdaa90d6d1b23, type: 3} + m_WaterLineCS: {fileID: 7200000, guid: 1e7e38362b5026d44ab4f3ff4a612026, type: 3} + m_WaterCausticsPS: {fileID: 4800000, guid: 020d64d10886f754e91664d240248c13, type: 3} + m_WaterDecalPS: {fileID: 4800000, guid: cf863cbd7bbd44a43b414caed214ba29, type: 3} + m_WaterDeformationCS: {fileID: 7200000, guid: 9b8063fa5834d4243bfca8c68a92d9f1, type: 3} + m_WaterFoamCS: {fileID: 7200000, guid: 0d16d14b783e65f4d81dbcece2bd0ef9, type: 3} + m_WaterDecalMigrationShader: {fileID: -6465566751694194690, guid: 9f1661ed5b4d6ee4685ad5683b09a903, type: 3} + m_FoamMask: {fileID: 2800000, guid: ca1d72d84c34dba4390eab4c86e62f62, type: 3} + - rid: 3368384739993452878 + type: {class: HDRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_DefaultShader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3} + m_CameraMotionVectorsPS: {fileID: 4800000, guid: 035941b63024d1943af48811c1db20d9, type: 3} + m_ColorPyramidPS: {fileID: 4800000, guid: 2fcfb8d92f45e4549b3f0bad5d0654bf, type: 3} + m_ColorPyramidCS: {fileID: 7200000, guid: 4e3267a1135742441a14298d8dcac04a, type: 3} + m_DepthPyramidCS: {fileID: 7200000, guid: 64a553bb564274041906f78ffba955e4, type: 3} + m_MaxZCS: {fileID: 7200000, guid: e95abf8c7230c344595f41c4dd5ff517, type: 3} + m_ApplyDistortionPS: {fileID: 4800000, guid: 02ae56f4306413c4a96dcf005cde1971, type: 3} + m_CustomPassUtils: {fileID: 4800000, guid: 7e3722d0388000848acb25fd3cc8c088, type: 3} + m_CustomPassRenderersUtils: {fileID: 4800000, guid: cef5ba33ee5063d4c8b495d2292e394d, type: 3} + m_ClearStencilBufferPS: {fileID: 4800000, guid: 8ea49ef16606acd489439e676ab84040, type: 3} + m_CopyStencilBufferPS: {fileID: 4800000, guid: 3d1574f1cdfa0ce4995f9bc79ed7f8ec, type: 3} + m_CopyDepthBufferPS: {fileID: 4800000, guid: 42dfcc8fe803ece4096c58630689982f, type: 3} + m_BlitPS: {fileID: 4800000, guid: e22fc1942c664490980b8793dd4a163d, type: 3} + m_BlitColorAndDepthPS: {fileID: 4800000, guid: b22ad378c678348729d3a3f981b9f270, type: 3} + m_DownsampleDepthPS: {fileID: 4800000, guid: 67d6171b0acc6554aad48c845ec7e67f, type: 3} + m_UpsampleTransparentPS: {fileID: 4800000, guid: 2ad7ce40f0dbaf64dadef1f58d8524d3, type: 3} + m_ResolveStencilCS: {fileID: 7200000, guid: 65b89cac5f286b043a31bf8041776ee7, type: 3} + m_DebugDisplayLatlongPS: {fileID: 4800000, guid: c1d1d149a043a5349ba367da6c2051ba, type: 3} + m_DebugViewMaterialGBufferPS: {fileID: 4800000, guid: 439949ea1bfa91b4ba0d04269fcde33d, type: 3} + m_DebugViewTilesPS: {fileID: 4800000, guid: c7c2bd17b06ceb4468e14081aaf1b96f, type: 3} + m_DebugFullScreenPS: {fileID: 4800000, guid: e874aca2df8300a488258738c31f85cf, type: 3} + m_DebugColorPickerPS: {fileID: 4800000, guid: 8137b807709e178498f22ed710864bb0, type: 3} + m_DebugExposurePS: {fileID: 4800000, guid: 0ef322534f047a34c96d29419d56d17a, type: 3} + m_DebugHDRPS: {fileID: 4800000, guid: 9bc5229549892084da43ad706d84f1bc, type: 3} + m_DebugLightVolumePS: {fileID: 4800000, guid: 8e706c0e71fcec34a8f5c9713e5e2943, type: 3} + m_DebugLightVolumeCS: {fileID: 7200000, guid: f5d5d21faef5cf445ac2c5d8ff9c4184, type: 3} + m_DebugBlitQuad: {fileID: 4800000, guid: cf5ca5b6ef18b3f429ed707ee9ceac9f, type: 3} + m_DebugViewVirtualTexturingBlit: {fileID: 4800000, guid: 55d195396b03b804eb78c92d468e3c8e, type: 3} + m_MaterialError: {fileID: 4800000, guid: 79a966a5200a456188dec0d48d805614, type: 3} + m_MaterialLoading: {fileID: 4800000, guid: 392325671f122f540be9033ca5ae7a56, type: 3} + m_ClearDebugBufferCS: {fileID: 7200000, guid: 7fc6041d5cf70004aa33bb1ac64e3c06, type: 3} + m_DebugWaveformPS: {fileID: 4800000, guid: 0024f9d09a828734192f3e1cd5931745, type: 3} + m_DebugWaveformCS: {fileID: 7200000, guid: 62b785f79355903428a21d5d8f8aeabe, type: 3} + m_DebugVectorscopePS: {fileID: 4800000, guid: 7a09af24008164d40ae85ccd6bf87e17, type: 3} + m_DebugVectorscopeCS: {fileID: 7200000, guid: 6a70efb18a2b2964c8eb0fc04aba20e9, type: 3} + m_DebugImageHistogramCS: {fileID: 7200000, guid: 52cc17ef5a5ffc443a5c142f9b745a85, type: 3} + m_DebugHDRxyMappingCS: {fileID: 7200000, guid: f055d2983d992b64494f1a03fc725cde, type: 3} + m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 22de19bc461f84742857dd64c56b0397, type: 3} + m_PlanarReflectionFilteringCS: {fileID: 7200000, guid: 9f3f8a01b8caaaa4595591dc96d43dd2, type: 3} + m_ScreenSpaceGlobalIlluminationCS: {fileID: 7200000, guid: 96170a954eb538b40a5ff369552c3629, type: 3} + m_ScreenSpaceReflectionsCS: {fileID: 7200000, guid: d1de9ac7d9016204da289affe9677942, type: 3} + m_ClearDispatchIndirectCS: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656, type: 3} + m_ClearLightListsCS: {fileID: 7200000, guid: 743eb3491795b9545955695d591195a1, type: 3} + m_BuildDispatchIndirectCS: {fileID: 7200000, guid: 4eb1b418be7044c40bb5200496c50f14, type: 3} + m_BuildScreenAABBCS: {fileID: 7200000, guid: 728dce960f8a9c44bbc3abb3b851d8f6, type: 3} + m_BuildPerTileLightListCS: {fileID: 7200000, guid: 65af3444cbf4b3747a4dead7ee00cfee, type: 3} + m_BuildPerBigTileLightListCS: {fileID: 7200000, guid: 5ee1f9d6e09abe045b2f5e0b784b9072, type: 3} + m_BuildPerVoxelLightListCS: {fileID: 7200000, guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196, type: 3} + m_LightListClusterClearAtomicIndexCS: {fileID: 7200000, guid: 1e3472a94b14a334a93230bbc700d7b2, type: 3} + m_BuildMaterialFlagsCS: {fileID: 7200000, guid: fb3eda953cd6e634e877fb777be2cd08, type: 3} + m_DeferredCS: {fileID: 7200000, guid: 0b64f79746d2daf4198eaf6eab9af259, type: 3} + m_VolumeVoxelizationCS: {fileID: 7200000, guid: c20b371db720da244b73830ec74a343a, type: 3} + m_VolumetricLightingCS: {fileID: 7200000, guid: b4901a10df2d1e24282725e9fbc77c97, type: 3} + m_VolumetricLightingFilteringCS: {fileID: 7200000, guid: ef9a910d0ec6ebb41ae3f5c7a69daf46, type: 3} + m_DefaultFogVolumeShader: {fileID: -6465566751694194690, guid: 95060fe3e070428418e64e6bed27b111, type: 3} + m_ScreenSpaceMultipleScatteringCS: {fileID: 7200000, guid: 29c79555731a206478f0ea448352340c, type: 3} + m_SubsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1, type: 3} + m_SubsurfaceScatteringDownsampleCS: {fileID: 7200000, guid: 4f8aaf0160a259e499fdfac512ca2692, type: 3} + m_CombineLightingPS: {fileID: 4800000, guid: 2e37131331fbdca449b1a2bc47a639ca, type: 3} + m_BlitCubemapPS: {fileID: 4800000, guid: d05913e251bed7a4992c921c62e1b647, type: 3} + m_OpaqueAtmosphericScatteringPS: {fileID: 4800000, guid: 32f724728cf19904291226f239ec16f0, type: 3} + m_HdriSkyPS: {fileID: 4800000, guid: 9bd32a6ece529fd4f9408b8d7e00c10d, type: 3} + m_IntegrateHdriSkyPS: {fileID: 4800000, guid: 48db2705cf2856d4e893eb30a6892d1b, type: 3} + m_SkyboxCubemapPS: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_GradientSkyPS: {fileID: 4800000, guid: 2b5d4f1b26f03dc4a873b093e0c4adb1, type: 3} + m_AmbientProbeConvolutionCS: {fileID: 7200000, guid: 6d048f7b1bd45e840b4e79ec92639fa8, type: 3} + m_GroundIrradiancePrecomputationCS: {fileID: 7200000, guid: eb6ae6f326207ee4d987a3e5adddf63a, type: 3} + m_InScatteredRadiancePrecomputationCS: {fileID: 7200000, guid: 70c69d514688f8545855680760d77418, type: 3} + m_PhysicallyBasedSkyPS: {fileID: 4800000, guid: a06934a4863e778498be65d8f865b7a4, type: 3} + m_CloudLayerPS: {fileID: 4800000, guid: 001a47fa123e95a4bba13ecb0442d944, type: 3} + m_BakeCloudTextureCS: {fileID: 7200000, guid: 09a7f6850ee9fb4439e5ebd632127da5, type: 3} + m_BakeCloudShadowsCS: {fileID: 7200000, guid: 3e7317e0800c066448ee07a3e47f102b, type: 3} + m_SkyLUTGenerator: {fileID: 7200000, guid: 79224112d91b32241be6b65802863db4, type: 3} + m_LineStagePrepareCS: {fileID: 7200000, guid: 53231d98bbe64477aacc1adc14ba2619, type: 3} + m_LineStageSetupSegmentCS: {fileID: 7200000, guid: 028836c66d494d8d94e1b2ca7d5382ae, type: 3} + m_LineStageShadingSetupCS: {fileID: 7200000, guid: fefde0fac988da24a93bc2d8d6e0a0a1, type: 3} + m_LineStageRasterBinCS: {fileID: 7200000, guid: 17d1e3e43f0e4c878b40b52848a58a77, type: 3} + m_LineStageWorkQueueCS: {fileID: 7200000, guid: dae4ea8aeff24b16be3f0b2948e0acc5, type: 3} + m_LineStageRasterFineCS: {fileID: 7200000, guid: 8691ac13e67d457abb92eca75e88e995, type: 3} + m_LineCompositePS: {fileID: 4800000, guid: 8d9fbe0862434a2298748d335b9abea5, type: 3} + m_PreIntegratedFGD_GGXDisneyDiffusePS: {fileID: 4800000, guid: 123f13d52852ef547b2962de4bd9eaad, type: 3} + m_PreIntegratedFGD_CharlieFabricLambertPS: {fileID: 4800000, guid: 3b3bf235775cf8b4baae7f3306787ab0, type: 3} + m_PreIntegratedFGD_WardPS: {fileID: 4800000, guid: d279c46a545b0af4f9f0c4fa82cd489e, type: 3} + m_PreIntegratedFGD_CookTorrancePS: {fileID: 4800000, guid: a6402c19b020b4a4fb7073aaa2e26aba, type: 3} + m_PreIntegratedFGD_MarschnerPS: {fileID: 4800000, guid: 31f36caf0a5e7f848a1b5328b6ad3eb8, type: 3} + m_PreIntegratedFiberScatteringCS: {fileID: 7200000, guid: 4a087c9d074552c48aeb85184d56312e, type: 3} + m_VolumetricMaterialCS: {fileID: 7200000, guid: 26f18c9cb0bccbf4481f8c84579affb1, type: 3} + m_EyeMaterialCS: {fileID: 7200000, guid: 76f78ba05cea1ed449c1ef613ab90597, type: 3} + m_FilterAreaLightCookiesPS: {fileID: 4800000, guid: c243aac96dda5fa40bed693ed5ba02c4, type: 3} + m_BuildProbabilityTablesCS: {fileID: 7200000, guid: b9f26cf340afe9145a699753531b2a4c, type: 3} + m_ComputeGgxIblSampleDataCS: {fileID: 7200000, guid: 764a24bb47ef5ba4781d9ae82ca07445, type: 3} + m_GGXConvolvePS: {fileID: 4800000, guid: 123ed592ad5c2494b8aed301fd609e7b, type: 3} + m_CharlieConvolvePS: {fileID: 4800000, guid: 5685fd17e71045e4ca9fefca38a7c177, type: 3} + m_GpuPrefixSumCS: {fileID: 7200000, guid: 76fcf27f72d24907b1846939a7a2d83f, type: 3} + m_GpuSortCS: {fileID: 7200000, guid: e485b8d649234276ababbd36fcec8c1a, type: 3} + m_BilateralUpsampleCS: {fileID: 7200000, guid: 68e831c555284d741b985e05369f0e63, type: 3} + m_TemporalFilterCS: {fileID: 7200000, guid: 741979ff70f7bd6489fbcb464280ecff, type: 3} + m_DiffuseDenoiserCS: {fileID: 7200000, guid: b4ed2382141619f40af1f743a84ccaea, type: 3} + m_FurnaceTestCS: {fileID: 7200000, guid: 9c19385e40e70ea41811a942a46b04a3, type: 3} + m_ObjectIDPS: {fileID: -6465566751694194690, guid: 89daf81f8e8f6634da726cbca859ca38, type: 3} + m_ComputeThicknessPS: {fileID: 4800000, guid: 4d2c6daf0d4968748bb5b82d5016fdea, type: 3} + m_CopyChannelCS: {fileID: 7200000, guid: a4d45eda75e8e474dbe24a31f741f3b4, type: 3} + m_ClearBuffer2D: {fileID: 7200000, guid: fa9b66253270e9c47a67ae142f669eb4, type: 3} + m_EncodeBC6HCS: {fileID: 7200000, guid: aa922d239de60304f964e24488559eeb, type: 3} + m_CubeToPanoPS: {fileID: 4800000, guid: 595434cc3b6405246b6cd3086d0b6f7d, type: 3} + m_BlitCubeTextureFacePS: {fileID: 4800000, guid: d850d0a2481878d4bbf17e5126b04163, type: 3} + m_ClearUIntTextureCS: {fileID: 7200000, guid: d067ad4b88af51c498875426894aef76, type: 3} + m_Texture3DAtlasCS: {fileID: 7200000, guid: 81522e314a83afd4a8ed43bd00757051, type: 3} + m_XrMirrorViewPS: {fileID: 4800000, guid: e6255f98cf405eb45ab6f9006cf11e1f, type: 3} + m_XrOcclusionMeshPS: {fileID: 4800000, guid: 46a45b32bb110604fb36216b63bcdb81, type: 3} + m_ContactShadowCS: {fileID: 7200000, guid: 3e6900e06dc185a4380af4dacb4db0a4, type: 3} + m_ScreenSpaceShadowPS: {fileID: 4800000, guid: bfa43a48695613b4ea19c58858ae1a61, type: 3} + m_ShadowClearPS: {fileID: 4800000, guid: e3cab24f27741f44d8af1e94d006267c, type: 3} + m_EvsmBlurCS: {fileID: 7200000, guid: fb36979473602464fa32deacb9630c08, type: 3} + m_DebugHDShadowMapPS: {fileID: 4800000, guid: 93d40cc9a6e13994f86f576a624efa18, type: 3} + m_DebugLocalVolumetricFogAtlasPS: {fileID: 4800000, guid: 8371b763f09c7304889c22aa97ebdfd2, type: 3} + m_MomentShadowsCS: {fileID: 7200000, guid: 4dea53e2ff15ed0448817c2aa4246e53, type: 3} + m_ShadowBlitPS: {fileID: 4800000, guid: ca059f1af4587a24b9a9eed3b66cff0f, type: 3} + m_DecalNormalBufferPS: {fileID: 4800000, guid: fd532bf1795188c4daaa66ea798b8b0a, type: 3} + m_GTAOCS: {fileID: 7200000, guid: 6710b06492bd58c4bb8aec0fdc1fced3, type: 3} + m_GTAOSpatialDenoiseCS: {fileID: 7200000, guid: 2cb33c21587d12b4388d7866ab6c65f6, type: 3} + m_GTAOTemporalDenoiseCS: {fileID: 7200000, guid: 31e0ca4c210f97c468037d11a5b832bb, type: 3} + m_GTAOCopyHistoryCS: {fileID: 7200000, guid: 7f43be57ffd12ff469d4fc175c00c4b4, type: 3} + m_GTAOBlurAndUpsample: {fileID: 7200000, guid: 9eb1abde882538a4ea46fa23e49ab9fa, type: 3} + m_CopyAlphaCS: {fileID: 7200000, guid: c2c7eb6611725264187721ef9df0354b, type: 3} + m_NanKillerCS: {fileID: 7200000, guid: 83982f199acf927499576a99abc9bea9, type: 3} + m_ExposureCS: {fileID: 7200000, guid: 976d7bce54fae534fb9ec67e9c18570c, type: 3} + m_HistogramExposureCS: {fileID: 7200000, guid: 222da48299136f34b8e3fb75ae9f8ac7, type: 3} + m_ApplyExposureCS: {fileID: 7200000, guid: 1a6fea1dc099b984d8f2b27d504dc096, type: 3} + m_UberPostCS: {fileID: 7200000, guid: f1bf52f7c71bffd4f91e6cd90d12a4f7, type: 3} + m_LutBuilder3DCS: {fileID: 7200000, guid: 37f2b1b0ecd6f1c439e4c1b4f2fdb524, type: 3} + m_DepthOfFieldKernelCS: {fileID: 7200000, guid: 7869415cc3e4eaa4d82ac21a752a2780, type: 3} + m_DepthOfFieldCoCCS: {fileID: 7200000, guid: 048b235b54fbfaa4d80ec85ea847d4f8, type: 3} + m_DepthOfFieldCoCReprojectCS: {fileID: 7200000, guid: 4980decaa3878d6448569489f5fc7931, type: 3} + m_DepthOfFieldDilateCS: {fileID: 7200000, guid: 1c93af4338c0c1b42b92464992eebc10, type: 3} + m_DepthOfFieldMipCS: {fileID: 7200000, guid: d3ef53de069ded64e8377cba6eb951fa, type: 3} + m_DepthOfFieldMipSafeCS: {fileID: 7200000, guid: 2d24ee7b2c804d947a5c371c12ed46bd, type: 3} + m_DepthOfFieldPrefilterCS: {fileID: 7200000, guid: f2b89d19910854346b792fe7177ce634, type: 3} + m_DepthOfFieldTileMaxCS: {fileID: 7200000, guid: 84f84585ea8a7a849bea4a581adb93a7, type: 3} + m_DepthOfFieldGatherCS: {fileID: 7200000, guid: 486be52dddc4e054fb10a7b9b78788c2, type: 3} + m_DepthOfFieldCombineCS: {fileID: 7200000, guid: c8049ca85c4c7d047ba28f34d800c663, type: 3} + m_DepthOfFieldPreCombineFarCS: {fileID: 7200000, guid: 3b4a2acd03d1ce2438d93c325d588735, type: 3} + m_DepthOfFieldClearIndirectArgsCS: {fileID: 7200000, guid: 69905045e1d0a65458b205d6ab55502b, type: 3} + m_PaniniProjectionCS: {fileID: 7200000, guid: 0ddbf72c8fbb6e44b983f470c8384ef6, type: 3} + m_DofCircleOfConfusion: {fileID: 7200000, guid: 75332b7b315c80d4babe506820aa0bfd, type: 3} + m_DofGatherCS: {fileID: 7200000, guid: 1e6b16a7970a1494db74b1d3d007d1cc, type: 3} + m_DofCoCMinMaxCS: {fileID: 7200000, guid: c70dd492c3d2fe94589d6ca8d4e37915, type: 3} + m_DofMinMaxDilateCS: {fileID: 7200000, guid: 757a3f81b35177b44b2b178909b49172, type: 3} + m_DofCombineCS: {fileID: 7200000, guid: d9b940a90a2d0884f94990a0dde43a53, type: 3} + m_DofComputeSlowTilesCS: {fileID: 7200000, guid: b89f86a76de81ee42ae16daad78eb382, type: 3} + m_DofComputeApertureShapeCS: {fileID: 7200000, guid: dd5acecb27e20334fa3be332e85172df, type: 3} + m_MotionBlurMotionVecPrepCS: {fileID: 7200000, guid: ed9438fa777911d48933402087203b15, type: 3} + m_MotionBlurGenTileCS: {fileID: 7200000, guid: 336e1fdbb3a1b8647b06208415f87804, type: 3} + m_MotionBlurMergeTileCS: {fileID: 7200000, guid: cd14ddf849edeed43b0e3ccf66023038, type: 3} + m_MotionBlurNeighborhoodTileCS: {fileID: 7200000, guid: 5ea9865df3e53b448856785b88f8e7b9, type: 3} + m_MotionBlurCS: {fileID: 7200000, guid: 2af5c49c7865edb4b823826970ec176a, type: 3} + m_BloomPrefilterCS: {fileID: 7200000, guid: 243b24008041aaa4a91800690f63c684, type: 3} + m_BloomBlurCS: {fileID: 7200000, guid: 133a68380d324de4ea8d3ff8657b02d8, type: 3} + m_BloomUpsampleCS: {fileID: 7200000, guid: 5dbb0ac12cb11f84084b7e5633481bd1, type: 3} + m_DepthValuesPS: {fileID: 4800000, guid: 6e6a4a3dbb788234594aa74f2d6aeb6f, type: 3} + m_ColorResolvePS: {fileID: 4800000, guid: dd7047092f3c82b40b3a07868f9c4de2, type: 3} + m_ResolveMotionVecPS: {fileID: 4800000, guid: ea18ca9826385e943979c46cf98968cc, type: 3} + m_FXAACS: {fileID: 7200000, guid: 1535d29f35ea86b4282b6ca652002e2a, type: 3} + m_FinalPassPS: {fileID: 4800000, guid: 5ac9ef0c50282754b93c7692488e7ee7, type: 3} + m_ClearBlackPS: {fileID: 4800000, guid: 3330c1503ea8c6d4d9408df3f64227eb, type: 3} + m_SMAAPS: {fileID: 4800000, guid: 9655f4aa89a469c49aceaceabf9bc77b, type: 3} + m_TemporalAntialiasingPS: {fileID: 4800000, guid: 3dd9fd928fdb83743b1f27d15df22179, type: 3} + m_SharpeningCS: {fileID: 7200000, guid: 667941138a753f447bad3bf94052f590, type: 3} + m_LensFlareDataDrivenPS: {fileID: 4800000, guid: 85330b3de0cfebc4ba78b2d61b1a2899, type: 3} + m_LensFlareScreenSpacePS: {fileID: 4800000, guid: 97abfc9f0525e1849b417eaae10f0329, type: 3} + m_LensFlareMergeOcclusionCS: {fileID: 7200000, guid: 07492750f384d9a4da9aaf5d2feeed4a, type: 3} + m_DLSSBiasColorMaskPS: {fileID: 4800000, guid: 017a05924c0b0484ca29717ed0c60343, type: 3} + m_CompositeUIAndOETFApplyPS: {fileID: 4800000, guid: 08b7ad21d2b8e9142b730b22d7355821, type: 3} + m_ContrastAdaptiveSharpenCS: {fileID: 7200000, guid: 560896aec2f412c48995be35551a4ac6, type: 3} + m_EdgeAdaptiveSpatialUpsamplingCS: {fileID: 7200000, guid: f054fa9fe2c85bb42b9489e2f9ffb643, type: 3} + m_VTFeedbackDownsample: {fileID: 7200000, guid: 32d963548086c2c439aeb23a93e9a00a, type: 3} + m_AccumulationCS: {fileID: 7200000, guid: ed80add7a217efa468d137d6f7c668f3, type: 3} + m_BlitAndExposeCS: {fileID: 7200000, guid: 4b9a355e064de034dbfafe4583ba766b, type: 3} + m_AlphaInjectionPS: {fileID: 4800000, guid: 4edd96259a5e8b44c90479928f0cd11e, type: 3} + m_ChromaKeyingPS: {fileID: 4800000, guid: 49feb6b111e82ec4eb6d3d08e4b6903e, type: 3} + m_CustomClearPS: {fileID: 4800000, guid: 9cef3686fa32c8840947ed99b561195c, type: 3} + - rid: 3368384739993452879 + type: {class: LookDevVolumeProfileSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} + data: + m_Version: 0 + m_VolumeProfile: {fileID: 11400000, guid: a3837bee00f735443a9ca15a1f874148, type: 2} + - rid: 3368384739993452880 + type: {class: HDRenderingLayersLimitSettings, ns: UnityEditor.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Editor} + data: + m_Version: 0 + - rid: 3368384739993452881 + type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime} + data: + m_Version: 0 + m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, type: 3} + m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, type: 3} + m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, type: 3} + m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, type: 3} + m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, type: 3} + m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, type: 3} + m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, type: 3} + m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, type: 3} + m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, type: 3} + - rid: 3368384739993452882 + type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_EnableCompilationCaching: 1 + m_EnableValidityChecks: 1 + - rid: 3368384739993452883 + type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3} + probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, type: 3} + probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, type: 3} + - rid: 3368384739993452884 + type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_IncludeReferencedInScenes: 1 + m_IncludeAssetsByLabel: 1 + m_LabelToInclude: HDRP:IncludeInBuild + - rid: 3368384739993452885 + type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, type: 3} + subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, type: 3} + voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, type: 3} + traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + - rid: 3368384739993452886 + type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3} + - rid: 3368384739993452887 + type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3} + probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3} + probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, type: 3} + numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, type: 3} + - rid: 3368384739993452888 + type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + m_ProbeVolumeDisableStreamingAssets: 0 + - rid: 3368384739993452889 + type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + - rid: 3368384739993452890 + type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3} + m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3} + m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3} diff --git a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset.meta b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset.meta new file mode 100644 index 00000000..a2994cfe --- /dev/null +++ b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c116788356e21a4888de895681c22f7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt.meta b/Assets/Rendering/URPDefaultResources.meta similarity index 57% rename from Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt.meta rename to Assets/Rendering/URPDefaultResources.meta index 22cc3d89..46cf87ce 100644 --- a/Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt.meta +++ b/Assets/Rendering/URPDefaultResources.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 -guid: 2026145634d264c45b00c976ff8e7d8d -TextScriptImporter: +guid: 8f7a732fa44faff4da0cf4cd0fcec93b +folderAsset: yes +DefaultImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset new file mode 100644 index 00000000..ea2f5985 --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: Universal Render Pipeline Asset + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 0600760c4b35037429aba9ee18c4d6f9, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 2048 + m_AdditionalLightsShadowResolutionTierLow: 256 + m_AdditionalLightsShadowResolutionTierMedium: 512 + m_AdditionalLightsShadowResolutionTierHigh: 1024 + m_ReflectionProbeBlending: 0 + m_ReflectionProbeBoxProjection: 0 + m_ShadowDistance: 50 + m_ShadowCascadeCount: 1 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.2 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 0 + m_ConservativeEnclosingSphere: 1 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 2048 + m_AdditionalLightsCookieFormat: 3 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 0 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_AllowPostProcessAlphaOutput: 0 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 0} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 1 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 1 + m_PrefilterXRKeywords: 0 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 1 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 0 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 0 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 0 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 0 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 0 + m_PrefilterDBufferMRT1: 0 + m_PrefilterDBufferMRT2: 0 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 0 + m_PrefilterNativeRenderPass: 0 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset.meta b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset.meta new file mode 100644 index 00000000..968c3c6f --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a35a2104d5d876648b58b2603fb8c1c8 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset new file mode 100644 index 00000000..f031e215 --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset @@ -0,0 +1,53 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: Universal Render Pipeline Asset_Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + probeVolumeResources: + probeVolumeDebugShader: {fileID: 0} + probeVolumeFragmentationDebugShader: {fileID: 0} + probeVolumeOffsetDebugShader: {fileID: 0} + probeVolumeSamplingDebugShader: {fileID: 0} + probeSamplingDebugMesh: {fileID: 0} + probeSamplingDebugTexture: {fileID: 0} + probeVolumeBlendStatesCS: {fileID: 0} + m_RendererFeatures: [] + m_RendererFeatureMap: + m_UseNativeRenderPass: 0 + xrSystemData: {fileID: 0} + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + m_AssetVersion: 2 + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 0 + m_DepthPrimingMode: 0 + m_CopyDepthMode: 1 + m_DepthAttachmentFormat: 0 + m_DepthTextureFormat: 0 + m_AccurateGbufferNormals: 0 + m_IntermediateTextureMode: 1 diff --git a/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset.meta b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset.meta new file mode 100644 index 00000000..66775445 --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/Universal Render Pipeline Asset_Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0600760c4b35037429aba9ee18c4d6f9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset b/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset new file mode 100644 index 00000000..64f0f206 --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset @@ -0,0 +1,257 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2ec995e51a6e251468d2a3fd8a686257, type: 3} + m_Name: UniversalRenderPipelineGlobalSettings + m_EditorClassIdentifier: + m_ShaderStrippingSetting: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + m_URPShaderStrippingSetting: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 0 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + m_ShaderVariantLogLevel: 0 + m_ExportShaderVariants: 1 + m_StripDebugVariants: 1 + m_StripUnusedPostProcessingVariants: 0 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + supportRuntimeDebugDisplay: 0 + m_EnableRenderGraph: 0 + m_Settings: + m_SettingsList: + m_List: + - rid: 3368384739993452891 + - rid: 3368384739993452892 + - rid: 3368384739993452893 + - rid: 3368384739993452894 + - rid: 3368384739993452895 + - rid: 3368384739993452896 + - rid: 3368384739993452897 + - rid: 3368384739993452898 + - rid: 3368384739993452899 + - rid: 3368384739993452900 + - rid: 3368384739993452901 + - rid: 3368384739993452902 + - rid: 3368384739993452903 + - rid: 3368384739993452904 + - rid: 3368384739993452905 + - rid: 3368384739993452906 + - rid: 3368384739993452907 + - rid: 3368384739993452908 + - rid: 3368384739993452909 + - rid: 3368384739993452910 + - rid: 3368384739993452911 + - rid: 3368384739993452912 + m_RuntimeSettings: + m_List: [] + m_AssetVersion: 8 + m_ObsoleteDefaultVolumeProfile: {fileID: 0} + m_RenderingLayerNames: + - Default + m_ValidRenderingLayers: 0 + lightLayerName0: + lightLayerName1: + lightLayerName2: + lightLayerName3: + lightLayerName4: + lightLayerName5: + lightLayerName6: + lightLayerName7: + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + references: + version: 2 + RefIds: + - rid: 3368384739993452891 + type: {class: UniversalRenderPipelineEditorAssets, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: eda47df5b85f4f249abf7abd73db2cb2, type: 2} + - rid: 3368384739993452892 + type: {class: UniversalRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2} + m_DefaultLineMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2} + m_DefaultTerrainMaterial: {fileID: 2100000, guid: 594ea882c5a793440b60ff72d896021e, type: 2} + m_DefaultDecalMaterial: {fileID: 2100000, guid: 31d0dcc6f2dd4e4408d18036a2c93862, type: 2} + m_DefaultSpriteMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + - rid: 3368384739993452893 + type: {class: UniversalRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 1 + m_BlueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + m_BayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} + m_DebugFontTex: {fileID: 2800000, guid: 26a413214480ef144b2915d6ff4d0beb, type: 3} + - rid: 3368384739993452894 + type: {class: UniversalRenderPipelineDebugShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DebugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + m_HdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + - rid: 3368384739993452895 + type: {class: UniversalRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_FallbackErrorShader: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_BlitHDROverlay: {fileID: 4800000, guid: a89bee29cffa951418fc1e2da94d1959, type: 3} + m_CoreBlitPS: {fileID: 4800000, guid: 93446b5c5339d4f00b85c159e1159b7c, type: 3} + m_CoreBlitColorAndDepthPS: {fileID: 4800000, guid: d104b2fc1ca6445babb8e90b0758136b, type: 3} + m_SamplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, type: 3} + m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, type: 3} + m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, type: 3} + - rid: 3368384739993452896 + type: {class: UniversalRenderPipelineRuntimeXRResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_xrOcclusionMeshPS: {fileID: 4800000, guid: 4431b1f1f743fbf4eb310a967890cbea, type: 3} + m_xrMirrorViewPS: {fileID: 4800000, guid: d5a307c014552314b9f560906d708772, type: 3} + m_xrMotionVector: {fileID: 4800000, guid: f89aac1e4f84468418fe30e611dff395, type: 3} + - rid: 3368384739993452897 + type: {class: URPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_VolumeProfile: {fileID: 11400000, guid: 7641b16591813c8478df3d5724c50315, type: 2} + - rid: 3368384739993452898 + type: {class: UniversalRenderPipelineEditorShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_AutodeskInteractive: {fileID: 4800000, guid: 0e9d5a909a1f7e84882a534d0d11e49f, type: 3} + m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: 5c81372d981403744adbdda4433c9c11, type: 3} + m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 80aa867ac363ac043847b06ad71604cd, type: 3} + m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, type: 3} + m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, type: 3} + m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, type: 3} + m_DefaultSpeedTree7Shader: {fileID: 4800000, guid: 0f4122b9a743b744abe2fb6a0a88868b, type: 3} + m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 9920c1f1781549a46ba081a2a15a16ec, type: 3} + m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: cbd3e1cc4ae141c42a30e33b4d666a61, type: 3} + - rid: 3368384739993452899 + type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_EnableRenderCompatibilityMode: 0 + - rid: 3368384739993452900 + type: {class: UniversalRendererResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_CameraMotionVector: {fileID: 4800000, guid: c56b7e0d4c7cb484e959caeeedae9bbf, type: 3} + m_StencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3} + m_DBufferClear: {fileID: 4800000, guid: f056d8bd2a1c7e44e9729144b4c70395, type: 3} + - rid: 3368384739993452901 + type: {class: URPShaderStrippingSetting, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 0 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + - rid: 3368384739993452902 + type: {class: Renderer2DResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_LightShader: {fileID: 4800000, guid: 3f6c848ca3d7bca4bbe846546ac701a1, type: 3} + m_ProjectedShadowShader: {fileID: 4800000, guid: ce09d4a80b88c5a4eb9768fab4f1ee00, type: 3} + m_SpriteShadowShader: {fileID: 4800000, guid: 44fc62292b65ab04eabcf310e799ccf6, type: 3} + m_SpriteUnshadowShader: {fileID: 4800000, guid: de02b375720b5c445afe83cd483bedf3, type: 3} + m_GeometryShadowShader: {fileID: 4800000, guid: 19349a0f9a7ed4c48a27445bcf92e5e1, type: 3} + m_GeometryUnshadowShader: {fileID: 4800000, guid: 77774d9009bb81447b048c907d4c6273, type: 3} + m_FallOffLookup: {fileID: 2800000, guid: 5688ab254e4c0634f8d6c8e0792331ca, type: 3} + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_DefaultLitMaterial: {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + m_DefaultUnlitMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_DefaultMaskMaterial: {fileID: 2100000, guid: 15d0c3709176029428a0da2f8cecf0b5, type: 2} + - rid: 3368384739993452903 + type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime} + data: + m_Version: 0 + m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, type: 3} + m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, type: 3} + m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, type: 3} + m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, type: 3} + m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, type: 3} + m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, type: 3} + m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, type: 3} + m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, type: 3} + m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, type: 3} + - rid: 3368384739993452904 + type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_EnableCompilationCaching: 1 + m_EnableValidityChecks: 1 + - rid: 3368384739993452905 + type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3} + probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, type: 3} + probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, type: 3} + - rid: 3368384739993452906 + type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_IncludeReferencedInScenes: 0 + m_IncludeAssetsByLabel: 0 + m_LabelToInclude: + - rid: 3368384739993452907 + type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, type: 3} + subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, type: 3} + voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, type: 3} + traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + - rid: 3368384739993452908 + type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3} + - rid: 3368384739993452909 + type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3} + probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3} + probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, type: 3} + numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, type: 3} + - rid: 3368384739993452910 + type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + m_ProbeVolumeDisableStreamingAssets: 0 + - rid: 3368384739993452911 + type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + - rid: 3368384739993452912 + type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3} + m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3} + m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3} diff --git a/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset.meta new file mode 100644 index 00000000..f6c6d3cb --- /dev/null +++ b/Assets/Rendering/URPDefaultResources/UniversalRenderPipelineGlobalSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec72006901959cd4791a67f23cef8143 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt b/Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt deleted file mode 100644 index 12dcde0c..00000000 --- a/Assets/ScriptTemplates/71-My Scripts__Game Objects__Mono Behaviour-NewBehaviourScript.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using UnityEngine; - -#NAMESPACE#public class #SCRIPTNAME# : MonoBehaviour -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt b/Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt deleted file mode 100644 index 6084fbf0..00000000 --- a/Assets/ScriptTemplates/72-My Scripts__Game Objects__Scriptable Object-NewScriptableObject.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using UnityEngine; - -#NAMESPACE#public class #SCRIPTNAME# : ScriptableObject -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt b/Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt deleted file mode 100644 index 54cfb4c6..00000000 --- a/Assets/ScriptTemplates/73-My Scripts__Entities__System-NewSystem.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using Unity.Entities; - -#NAMESPACE#public partial struct #SCRIPTNAME# : ISystem -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt b/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt deleted file mode 100644 index 2b991428..00000000 --- a/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using Unity.Entities; - -#NAMESPACE#public struct #SCRIPTNAME# : IComponentData -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt.meta b/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt.meta deleted file mode 100644 index ae221e4b..00000000 --- a/Assets/ScriptTemplates/74-My Scripts__Entities__Component-NewComponent.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: eb44eb497ac6b0c48ab5907a3c41aa2b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt b/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt deleted file mode 100644 index 8779d504..00000000 --- a/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt +++ /dev/null @@ -1,13 +0,0 @@ -#SIGNATURE#using Unity.Entities; -using UnityEngine; - -#NAMESPACE#public class #SCRIPTNAME# : MonoBehaviour -{ - public class #SCRIPTNAME#Baker : Baker<#SCRIPTNAME#> - { - public override void Bake(#SCRIPTNAME# authoring) - { - - } - } -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt.meta b/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt.meta deleted file mode 100644 index 626b43cc..00000000 --- a/Assets/ScriptTemplates/75-My Scripts__Entities__Authoring-NewAuthoring.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: c16f4ba42ae8652418e554abba5799c5 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt b/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt deleted file mode 100644 index 50cc1655..00000000 --- a/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt +++ /dev/null @@ -1,9 +0,0 @@ -#SIGNATURE#using Unity.Entities; - -#NAMESPACE#public partial class #SCRIPTNAME# : SystemBase -{ - protected override void OnUpdate() - { - - } -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt.meta b/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt.meta deleted file mode 100644 index 9faa2835..00000000 --- a/Assets/ScriptTemplates/76-My Scripts__Entities__Managed System-NewManagedSystem.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6107209ebc8b1334facd61fd39f5092d -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt b/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt deleted file mode 100644 index 8468b2fa..00000000 --- a/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using Unity.Entities; - -#NAMESPACE#public class #SCRIPTNAME# : IComponentData -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt.meta b/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt.meta deleted file mode 100644 index 72e14a60..00000000 --- a/Assets/ScriptTemplates/77-My Scripts__Entities__Managed Component-NewManagedComponent.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 39183c0978530bf4e96d82ef04174faf -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt b/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt deleted file mode 100644 index 07e6bc11..00000000 --- a/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using System; - -#NAMESPACE#public class #SCRIPTNAME# -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt.meta b/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt.meta deleted file mode 100644 index 5e9de06a..00000000 --- a/Assets/ScriptTemplates/78-My Scripts__C# Class-NewClass.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ffe00a2bb10cc7742a9e192ed18013f5 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt b/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt deleted file mode 100644 index b0a28198..00000000 --- a/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using System; - -#NAMESPACE#public struct #SCRIPTNAME# -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt.meta b/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt.meta deleted file mode 100644 index 6d45e140..00000000 --- a/Assets/ScriptTemplates/79-My Scripts__C# Struct-NewStruct.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a400a616546ede94c9ce3a74636fd176 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt b/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt deleted file mode 100644 index b6d9f3b6..00000000 --- a/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt +++ /dev/null @@ -1,4 +0,0 @@ -#SIGNATURE##NAMESPACE#public enum #SCRIPTNAME# -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt.meta b/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt.meta deleted file mode 100644 index e5fa4dad..00000000 --- a/Assets/ScriptTemplates/80-My Scripts__C# Enum-NewEnum.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b3293ab31ca52484784f15be48433073 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt b/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt deleted file mode 100644 index 47c04479..00000000 --- a/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt +++ /dev/null @@ -1,6 +0,0 @@ -#SIGNATURE#using System; - -#NAMESPACE#public interface #SCRIPTNAME# -{ - -} \ No newline at end of file diff --git a/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt.meta b/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt.meta deleted file mode 100644 index 8d2a5f60..00000000 --- a/Assets/ScriptTemplates/81-My Scripts__C# Interface-NewInterface.cs.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: f29d605558446ef4aa37e5ca0241a5cd -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs new file mode 100644 index 00000000..9378ea04 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs @@ -0,0 +1,116 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +#if CONVERT_MATERIALS +using UnityEditor.Rendering; +using UnityEngine.Rendering; +#if CONVERT_URP +using UnityEditor.Rendering.Universal; +using UnityEngine.Rendering.Universal; +#endif +#if CONVERT_HDRP +using UnityEngine.Rendering.HighDefinition; +using UnityEditor.Rendering.HighDefinition; +#endif +#endif + +public static class MaterialPipelineConverter +{ + const string _partialPath = "LoadingSceneExamples/Materials"; + + public static void ConvertMaterials() + { +#if CONVERT_MATERIALS + string fullPath = FindFolderByPartialPath(_partialPath); + if (string.IsNullOrEmpty(fullPath)) + return; + + List upgraders = GetMaterialUpgraders(); + if (upgraders.Count > 0) + { + MaterialUpgrader.UpgradeProjectFolder(GetMaterialUpgraders(), fullPath); + AssetDatabase.Refresh(); + } +#endif + } + +#if CONVERT_MATERIALS + static List GetMaterialUpgraders() + { + RenderPipelineAsset renderPipeline = GraphicsSettings.currentRenderPipeline; + List upgraders = new(); +#if CONVERT_HDRP + if (renderPipeline is HDRenderPipelineAsset) + upgraders.Add(new StandardsToHDLitMaterialUpgrader("Standard", "HDRP/Lit")); +#endif +#if CONVERT_URP + if (renderPipeline is UniversalRenderPipelineAsset) + upgraders.Add(new StandardUpgrader("Standard")); +#endif + return upgraders; + } +#endif + + static string FindFolderByPartialPath(string partialPath) + { + string[] allFolders = AssetDatabase.GetAllAssetPaths(); + foreach (string folder in allFolders) + { + if (folder.EndsWith(partialPath)) + return folder; + } + return null; + } +} + +#if CONVERT_HDRP +// Modified original from `Packages/com.unity.render-pipelines.high-definition/Editor/Material/Lit/StandardsToHDLitMaterialUpgrader.cs` +internal class StandardsToHDLitMaterialUpgrader : MaterialUpgrader +{ + internal StandardsToHDLitMaterialUpgrader(string sourceShaderName, string destShaderName, MaterialFinalizer finalizer = null) + { + RenameShader(sourceShaderName, destShaderName, finalizer); + + RenameTexture("_MainTex", "_BaseColorMap"); + RenameColor("_Color", "_BaseColor"); + RenameFloat("_Glossiness", "_Smoothness"); + RenameTexture("_BumpMap", "_NormalMap"); + RenameFloat("_BumpScale", "_NormalScale"); + RenameTexture("_ParallaxMap", "_HeightMap"); + RenameTexture("_EmissionMap", "_EmissiveColorMap"); + RenameTexture("_DetailAlbedoMap", "_DetailMap"); + RenameFloat("_UVSec", "_UVDetail"); + SetFloat("_LinkDetailsWithBase", 0); + RenameFloat("_DetailNormalMapScale", "_DetailNormalScale"); + RenameFloat("_Cutoff", "_AlphaCutoff"); + RenameKeywordToFloat("_ALPHATEST_ON", "_AlphaCutoffEnable", 1f, 0f); + + SetFloat("_MaterialID", 1f); + } + + public override void Convert(Material srcMaterial, Material dstMaterial) + { + dstMaterial.hideFlags = HideFlags.DontUnloadUnusedAsset; + + base.Convert(srcMaterial, dstMaterial); + + float metallicValue = Mathf.Pow(srcMaterial.GetFloat("_Metallic"), 2.2f); + dstMaterial.SetFloat("_Metallic", metallicValue); + dstMaterial.SetFloat("_AORemapMin", 1f - srcMaterial.GetFloat("_OcclusionStrength")); + dstMaterial.SetFloat("_SmoothnessRemapMax", srcMaterial.GetFloat("_Glossiness")); + dstMaterial.SetFloat("_SurfaceType", 0); + dstMaterial.SetFloat("_BlendMode", 0); + dstMaterial.SetFloat("_AlphaCutoffEnable", 0); + dstMaterial.SetFloat("_EnableBlendModePreserveSpecularLighting", 1); + + Color hdrEmission = srcMaterial.GetColor("_EmissionColor"); + + if (!srcMaterial.IsKeywordEnabled("_EMISSION")) + hdrEmission = Color.black; + + dstMaterial.SetColor("_EmissiveColor", hdrEmission); + + HDShaderUtils.ResetMaterialKeywords(dstMaterial); + } +} +#endif \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs.meta new file mode 100644 index 00000000..ae580309 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 35ef34a8ee68e684588480a73ab173eb \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef index 37956c1c..b1648e03 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef @@ -1,3 +1,36 @@ { - "name": "Sample.LoadingScene.Editor" -} + "name": "Sample.LoadingScene.Editor", + "rootNamespace": "", + "references": [ + "GUID:3eae0364be2026648bf74846acb8a731", + "GUID:c579267770062bf448e75eb160330b7f", + "GUID:15fc0a57446b3144c949da3e2b9737a9", + "GUID:78bd2ddd6e276394a9615c203e574844", + "GUID:457756d89b35d2941b3e7b37b4ece6f1" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.render-pipelines.core", + "expression": "12.1", + "define": "CONVERT_MATERIALS" + }, + { + "name": "com.unity.render-pipelines.high-definition", + "expression": "12.1", + "define": "CONVERT_HDRP" + }, + { + "name": "com.unity.render-pipelines.universal", + "expression": "12.1", + "define": "CONVERT_URP" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs index 0aedb700..0533ccd5 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs @@ -22,6 +22,7 @@ public static class SceneBuildSettingsEditor static SceneBuildSettingsEditor() { EditorApplication.delayCall += CheckScenesInBuildSettings; + EditorApplication.delayCall += MaterialPipelineConverter.ConvertMaterials; } static void CheckScenesInBuildSettings() @@ -40,7 +41,7 @@ static void CheckScenesInBuildSettings() string[] missingScenes = _requiredSceneNames .Where(name => !buildScenes.Contains(name)) .Select(name => allScenePaths.FirstOrDefault(path => Path.GetFileNameWithoutExtension(path) == name)) - .Where(path => !string.IsNullOrEmpty(path)) + .Where(path => !string.IsNullOrEmpty(path) && !path.Contains("Packages/com.mygamedevtools.scene-loader")) .ToArray(); if (missingScenes.Length > 0) diff --git a/Packages/manifest.json b/Packages/manifest.json index f568ea0f..7479a455 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -3,6 +3,9 @@ "com.unity.addressables": "2.2.2", "com.unity.feature.development": "1.0.2", "com.unity.ide.visualstudio": "2.0.22", + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.render-pipelines.high-definition": "17.0.4", + "com.unity.render-pipelines.universal": "17.0.4", "com.unity.timeline": "1.8.7", "com.unity.ugui": "2.0.0", "com.unity.modules.accessibility": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 3a155ecb..05905abf 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -21,6 +21,28 @@ }, "url": "https://packages.unity.com" }, + "com.unity.burst": { + "version": "1.8.19", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.collections": { + "version": "2.5.1", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.8.17", + "com.unity.test-framework": "1.4.5", + "com.unity.nuget.mono-cecil": "1.11.4", + "com.unity.test-framework.performance": "3.0.3" + }, + "url": "https://packages.unity.com" + }, "com.unity.editorcoroutines": { "version": "1.0.0", "depth": 1, @@ -66,6 +88,20 @@ }, "url": "https://packages.unity.com" }, + "com.unity.mathematics": { + "version": "1.3.2", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.nuget.mono-cecil": { + "version": "1.11.4", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, "com.unity.performance.profile-analyzer": { "version": "1.2.3", "depth": 1, @@ -80,6 +116,71 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.render-pipelines.core": { + "version": "17.0.4", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.burst": "1.8.14", + "com.unity.mathematics": "1.3.2", + "com.unity.ugui": "2.0.0", + "com.unity.collections": "2.4.3", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.rendering.light-transport": "1.0.1" + } + }, + "com.unity.render-pipelines.high-definition": { + "version": "17.0.4", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.video": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.shadergraph": "17.0.4", + "com.unity.visualeffectgraph": "17.0.4", + "com.unity.render-pipelines.high-definition-config": "17.0.4" + } + }, + "com.unity.render-pipelines.high-definition-config": { + "version": "17.0.4", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.4" + } + }, + "com.unity.render-pipelines.universal": { + "version": "17.0.4", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.shadergraph": "17.0.4", + "com.unity.render-pipelines.universal-config": "17.0.3" + } + }, + "com.unity.render-pipelines.universal-config": { + "version": "17.0.3", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.3" + } + }, + "com.unity.rendering.light-transport": { + "version": "1.0.1", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.collections": "2.2.0", + "com.unity.mathematics": "1.2.4", + "com.unity.modules.terrain": "1.0.0" + } + }, "com.unity.scriptablebuildpipeline": { "version": "2.1.4", "depth": 1, @@ -87,6 +188,13 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.searcher": { + "version": "4.9.3", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, "com.unity.settings-manager": { "version": "2.0.1", "depth": 2, @@ -94,6 +202,15 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.shadergraph": { + "version": "17.0.4", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.0.4", + "com.unity.searcher": "4.9.3" + } + }, "com.unity.test-framework": { "version": "1.4.6", "depth": 1, @@ -105,6 +222,16 @@ }, "url": "https://packages.unity.com" }, + "com.unity.test-framework.performance": { + "version": "3.0.3", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.31", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, "com.unity.testtools.codecoverage": { "version": "1.2.6", "depth": 1, @@ -136,6 +263,15 @@ "com.unity.modules.imgui": "1.0.0" } }, + "com.unity.visualeffectgraph": { + "version": "17.0.4", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.shadergraph": "17.0.4", + "com.unity.render-pipelines.core": "17.0.4" + } + }, "com.unity.modules.accessibility": { "version": "1.0.0", "depth": 0, diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index 43369e3c..d98609d4 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -3,7 +3,7 @@ --- !u!30 &1 GraphicsSettings: m_ObjectHideFlags: 0 - serializedVersion: 13 + serializedVersion: 16 m_Deferred: m_Mode: 1 m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} @@ -13,9 +13,6 @@ GraphicsSettings: m_ScreenSpaceShadows: m_Mode: 1 m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} - m_LegacyDeferred: - m_Mode: 1 - m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} m_DepthNormals: m_Mode: 1 m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} @@ -28,6 +25,7 @@ GraphicsSettings: m_LensFlare: m_Mode: 1 m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_VideoShadersIncludeMode: 2 m_AlwaysIncludedShaders: - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} @@ -36,8 +34,8 @@ GraphicsSettings: - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] - m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, - type: 0} + m_PreloadShadersBatchTimeLimit: -1 + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} m_CustomRenderPipeline: {fileID: 0} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} @@ -47,6 +45,7 @@ GraphicsSettings: m_LightmapStripping: 0 m_FogStripping: 0 m_InstancingStripping: 0 + m_BrgStripping: 0 m_LightmapKeepPlain: 1 m_LightmapKeepDirCombined: 1 m_LightmapKeepDynamicPlain: 1 @@ -57,7 +56,12 @@ GraphicsSettings: m_FogKeepExp: 1 m_FogKeepExp2: 1 m_AlbedoSwatchInfos: [] - m_LightsUseLinearIntensity: 0 - m_LightsUseColorTemperature: 0 + m_RenderPipelineGlobalSettingsMap: + UnityEngine.Rendering.HighDefinition.HDRenderPipeline: {fileID: 11400000, guid: 6c116788356e21a4888de895681c22f7, type: 2} + UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: ec72006901959cd4791a67f23cef8143, type: 2} + m_LightsUseLinearIntensity: 1 + m_LightsUseColorTemperature: 1 m_LogWhenShaderIsCompiled: 0 - m_AllowEnlightenSupportForUpgradedProject: 0 + m_LightProbeOutsideHullStrategy: 0 + m_CameraRelativeLightCulling: 0 + m_CameraRelativeShadowCulling: 0 diff --git a/ProjectSettings/HDRPProjectSettings.asset b/ProjectSettings/HDRPProjectSettings.asset new file mode 100644 index 00000000..8c122969 --- /dev/null +++ b/ProjectSettings/HDRPProjectSettings.asset @@ -0,0 +1,28 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63a2978a97e4fc04cb9d905947216f3d, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ProjectSettingFolderPath: HDRPDefaultResources + m_LastMaterialVersion: 13 + m_HDShaderGraphLastSeenVersion: 0 + m_PluginMaterialVersions: + m_Keys: [] + m_Values: + m_PluginSubTargetVersions: + m_Keys: [] + m_Values: + m_Version: 2 + m_ObsoleteWizardPopupAlreadyShownOnce: 0 + m_ObsoleteWizardActiveTab: 0 + m_ObsoleteWizardNeedRestartAfterChangingToDX12: 0 + m_ObsoleteWizardNeedToRunFixAllAgainAfterDomainReload: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset index 17c8f538..6a65192d 100644 --- a/ProjectSettings/InputManager.asset +++ b/ProjectSettings/InputManager.asset @@ -293,3 +293,196 @@ InputManager: type: 0 axis: 0 joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: joystick button 8 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: backspace + altNegativeButton: + altPositiveButton: joystick button 9 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Reset + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Next + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page down + altNegativeButton: + altPositiveButton: joystick button 5 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Previous + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page up + altNegativeButton: + altPositiveButton: joystick button 4 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Validate + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Persistent + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: right shift + altNegativeButton: + altPositiveButton: joystick button 2 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Multiplier + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: joystick button 3 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 6 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 5 + joyNum: 0 + m_UsePhysicalKeys: 1 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 0614e568..f76e40c1 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -47,7 +47,7 @@ PlayerSettings: defaultScreenWidthWeb: 960 defaultScreenHeightWeb: 600 m_StereoRenderingPath: 0 - m_ActiveColorSpace: 0 + m_ActiveColorSpace: 1 unsupportedMSAAFallback: 0 m_SpriteBatchMaxVertexCount: 65535 m_SpriteBatchVertexThreshold: 300 diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset index 7b7658d6..c1d21eff 100644 --- a/ProjectSettings/QualitySettings.asset +++ b/ProjectSettings/QualitySettings.asset @@ -4,185 +4,10 @@ QualitySettings: m_ObjectHideFlags: 0 serializedVersion: 5 - m_CurrentQuality: 5 + m_CurrentQuality: 0 m_QualitySettings: - - serializedVersion: 2 - name: Very Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 15 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 1 - textureQuality: 1 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.3 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 4 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.4 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 16 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Medium - pixelLightCount: 1 - shadows: 1 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 1 - lodBias: 0.7 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 64 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: High - pixelLightCount: 2 - shadows: 2 - shadowResolution: 1 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 40 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 256 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Very High - pixelLightCount: 3 - shadows: 2 - shadowResolution: 2 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 70 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 - anisotropicTextures: 2 - antiAliasing: 2 - softParticles: 1 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1.5 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 1024 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Ultra + - serializedVersion: 4 + name: Default pixelLightCount: 4 shadows: 2 shadowResolution: 2 @@ -193,17 +18,24 @@ QualitySettings: shadowCascade2Split: 0.33333334 shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 + skinWeights: 4 + globalTextureMipmapLimit: 0 + textureMipmapLimitSettings: [] anisotropicTextures: 2 - antiAliasing: 2 + antiAliasing: 0 softParticles: 1 softVegetation: 1 realtimeReflectionProbes: 1 billboardsFaceCameraPosition: 1 + useLegacyDetailDistribution: 1 + adaptiveVsync: 0 vSyncCount: 1 - lodBias: 2 + realtimeGICPUUsage: 100 + adaptiveVsyncExtraA: 0 + adaptiveVsyncExtraB: 0 + lodBias: 1 maximumLODLevel: 0 + enableLODCrossFade: 1 streamingMipmapsActive: 0 streamingMipmapsAddAllCameras: 1 streamingMipmapsMemoryBudget: 512 @@ -215,18 +47,29 @@ QualitySettings: asyncUploadBufferSize: 16 asyncUploadPersistentBuffer: 1 resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + terrainQualityOverrides: 0 + terrainPixelError: 1 + terrainDetailDensityScale: 1 + terrainBasemapDistance: 1000 + terrainDetailDistance: 80 + terrainTreeDistance: 5000 + terrainBillboardStart: 50 + terrainFadeLength: 5 + terrainMaxTrees: 50 excludedTargetPlatforms: [] + m_TextureMipmapLimitGroupNames: [] m_PerPlatformDefaultQuality: - Android: 2 - Lumin: 5 - Nintendo 3DS: 5 - Nintendo Switch: 5 - PS4: 5 - PSP2: 2 - Stadia: 5 - Standalone: 5 - WebGL: 3 - Windows Store Apps: 5 - XboxOne: 5 - iPhone: 2 - tvOS: 2 + Android: 0 + Lumin: 0 + Nintendo 3DS: 0 + Nintendo Switch: 0 + PS4: 0 + PSP2: 0 + Stadia: 0 + Standalone: 0 + WebGL: 0 + Windows Store Apps: 0 + XboxOne: 0 + iPhone: 0 + tvOS: 0 diff --git a/ProjectSettings/ShaderGraphSettings.asset b/ProjectSettings/ShaderGraphSettings.asset new file mode 100644 index 00000000..df2f009a --- /dev/null +++ b/ProjectSettings/ShaderGraphSettings.asset @@ -0,0 +1,18 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 53 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3} + m_Name: + m_EditorClassIdentifier: + shaderVariantLimit: 2048 + customInterpolatorErrorThreshold: 32 + customInterpolatorWarningThreshold: 16 + customHeatmapValues: {fileID: 0} diff --git a/ProjectSettings/URPProjectSettings.asset b/ProjectSettings/URPProjectSettings.asset new file mode 100644 index 00000000..08faf033 --- /dev/null +++ b/ProjectSettings/URPProjectSettings.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} + m_Name: + m_EditorClassIdentifier: + m_LastMaterialVersion: 9 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset index 3a95c98b..f99437bb 100644 --- a/ProjectSettings/VFXManager.asset +++ b/ProjectSettings/VFXManager.asset @@ -3,10 +3,17 @@ --- !u!937362698 &1 VFXManager: m_ObjectHideFlags: 0 - m_IndirectShader: {fileID: 0} - m_CopyBufferShader: {fileID: 0} - m_SortShader: {fileID: 0} - m_StripUpdateShader: {fileID: 0} + m_IndirectShader: {fileID: 7200000, guid: 84a17cfa13e40ae4082ef42714f0a81c, type: 3} + m_CopyBufferShader: {fileID: 7200000, guid: 23c51f21a3503f6428b527b01f8a2f4e, type: 3} + m_SortShader: {fileID: 7200000, guid: ea257ca3cfb12a642a5025e612af6b2a, type: 3} + m_StripUpdateShader: {fileID: 7200000, guid: 8fa6c4009fe2a4d4486c62736fc30ad8, type: 3} + m_EmptyShader: {fileID: 4800000, guid: 33a2079f6a2db4c4eb2e44b33f4ddf6b, type: 3} m_RenderPipeSettingsPath: m_FixedTimeStep: 0.016666668 m_MaxDeltaTime: 0.05 + m_MaxScrubTime: 30 + m_MaxCapacity: 100000000 + m_CompiledVersion: 7 + m_RuntimeVersion: 38 + m_RuntimeResources: {fileID: 11400000, guid: bc10b42afe3813544bffd38ae2cd893d, type: 2} + m_BatchEmptyLifetime: 300 From 23437c0c7ebe89bb53055799d2f5566f953e5a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 15:31:31 -0300 Subject: [PATCH 34/53] fix: update material conversion logic --- .../Editor/MaterialPipelineConverter.cs | 60 ++++++++++++------- .../Editor/SceneBuildSettingsEditor.cs | 1 - .../package.json | 2 +- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs index 9378ea04..cd4a0d12 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/MaterialPipelineConverter.cs @@ -1,6 +1,7 @@ using UnityEngine; using UnityEditor; using System.Collections.Generic; +using System.Linq; #if CONVERT_MATERIALS using UnityEditor.Rendering; using UnityEngine.Rendering; @@ -14,53 +15,66 @@ #endif #endif +[InitializeOnLoad] public static class MaterialPipelineConverter { - const string _partialPath = "LoadingSceneExamples/Materials"; + const string _partialPath = "Loading Scene Examples/Materials"; + + static MaterialPipelineConverter() + { + EditorApplication.delayCall += ConvertMaterials; + } public static void ConvertMaterials() { + RenderPipelineAsset renderPipeline = GraphicsSettings.currentRenderPipeline; + if (!renderPipeline) + return; + #if CONVERT_MATERIALS - string fullPath = FindFolderByPartialPath(_partialPath); - if (string.IsNullOrEmpty(fullPath)) + string[] materialPaths = AssetDatabase.FindAssets("t:Material") + .Select(AssetDatabase.GUIDToAssetPath) + .Where(path => path.Contains(_partialPath)) + .ToArray(); + + if (materialPaths.Length == 0) + return; + + Material[] materials = materialPaths + .Select(path => AssetDatabase.LoadAssetAtPath(path)) + .Where(material => material != null && material.shader.name == "Standard") + .ToArray(); + + if (materials.Length == 0) return; - List upgraders = GetMaterialUpgraders(); - if (upgraders.Count > 0) + List upgraders = GetMaterialUpgraders(renderPipeline); + if (upgraders.Count > 0 && EditorUtility.DisplayDialog("Sample Material Upgrader", "The sample materials have to be upgraded to match your render pipeline. Would you like to upgrade them now?", "Upgrade", "Ignore")) { - MaterialUpgrader.UpgradeProjectFolder(GetMaterialUpgraders(), fullPath); + foreach (Material material in materials) + { + MaterialUpgrader.Upgrade(material, upgraders, MaterialUpgrader.UpgradeFlags.None); + } AssetDatabase.Refresh(); } #endif } #if CONVERT_MATERIALS - static List GetMaterialUpgraders() + static List GetMaterialUpgraders(RenderPipelineAsset renderPipeline) { - RenderPipelineAsset renderPipeline = GraphicsSettings.currentRenderPipeline; List upgraders = new(); -#if CONVERT_HDRP - if (renderPipeline is HDRenderPipelineAsset) - upgraders.Add(new StandardsToHDLitMaterialUpgrader("Standard", "HDRP/Lit")); -#endif #if CONVERT_URP if (renderPipeline is UniversalRenderPipelineAsset) upgraders.Add(new StandardUpgrader("Standard")); +#endif +#if CONVERT_HDRP + if (renderPipeline is HDRenderPipelineAsset) + upgraders.Add(new StandardsToHDLitMaterialUpgrader("Standard", "HDRP/Lit")); #endif return upgraders; } #endif - - static string FindFolderByPartialPath(string partialPath) - { - string[] allFolders = AssetDatabase.GetAllAssetPaths(); - foreach (string folder in allFolders) - { - if (folder.EndsWith(partialPath)) - return folder; - } - return null; - } } #if CONVERT_HDRP diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs index 0533ccd5..09d31db7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs @@ -22,7 +22,6 @@ public static class SceneBuildSettingsEditor static SceneBuildSettingsEditor() { EditorApplication.delayCall += CheckScenesInBuildSettings; - EditorApplication.delayCall += MaterialPipelineConverter.ConvertMaterials; } static void CheckScenesInBuildSettings() diff --git a/Packages/com.mygamedevtools.scene-loader/package.json b/Packages/com.mygamedevtools.scene-loader/package.json index c1eba704..8f5a6e98 100644 --- a/Packages/com.mygamedevtools.scene-loader/package.json +++ b/Packages/com.mygamedevtools.scene-loader/package.json @@ -2,7 +2,7 @@ "name": "com.mygamedevtools.scene-loader", "version": "3.1.0", "displayName": "Advanced Scene Manager", - "description": "This package simplifies scene operations: load, unload and transition. In a quick example:\n\n\u2590 // Unity Manager scene transition\n\u2590 yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n\u2590 LoadSceneMode.Additive);\n\u2590 yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n\u2590 LoadSceneMode.Additive);\n\u2590\n\u2590 SceneManager.SetActiveScene(\n\u2590 SceneManager.GetSceneByName(\"my-target-scene\"));\n\u2590\n\u2590 SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n\u2590 SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n\u2590\n\u2590 // Advanced Scene Manager scene transition\n\u2590 AdvancedSceneManager.TransitionAsync(\"my-target-scene\", \"my-loading-scene\");\n\nYou can also take advantage of these features:\n\n\u25aa Unified API for addressable and non-addressable scenes.\n\u25aa Awaitable scene operations.\n\u25aa Modular implementation with interfaces.\n\u25aa Load, unload or transition to multiple scenes.", + "description": "This package simplifies scene operations: load, unload and transition.\nFor example, this is how you perform a scene transition:\n\n\u2503AdvancedSceneManager.TransitionAsync(\"my-target-scene\", \"my-loading-scene\");\n\nInstead of:\n\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503\n\u2503 SceneManager.SetActiveScene(\n\u2503 SceneManager.GetSceneByName(\"my-target-scene\"));\n\u2503\n\u2503 SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n\u2503 SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n\nYou can also take advantage of these features:\n\n\u25aa Unified API for addressable and non-addressable scenes.\n\u25aa Awaitable scene operations.\n\u25aa Modular implementation with interfaces.\n\u25aa Load, unload or transition to multiple scenes.", "unity": "2021.3", "keywords": [], "author": { From 51a2eb994d166f7dae95a953610f0f95f284e635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 15:38:06 -0300 Subject: [PATCH 35/53] embed license with package --- .../LICENSE.txt | 21 +++++++++++++++++++ .../LICENSE.txt.meta | 7 +++++++ 2 files changed, 28 insertions(+) create mode 100644 Packages/com.mygamedevtools.scene-loader/LICENSE.txt create mode 100644 Packages/com.mygamedevtools.scene-loader/LICENSE.txt.meta diff --git a/Packages/com.mygamedevtools.scene-loader/LICENSE.txt b/Packages/com.mygamedevtools.scene-loader/LICENSE.txt new file mode 100644 index 00000000..ad781d94 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 MyGameDevTools + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/LICENSE.txt.meta b/Packages/com.mygamedevtools.scene-loader/LICENSE.txt.meta new file mode 100644 index 00000000..538bae99 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a9c44f367cac8a4892345e7d7405ed7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 6b29c9ca6be80de44c7a273bc2882143d13ebe02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 15:45:54 -0300 Subject: [PATCH 36/53] fix: test ci ammend commits --- .github/workflows/release-template.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 332f08e0..38ad8d76 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -73,14 +73,14 @@ jobs: run: | git config --global user.name 'semantic-release-bot' git config --global user.email 'semantic-release-bot@martynus.net' - git commit -am "update package.json" + git commit --amend -a --no-edit git branch -d upm &> /dev/null || echo upm branch not found git subtree split -P "$PACKAGE_PATH" -b upm git checkout upm if [[ -d "Samples" ]]; then git mv Samples Samples~ rm -f Samples.meta - git commit -am "fix: Samples => Samples~" + git commit --amend -a --no-edit fi git push -f -u origin upm - name: 🏷️ Create UPM Tag From ebee026b14c9cca012432410701a3d8a28daf6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 3 Mar 2025 19:47:00 -0300 Subject: [PATCH 37/53] fix failing test --- .../Runtime/Utilities/SceneDataUtilities.cs | 2 +- .../Tests/Runtime/SceneManagerTests.cs | 160 +++++++++--------- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs index 0d060016..4dc8c59f 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/Utilities/SceneDataUtilities.cs @@ -171,7 +171,7 @@ public static bool TryGetSceneDataByLoadSceneInfo(ILoadSceneInfo loadSceneInfo, } } - Debug.LogWarning($"Unable to get an {nameof(ISceneData)} with the load scene info {loadSceneInfo}."); + Debug.LogWarning($"Unable to get an {nameof(ISceneData)} with the load scene info {loadSceneInfo}. Is the scene loaded?"); sceneData = default; return false; } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs index 27588244..2b6b05c7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManagerTests.cs @@ -35,10 +35,10 @@ public void OneTimeSetup() ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; for (int i = 0; i < sceneManagers.Length; i++) { - var director = sceneManagers[i]; - director.ActiveSceneChanged += ReportSceneActivation; - director.SceneUnloaded += ReportSceneUnloaded; - director.SceneLoaded += ReportSceneLoaded; + var manager = sceneManagers[i]; + manager.ActiveSceneChanged += ReportSceneActivation; + manager.SceneUnloaded += ReportSceneUnloaded; + manager.SceneLoaded += ReportSceneLoaded; } } @@ -48,10 +48,10 @@ public void OneTimeTeardown() ISceneManager[] sceneManagers = SceneTestEnvironment.SceneManagers; for (int i = 0; i < sceneManagers.Length; i++) { - var director = sceneManagers[i]; - director.ActiveSceneChanged -= ReportSceneActivation; - director.SceneUnloaded -= ReportSceneUnloaded; - director.SceneLoaded -= ReportSceneLoaded; + var manager = sceneManagers[i]; + manager.ActiveSceneChanged -= ReportSceneActivation; + manager.SceneUnloaded -= ReportSceneUnloaded; + manager.SceneLoaded -= ReportSceneLoaded; } } @@ -101,7 +101,7 @@ public IEnumerator InitializationScene_Unload() } [UnityTest] - public IEnumerator SetActive_NotThroughDirector([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public IEnumerator SetActive_NotThroughmanager([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { Scene loadedScene = default; SceneManager.sceneLoaded += assignLoadedScene; @@ -109,7 +109,7 @@ public IEnumerator SetActive_NotThroughDirector([ValueSource(typeof(SceneTestEnv yield return SceneManager.LoadSceneAsync(SceneBuilder.SceneNames[1], LoadSceneMode.Additive); yield return new WaitUntil(() => loadedScene.IsValid()); - Assert.Throws(() => director.SetActiveScene(loadedScene)); + Assert.Throws(() => manager.SetActiveScene(loadedScene)); yield return SceneManager.UnloadSceneAsync(loadedScene); @@ -121,20 +121,20 @@ void assignLoadedScene(Scene scene, LoadSceneMode loadSceneMode) } [Test] - public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void GetActiveScene_Empty([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - Assert.False(director.GetActiveScene().IsValid()); + Assert.False(manager.GetActiveScene().IsValid()); } [UnityTest] - public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - var loadTask = director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); + var loadTask = manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]), true)); yield return loadTask.ToWaitTask(); Scene loadedScene = loadTask.Result; - var managerActiveScene = director.GetActiveScene(); + var managerActiveScene = manager.GetActiveScene(); Assert.True(loadedScene.IsValid()); Assert.True(managerActiveScene.IsValid()); @@ -142,51 +142,51 @@ public IEnumerator GetActiveScene_Valid([ValueSource(typeof(SceneTestEnvironment } [Test] - public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void GetLoadedSceneByName_Invalid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - Assert.Throws(() => director.GetLoadedSceneByName("not-a-real-scene")); + Assert.Throws(() => manager.GetLoadedSceneByName("not-a-real-scene")); } [UnityTest] - public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public IEnumerator GetLoadedSceneByName_Valid([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - yield return director.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); + yield return manager.LoadAsync(new SceneParameters(new LoadSceneInfoName(SceneBuilder.SceneNames[1]))).ToWaitTask(); - Assert.True(director.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); + Assert.True(manager.GetLoadedSceneByName(SceneBuilder.SceneNames[1]).IsValid()); } [Test] - public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void EmptyState([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - Assert.False(director.GetLastLoadedScene().IsValid()); - Assert.False(director.GetActiveScene().IsValid()); + Assert.False(manager.GetLastLoadedScene().IsValid()); + Assert.False(manager.GetActiveScene().IsValid()); } [Test] - public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void GetLoadedSceneAt_IndexError([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { - Assert.Throws(() => director.GetLoadedSceneAt(-1)); - Assert.Throws(() => director.GetLoadedSceneAt(1)); + Assert.Throws(() => manager.GetLoadedSceneAt(-1)); + Assert.Throws(() => manager.GetLoadedSceneAt(1)); } [UnityTest] - public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); - return Load_Template(director, () => director.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); + return Load_Template(manager, () => manager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Progress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); Assert.AreEqual(0, progress.Value); - yield return director.LoadAsync(sceneParameters, progress).ToWaitTask(); + yield return manager.LoadAsync(sceneParameters, progress).ToWaitTask(); Assert.AreEqual(1, progress.Value); } [UnityTest] - public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { ILoadSceneInfo[] sceneInfos = sceneParameters.GetLoadSceneInfos(); int length = sceneInfos.Length; @@ -196,57 +196,57 @@ public IEnumerator Load_Stress([ValueSource(typeof(SceneTestEnvironment), nameof for (int i = 0; i < length; i++) { - var loadTask = director.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); + var loadTask = manager.LoadAsync(new SceneParameters(sceneInfos[i], setActive)); yield return loadTask.ToWaitTask(); loadedScenes[i] = loadTask.Result; } - Assert.AreEqual(length, director.LoadedSceneCount); - Assert.AreEqual(loadedScenes[^1], director.GetLastLoadedScene()); + Assert.AreEqual(length, manager.LoadedSceneCount); + Assert.AreEqual(loadedScenes[^1], manager.GetLastLoadedScene()); for (int i = 0; i < length; i++) - Assert.AreEqual(loadedScenes[i], director.GetLoadedSceneAt(i)); + Assert.AreEqual(loadedScenes[i], manager.GetLoadedSceneAt(i)); - Assert.That(setActive ? loadedScenes[^1] == director.GetActiveScene() : loadedScenes[^1] != director.GetActiveScene()); + Assert.That(setActive ? loadedScenes[^1] == manager.GetActiveScene() : loadedScenes[^1] != manager.GetActiveScene()); Assert.AreEqual(length, _scenesLoaded); Assert.AreEqual(0, _scenesUnloaded); Assert.AreEqual(setActive ? length : 0, _scenesActivated); } [Test] - public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void Load_NotInBuild([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { var sceneName = "not-a-real-scene"; LogAssert.Expect(LogType.Error, new Regex("'not-a-real-scene' couldn't be loaded")); - var wait = director.LoadAsync(sceneName).ToWaitTask(); + var wait = manager.LoadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } [UnityTest] - public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) + public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - yield return Unload_Template(director, () => director.LoadAsync(sceneParameters), () => director.UnloadAsync(sceneParameters), sceneParameters.Length); + yield return Unload_Template(manager, () => manager.LoadAsync(sceneParameters), () => manager.UnloadAsync(sceneParameters), sceneParameters.Length); } [Test] - public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director) + public void Unload_NotLoaded([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager) { var sceneName = "not-a-real-scene"; - if (director is not SceneManager) - LogAssert.Expect(LogType.Warning, new Regex("Some of the scenes could not be found loaded")); - var wait = director.UnloadAsync(sceneName).ToWaitTask(); + if (manager is not SceneManager) + LogAssert.Expect(LogType.Warning, new Regex("Unable to get an ISceneData with the load scene info")); + var wait = manager.UnloadAsync(sceneName).ToWaitTask(); Assert.Throws(() => wait.MoveNext()); } [UnityTest] - public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. + public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { - yield return Transition_Template(director, () => director.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + yield return Transition_Template(manager, () => manager.TransitionAsync(sceneParameters, loadingScene), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] - public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) { int expectedLoadedScenes = loadingScene == null ? 1 : 2; // If there's no loading scene, the scene manager will create a temporary scene @@ -258,7 +258,7 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron // The temporary scene unload does not go through the ISceneManager SceneManager.sceneUnloaded += sceneUnloaded; - var task = director.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); + var task = manager.TransitionAsync(new SceneParameters(targetScene, true), loadingScene); yield return task.ToWaitTask(); @@ -266,11 +266,11 @@ public IEnumerator Transition_NoSourceScene([ValueSource(typeof(SceneTestEnviron SceneManager.sceneUnloaded -= sceneUnloaded; - Assert.AreEqual(loadedScene, director.GetActiveScene()); + Assert.AreEqual(loadedScene, manager.GetActiveScene()); Assert.AreEqual(expectedLoadedScenes, _scenesLoaded); Assert.AreEqual(expectedUnloadedScenes, unloadedScenesCount); - yield return new WaitUntil(() => director.TotalSceneCount == 1); + yield return new WaitUntil(() => manager.TotalSceneCount == 1); void sceneUnloaded(Scene scene) { @@ -279,71 +279,71 @@ void sceneUnloaded(Scene scene) } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByScene([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo sceneInfo) { - var task = director.LoadAsync(new SceneParameters(sceneInfo)); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); Scene scene = task.Result; - task = director.UnloadAsync(scene); + task = manager.UnloadAsync(scene); yield return task.ToWaitTask(); - Assert.Zero(director.LoadedSceneCount); + Assert.Zero(manager.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByName([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = director.LoadAsync(new SceneParameters(sceneInfo)); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); - task = director.UnloadAsync(SceneBuilder.SceneNames[1]); + task = manager.UnloadAsync(SceneBuilder.SceneNames[1]); yield return task.ToWaitTask(); - Assert.Zero(director.LoadedSceneCount); + Assert.Zero(manager.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByPath([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = director.LoadAsync(new SceneParameters(sceneInfo)); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); - task = director.UnloadAsync(SceneBuilder.ScenePaths[1]); + task = manager.UnloadAsync(SceneBuilder.ScenePaths[1]); yield return task.ToWaitTask(); - Assert.Zero(director.LoadedSceneCount); + Assert.Zero(manager.LoadedSceneCount); } [UnityTest] - public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager director, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) + public IEnumerator Load_ByInfo_UnloadByIndex([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneManagers))] ISceneManager manager, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList_NoAddressable))] ILoadSceneInfo sceneInfo) { - var task = director.LoadAsync(new SceneParameters(sceneInfo)); + var task = manager.LoadAsync(new SceneParameters(sceneInfo)); yield return task.ToWaitTask(); #if UNITY_EDITOR - task = director.UnloadAsync(1); + task = manager.UnloadAsync(1); #else - task = director.UnloadAsync(2); + task = manager.UnloadAsync(2); #endif yield return task.ToWaitTask(); - Assert.Zero(director.LoadedSceneCount); + Assert.Zero(manager.LoadedSceneCount); } - public IEnumerator Load_Template(ISceneManager director, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) + public IEnumerator Load_Template(ISceneManager manager, Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); - director.SceneLoaded += reportSceneLoaded; + manager.SceneLoaded += reportSceneLoaded; var task = loadTask(); @@ -351,15 +351,15 @@ public IEnumerator Load_Template(ISceneManager director, Func> yield return task.ToWaitTask(); - director.SceneLoaded -= reportSceneLoaded; + manager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; Assert.AreEqual(1, progress.Value); Assert.AreEqual(sceneCount, loadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(sceneCount, director.LoadedSceneCount); + Assert.AreEqual(sceneCount, manager.LoadedSceneCount); if (setIndexActive >= 0) - Assert.AreEqual(director.GetActiveScene(), loadedScenes[setIndexActive]); + Assert.AreEqual(manager.GetActiveScene(), loadedScenes[setIndexActive]); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(0, _scenesUnloaded); Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); @@ -367,38 +367,38 @@ public IEnumerator Load_Template(ISceneManager director, Func> void reportSceneLoaded(Scene loadedScene) => reportedScenes.Add(loadedScene); } - public IEnumerator Transition_Template(ISceneManager director, Func> transitionTask, int sceneCount, int setIndexActive) + public IEnumerator Transition_Template(ISceneManager manager, Func> transitionTask, int sceneCount, int setIndexActive) { - yield return LoadFirstScene(director); + yield return LoadFirstScene(manager); var task = transitionTask(); yield return task.ToWaitTask(); Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); - Assert.AreEqual(loadedScenes[setIndexActive], director.GetActiveScene()); + Assert.AreEqual(loadedScenes[setIndexActive], manager.GetActiveScene()); - yield return new WaitUntil(() => director.TotalSceneCount == sceneCount); + yield return new WaitUntil(() => manager.TotalSceneCount == sceneCount); } - public IEnumerator Unload_Template(ISceneManager director, Func> loadTask, Func> unloadTask, int sceneCount) + public IEnumerator Unload_Template(ISceneManager manager, Func> loadTask, Func> unloadTask, int sceneCount) { var load = loadTask(); yield return load.ToWaitTask(); var loadedSceneHandles = load.Result.GetScenes().Select(s => s.handle).ToArray(); var reportedScenes = new List(sceneCount); - director.SceneUnloaded += reportSceneUnloaded; + manager.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); yield return unload.ToWaitTask(); - director.SceneUnloaded -= reportSceneUnloaded; + manager.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; Assert.AreEqual(sceneCount, unloadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(0, director.LoadedSceneCount); + Assert.AreEqual(0, manager.LoadedSceneCount); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(sceneCount, _scenesUnloaded); From fe08804635a91bea0e76113be755602e02dd23b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 5 Mar 2025 11:45:43 -0300 Subject: [PATCH 38/53] fix: rename package due to collisions with existing asset --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yml | 2 +- .github/ISSUE_TEMPLATE/question.yml | 4 +- CODE_OF_CONDUCT.md | 2 +- CONTRIBUTING.md | 6 +- ...ancedSceneManager.cs => MySceneManager.cs} | 4 +- ...Manager.cs.meta => MySceneManager.cs.meta} | 0 .../Editor/SceneBuildSettingsEditor.cs | 6 +- .../Scripts/Runtime/SceneTransitionTrigger.cs | 4 +- ...s => StaticSceneManager_ExtensionTests.cs} | 54 +++++++------- ...StaticSceneManager_ExtensionTests.cs.meta} | 0 ...r_Tests.cs => StaticSceneManager_Tests.cs} | 68 +++++++++--------- ....meta => StaticSceneManager_Tests.cs.meta} | 0 .../package.json | 4 +- README.md | 51 ++++++++----- docs/img/banner.jpg | Bin 86244 -> 80754 bytes 16 files changed, 110 insertions(+), 97 deletions(-) rename Packages/com.mygamedevtools.scene-loader/Runtime/{AdvancedSceneManager.cs => MySceneManager.cs} (99%) rename Packages/com.mygamedevtools.scene-loader/Runtime/{AdvancedSceneManager.cs.meta => MySceneManager.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{AdvancedSceneManager_ExtensionTests.cs => StaticSceneManager_ExtensionTests.cs} (51%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{AdvancedSceneManager_ExtensionTests.cs.meta => StaticSceneManager_ExtensionTests.cs.meta} (100%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{AdvancedSceneManager_Tests.cs => StaticSceneManager_Tests.cs} (64%) rename Packages/com.mygamedevtools.scene-loader/Tests/Runtime/{AdvancedSceneManager_Tests.cs.meta => StaticSceneManager_Tests.cs.meta} (100%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 09bfa0f2..3130955b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -43,7 +43,7 @@ body: - type: input id: version attributes: - label: Advanced Scene Manager Version + label: Package Version description: The version of the package you are using placeholder: "e.g., 3.1.0" validations: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 96c32090..2bd94c51 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -6,7 +6,7 @@ body: attributes: value: | ## Feature Request - Have a feature idea? Let us know what you'd like to see in the Advanced Scene Manager! + Have a feature idea? Let us know what you'd like to see in My Scene Manager! - type: input id: summary attributes: diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index edfba632..52d0e2f8 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -6,7 +6,7 @@ body: attributes: value: | ## Question or Support Request - Need help or have a question about using the Advanced Scene Manager? Let us know! + Need help or have a question about using My Scene Manager? Let us know! - type: textarea id: question attributes: @@ -17,7 +17,7 @@ body: - type: input id: version attributes: - label: Advanced Scene Manager Version + label: Package Version description: The version of the package you are using placeholder: "e.g., 3.1.0" validations: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c41729d8..2506d41b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,7 +2,7 @@ ## Our Pledge -We, as contributors and maintainers of Advanced Scene Manager, pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. +We, as contributors and maintainers of My Scene Manager, pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We are committed to fostering an open, welcoming, and inclusive community. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index efd1690e..2c4da0ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ # Contribution Guide -Thank you for considering contributing to Advanced Scene Manager! Whether you're fixing a bug, adding a feature, or improving the documentation, your contributions are greatly appreciated and help make the tool better for everyone. +Thank you for considering contributing to My Scene Manager! Whether you're fixing a bug, adding a feature, or improving the documentation, your contributions are greatly appreciated and help make the tool better for everyone. ## How to Contribute -There are several ways you can contribute to Advanced Scene Manager: +There are several ways you can contribute to My Scene Manager: ### 1. Reporting Issues @@ -28,7 +28,7 @@ If you'd like to submit code to fix an issue or add a feature, please follow the Clone your forked repository to your local machine: ```bash -git clone https://github.com/your-username/advanced-scene-manager.git +git clone https://github.com/mygamedevtools/scene-loader.git ``` #### Create a New Branch diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs b/Packages/com.mygamedevtools.scene-loader/Runtime/MySceneManager.cs similarity index 99% rename from Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs rename to Packages/com.mygamedevtools.scene-loader/Runtime/MySceneManager.cs index 73b93aee..7cfbf93a 100644 --- a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs +++ b/Packages/com.mygamedevtools.scene-loader/Runtime/MySceneManager.cs @@ -10,14 +10,14 @@ namespace MyGameDevTools.SceneLoading { - public static class AdvancedSceneManager + public static class MySceneManager { internal static ISceneManager Instance { get { if (_instance == null) - throw new NullReferenceException("[AdvancedSceneManager] The static Scene Manager instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); + throw new NullReferenceException($"[{nameof(MySceneManager)}] The static Scene Manager instance is not available before the first scene is fully loaded. Try moving the call to `Start()`."); return _instance; } } diff --git a/Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta b/Packages/com.mygamedevtools.scene-loader/Runtime/MySceneManager.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Runtime/AdvancedSceneManager.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Runtime/MySceneManager.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs index 09d31db7..37667ab7 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs @@ -47,7 +47,7 @@ static void CheckScenesInBuildSettings() { bool addScenes = EditorUtility.DisplayDialogComplex( _sampleName, - "To run the " + _sampleName + ", you need to add the sample scenes to the Build Settings. Would you like to add them now?\nYou can remove them later in the menu: \"Tools/Advanced Scene Manager/Remove '" + _sampleName + "' from Build Settings\".", + "To run the " + _sampleName + ", you need to add the sample scenes to the Build Settings. Would you like to add them now?\nYou can remove them later in the menu: \"Tools/My Scene Manager/Remove '" + _sampleName + "' from Build Settings\".", "Add Scenes", "Ignore", "Don't Show Again" @@ -83,7 +83,7 @@ static void AddScenesToBuildSettings(string[] scenes) EditorBuildSettings.scenes = currentScenes.ToArray(); } - [MenuItem("Tools/Advanced Scene Manager/Remove '" + _sampleName + "' from Build Settings")] + [MenuItem("Tools/My Scene Manager/Remove '" + _sampleName + "' from Build Settings")] static void RemoveSampleScenesFromBuildSettings() { List currentScenes = EditorBuildSettings.scenes.ToList(); @@ -92,7 +92,7 @@ static void RemoveSampleScenesFromBuildSettings() EditorBuildSettings.scenes = currentScenes.ToArray(); } - [MenuItem("Tools/Advanced Scene Manager/Reset '" + _sampleName + "' Add Scenes Prompt")] + [MenuItem("Tools/My Scene Manager/Reset '" + _sampleName + "' Add Scenes Prompt")] private static void ResetDontShowAgain() { EditorPrefs.DeleteKey(_dontShowAgainKey); diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs index efb6ce7c..fedae7bc 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/SceneTransitionTrigger.cs @@ -16,7 +16,7 @@ public class SceneTransitionTrigger : MonoBehaviour ///

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 DNj!reVs#6)Sg!DGq4 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 NAQiUb>0^4{`X3C5b7cSk literal 0 HcmV?d00001 diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr.meta new file mode 100644 index 00000000..5eb6762a --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scenes/SceneB/ReflectionProbe-1.exr.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 3ca868183594b1d49a127bff22d45823 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts.meta new file mode 100644 index 00000000..45e4e89e --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6adecbebb7cfd5a4685b3a0b5bb3ad62 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor.meta new file mode 100644 index 00000000..73def965 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 322e597b443729b45815e23122d1fdd6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef new file mode 100644 index 00000000..37956c1c --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef @@ -0,0 +1,3 @@ +{ + "name": "Sample.LoadingScene.Editor" +} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef.meta new file mode 100644 index 00000000..3afdbd10 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7479c7f3f090a70479be9cf477703a60 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs new file mode 100644 index 00000000..0aedb700 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; + +[InitializeOnLoad] +public static class SceneBuildSettingsEditor +{ + const string _sampleName = "Loading Scene Examples"; + const string _sampleSlug = "asm_lse"; + const string _dontShowAgainKey = _sampleSlug + "::dontShowAddScenesPrompt"; + + static readonly string[] _requiredSceneNames = + { + "SceneA", + "SceneB", + "Loading_Fade", + "Loading_Animated", + "Loading_Custom" + }; + + static SceneBuildSettingsEditor() + { + EditorApplication.delayCall += CheckScenesInBuildSettings; + } + + static void CheckScenesInBuildSettings() + { + if (EditorPrefs.GetBool(_dontShowAgainKey, false)) + return; + + string[] buildScenes = EditorBuildSettings.scenes + .Select(scene => Path.GetFileNameWithoutExtension(scene.path)) + .ToArray(); + + string[] allScenePaths = AssetDatabase.FindAssets("t:Scene") + .Select(AssetDatabase.GUIDToAssetPath) + .ToArray(); + + string[] missingScenes = _requiredSceneNames + .Where(name => !buildScenes.Contains(name)) + .Select(name => allScenePaths.FirstOrDefault(path => Path.GetFileNameWithoutExtension(path) == name)) + .Where(path => !string.IsNullOrEmpty(path)) + .ToArray(); + + if (missingScenes.Length > 0) + { + bool addScenes = EditorUtility.DisplayDialogComplex( + _sampleName, + "To run the " + _sampleName + ", you need to add the sample scenes to the Build Settings. Would you like to add them now?\nYou can remove them later in the menu: \"Tools/Advanced Scene Manager/Remove '" + _sampleName + "' from Build Settings\".", + "Add Scenes", + "Ignore", + "Don't Show Again" + ) switch + { + 0 => true, + 2 => SetDontShowAgain(), + _ => false + }; + + if (addScenes) + { + AddScenesToBuildSettings(missingScenes); + } + } + } + + static bool SetDontShowAgain() + { + EditorPrefs.SetBool(_dontShowAgainKey, true); + return false; + } + + static void AddScenesToBuildSettings(string[] scenes) + { + List currentScenes = EditorBuildSettings.scenes.ToList(); + + foreach (string scene in scenes) + { + currentScenes.Add(new EditorBuildSettingsScene(scene, true)); + } + + EditorBuildSettings.scenes = currentScenes.ToArray(); + } + + [MenuItem("Tools/Advanced Scene Manager/Remove '" + _sampleName + "' from Build Settings")] + static void RemoveSampleScenesFromBuildSettings() + { + List currentScenes = EditorBuildSettings.scenes.ToList(); + currentScenes.RemoveAll(scene => _requiredSceneNames.Contains(Path.GetFileNameWithoutExtension(scene.path))); + + EditorBuildSettings.scenes = currentScenes.ToArray(); + } + + [MenuItem("Tools/Advanced Scene Manager/Reset '" + _sampleName + "' Add Scenes Prompt")] + private static void ResetDontShowAgain() + { + EditorPrefs.DeleteKey(_dontShowAgainKey); + } +} diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs.meta new file mode 100644 index 00000000..dd718460 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/SceneBuildSettingsEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a7fd449815eefcf45aa518254adacc34 \ No newline at end of file diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime.meta b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime.meta new file mode 100644 index 00000000..e76772b2 --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e8a9992f3d0281247a4c8fabbd6e7a8b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs new file mode 100644 index 00000000..db842c8e --- /dev/null +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Runtime/AnimatedTrigger.cs @@ -0,0 +1,75 @@ +using MyGameDevTools.SceneLoading; +using UnityEngine; + +public class AnimatedTrigger : MonoBehaviour +{ + ///

public void TransitionWithLoading(string loadingScene) { - AdvancedSceneManager.TransitionAsync(_targetScene, loadingScene); + MySceneManager.TransitionAsync(_targetScene, loadingScene); } /// @@ -24,6 +24,6 @@ public void TransitionWithLoading(string loadingScene) /// public void Transition() { - AdvancedSceneManager.TransitionAsync(_targetScene); + MySceneManager.TransitionAsync(_targetScene); } } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs similarity index 51% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs index 6c1c63c4..3bf29a14 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs @@ -7,7 +7,7 @@ namespace MyGameDevTools.SceneLoading.Tests { - public partial class AdvancedSceneManager_Tests + public partial class StaticSceneManager_Tests { int[] _buildIndexes = new[] { 1, 2, 3 }; @@ -29,28 +29,28 @@ public void AssetReferenceSetup() public IEnumerator Load_Extension_ByIndex() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAsync(1, true, progress), progress, 1, 0); + yield return Load_Template(() => MySceneManager.LoadAsync(1, true, progress), progress, 1, 0); } [UnityTest] public IEnumerator Load_Extension_ByIndex_Multiple() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); + yield return Load_Template(() => MySceneManager.LoadAsync(_buildIndexes, 1, progress), progress, _buildIndexes.Length, 1); } [UnityTest] public IEnumerator Load_Extension_ByName() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + yield return Load_Template(() => MySceneManager.LoadAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); } [UnityTest] public IEnumerator Load_Extension_ByName_Multiple() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + yield return Load_Template(() => MySceneManager.LoadAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); } #if ENABLE_ADDRESSABLES @@ -58,103 +58,103 @@ public IEnumerator Load_Extension_ByName_Multiple() public IEnumerator Load_Extension_Addressable_ByAddress() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); + yield return Load_Template(() => MySceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true, progress), progress, 1, 0); } [UnityTest] public IEnumerator Load_Extension_Addressable_ByAddress_Multiple() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); + yield return Load_Template(() => MySceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 1, progress), progress, SceneBuilder.SceneNames.Length, 1); } [UnityTest] public IEnumerator Load_Extension_Addressable_ByAssetReference() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); + yield return Load_Template(() => MySceneManager.LoadAddressableAsync(_assetReferences[1], true, progress), progress, 1, 0); } [UnityTest] public IEnumerator Load_Extension_Addressable_ByAssetReference_Multiple() { var progress = new SimpleProgress(); - yield return Load_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); + yield return Load_Template(() => MySceneManager.LoadAddressableAsync(_assetReferences, 1, progress), progress, _assetReferences.Length, 1); } #endif [UnityTest] public IEnumerator Transition_Extension_ByIndex() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(1, 1), 1, 0); + yield return Transition_Template(() => MySceneManager.TransitionAsync(1, 1), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByIndex_Multiple() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); + yield return Transition_Template(() => MySceneManager.TransitionAsync(_buildIndexes, 1), _buildIndexes.Length, 0); } [UnityTest] public IEnumerator Transition_Extension_ByName() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + yield return Transition_Template(() => MySceneManager.TransitionAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_ByName_Multiple() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(() => MySceneManager.TransitionAsync(SceneBuilder.SceneNames, SceneBuilder.ScenePaths[0]), SceneBuilder.SceneNames.Length, 0); } #if ENABLE_ADDRESSABLES [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAddress() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); + yield return Transition_Template(() => MySceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames[1], SceneBuilder.SceneNames[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAddress_Multiple() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(() => MySceneManager.TransitionAddressableAsync(SceneBuilder.SceneNames, SceneBuilder.SceneNames[0]), SceneBuilder.SceneNames.Length, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAssetReference() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); + yield return Transition_Template(() => MySceneManager.TransitionAddressableAsync(_assetReferences[1], _assetReferences[0]), 1, 0); } [UnityTest] public IEnumerator Transition_Extension_Addressable_ByAssetReference_Multiple() { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); + yield return Transition_Template(() => MySceneManager.TransitionAddressableAsync(_assetReferences, _assetReferences[0]), SceneBuilder.SceneNames.Length, 0); } #endif [UnityTest] public IEnumerator Unload_Extension_ByIndex() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(1, true), () => AdvancedSceneManager.UnloadAsync(1), 1); + yield return Unload_Template(() => MySceneManager.LoadAsync(1, true), () => MySceneManager.UnloadAsync(1), 1); } [UnityTest] public IEnumerator Unload_Extension_ByIndex_Multiple() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(_buildIndexes, 0), () => AdvancedSceneManager.UnloadAsync(_buildIndexes), _buildIndexes.Length); + yield return Unload_Template(() => MySceneManager.LoadAsync(_buildIndexes, 0), () => MySceneManager.UnloadAsync(_buildIndexes), _buildIndexes.Length); } [UnityTest] public IEnumerator Unload_Extension_ByName() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true), () => AdvancedSceneManager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); + yield return Unload_Template(() => MySceneManager.LoadAsync(SceneBuilder.SceneNames[1], true), () => MySceneManager.UnloadAsync(SceneBuilder.SceneNames[1]), 1); } [UnityTest] public IEnumerator Unload_Extension_ByName_Multiple() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 0), () => AdvancedSceneManager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + yield return Unload_Template(() => MySceneManager.LoadAsync(SceneBuilder.SceneNames, 0), () => MySceneManager.UnloadAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); } [UnityTest] @@ -163,12 +163,12 @@ public IEnumerator Unload_Extension_ByScene_Multiple() Task loadTask = Task.FromResult(default); yield return Unload_Template(() => { - loadTask = AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames, 0); + loadTask = MySceneManager.LoadAsync(SceneBuilder.SceneNames, 0); return loadTask; }, () => { SceneResult result = loadTask.GetAwaiter().GetResult(); - return AdvancedSceneManager.UnloadAsync(result.GetScenes()); + return MySceneManager.UnloadAsync(result.GetScenes()); }, SceneBuilder.SceneNames.Length); } @@ -176,25 +176,25 @@ public IEnumerator Unload_Extension_ByScene_Multiple() [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAddress() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => AdvancedSceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); + yield return Unload_Template(() => MySceneManager.LoadAddressableAsync(SceneBuilder.SceneNames[1], true), () => MySceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames[1]), 1); } [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAddress_Multiple() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => AdvancedSceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); + yield return Unload_Template(() => MySceneManager.LoadAddressableAsync(SceneBuilder.SceneNames, 0), () => MySceneManager.UnloadAddressableAsync(SceneBuilder.SceneNames), SceneBuilder.SceneNames.Length); } [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAssetReference() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences[1], true), () => AdvancedSceneManager.UnloadAddressableAsync(_assetReferences[1]), 1); + yield return Unload_Template(() => MySceneManager.LoadAddressableAsync(_assetReferences[1], true), () => MySceneManager.UnloadAddressableAsync(_assetReferences[1]), 1); } [UnityTest] public IEnumerator Unload_Extension_Addressable_ByAssetReference_Multiple() { - yield return Unload_Template(() => AdvancedSceneManager.LoadAddressableAsync(_assetReferences, 0), () => AdvancedSceneManager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); + yield return Unload_Template(() => MySceneManager.LoadAddressableAsync(_assetReferences, 0), () => MySceneManager.UnloadAddressableAsync(_assetReferences), _assetReferences.Length); } #endif } diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_ExtensionTests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_Tests.cs similarity index 64% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_Tests.cs index 2d86bc34..516b82bd 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_Tests.cs @@ -11,7 +11,7 @@ namespace MyGameDevTools.SceneLoading.Tests { [PrebuildSetup(typeof(SceneTestEnvironment)), PostBuildCleanup(typeof(SceneTestEnvironment))] - public partial class AdvancedSceneManager_Tests + public partial class StaticSceneManager_Tests { int _scenesActivated; int _scenesUnloaded; @@ -22,23 +22,23 @@ public void OneTimeSetup() { SceneTestEnvironment.ValidateSceneEnvironment(); - AdvancedSceneManager.ActiveSceneChanged += ReportSceneActivation; - AdvancedSceneManager.SceneUnloaded += ReportSceneUnloaded; - AdvancedSceneManager.SceneLoaded += ReportSceneLoaded; + MySceneManager.ActiveSceneChanged += ReportSceneActivation; + MySceneManager.SceneUnloaded += ReportSceneUnloaded; + MySceneManager.SceneLoaded += ReportSceneLoaded; } [OneTimeTearDown] public void OneTimeTeardown() { - AdvancedSceneManager.ActiveSceneChanged -= ReportSceneActivation; - AdvancedSceneManager.SceneUnloaded -= ReportSceneUnloaded; - AdvancedSceneManager.SceneLoaded -= ReportSceneLoaded; + MySceneManager.ActiveSceneChanged -= ReportSceneActivation; + MySceneManager.SceneUnloaded -= ReportSceneUnloaded; + MySceneManager.SceneLoaded -= ReportSceneLoaded; } [SetUp] public void TestSetup() { - AdvancedSceneManager.SetActiveScene(AdvancedSceneManager.GetLoadedSceneAt(0)); + MySceneManager.SetActiveScene(MySceneManager.GetLoadedSceneAt(0)); _scenesActivated = 0; _scenesUnloaded = 0; @@ -56,41 +56,41 @@ public IEnumerator UnloadScenesOnTearDown() public void InitialStateTest() { int loadedScenes = 0; - Assert.DoesNotThrow(() => loadedScenes = AdvancedSceneManager.LoadedSceneCount); + Assert.DoesNotThrow(() => loadedScenes = MySceneManager.LoadedSceneCount); Assert.AreEqual(1, loadedScenes); - Assert.AreEqual(1, AdvancedSceneManager.TotalSceneCount); + Assert.AreEqual(1, MySceneManager.TotalSceneCount); Scene activeScene = SceneManager.GetActiveScene(); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetActiveScene()); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLastLoadedScene()); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneAt(0)); - Assert.AreEqual(activeScene, AdvancedSceneManager.GetLoadedSceneByName(activeScene.name)); + Assert.AreEqual(activeScene, MySceneManager.GetActiveScene()); + Assert.AreEqual(activeScene, MySceneManager.GetLastLoadedScene()); + Assert.AreEqual(activeScene, MySceneManager.GetLoadedSceneAt(0)); + Assert.AreEqual(activeScene, MySceneManager.GetLoadedSceneByName(activeScene.name)); } [UnityTest] public IEnumerator Load([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { var progress = new SimpleProgress(); - return Load_Template(() => AdvancedSceneManager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); + return Load_Template(() => MySceneManager.LoadAsync(sceneParameters, progress), progress, sceneParameters.Length, sceneParameters.GetIndexToActivate()); } [UnityTest] public IEnumerator Unload([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SceneParametersList))] SceneParameters sceneParameters) { - yield return Unload_Template(() => AdvancedSceneManager.LoadAsync(sceneParameters), () => AdvancedSceneManager.UnloadAsync(sceneParameters), sceneParameters.Length); + yield return Unload_Template(() => MySceneManager.LoadAsync(sceneParameters), () => MySceneManager.UnloadAsync(sceneParameters), sceneParameters.Length); } [UnityTest] public IEnumerator Transition([ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment. TransitionSceneParametersList))] SceneParameters sceneParameters) { - yield return Transition_Template(() => AdvancedSceneManager.TransitionAsync(sceneParameters), sceneParameters.Length, sceneParameters.GetIndexToActivate()); + yield return Transition_Template(() => MySceneManager.TransitionAsync(sceneParameters), sceneParameters.Length, sceneParameters.GetIndexToActivate()); } public IEnumerator Load_Template(Func> loadTask, SimpleProgress progress, int sceneCount, int setIndexActive) { var reportedScenes = new List(sceneCount); - AdvancedSceneManager.SceneLoaded += reportSceneLoaded; + MySceneManager.SceneLoaded += reportSceneLoaded; var task = loadTask(); @@ -98,15 +98,15 @@ public IEnumerator Load_Template(Func> loadTask, SimpleProgres yield return task.ToWaitTask(); - AdvancedSceneManager.SceneLoaded -= reportSceneLoaded; + MySceneManager.SceneLoaded -= reportSceneLoaded; Scene[] loadedScenes = task.Result; Assert.AreEqual(1, progress.Value); Assert.AreEqual(sceneCount, loadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(sceneCount + 1, AdvancedSceneManager.LoadedSceneCount); + Assert.AreEqual(sceneCount + 1, MySceneManager.LoadedSceneCount); if (setIndexActive >= 0) - Assert.AreEqual(AdvancedSceneManager.GetActiveScene(), loadedScenes[setIndexActive]); + Assert.AreEqual(MySceneManager.GetActiveScene(), loadedScenes[setIndexActive]); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(0, _scenesUnloaded); Assert.AreEqual(setIndexActive >= 0 ? 1 : 0, _scenesActivated); @@ -123,9 +123,9 @@ public IEnumerator Transition_Template(Func> transitionTask, i Scene[] loadedScenes = task.Result; Assert.AreEqual(sceneCount, loadedScenes.Length); - Assert.AreEqual(loadedScenes[setIndexActive], AdvancedSceneManager.GetActiveScene()); + Assert.AreEqual(loadedScenes[setIndexActive], MySceneManager.GetActiveScene()); - yield return new WaitUntil(() => AdvancedSceneManager.TotalSceneCount == sceneCount + 1); + yield return new WaitUntil(() => MySceneManager.TotalSceneCount == sceneCount + 1); } public IEnumerator Unload_Template(Func> loadTask, Func> unloadTask, int sceneCount) @@ -135,17 +135,17 @@ public IEnumerator Unload_Template(Func> loadTask, Func s.handle).ToArray(); var reportedScenes = new List(sceneCount); - AdvancedSceneManager.SceneUnloaded += reportSceneUnloaded; + MySceneManager.SceneUnloaded += reportSceneUnloaded; var unload = unloadTask(); yield return unload.ToWaitTask(); - AdvancedSceneManager.SceneUnloaded -= reportSceneUnloaded; + MySceneManager.SceneUnloaded -= reportSceneUnloaded; Scene[] unloadedScenes = unload.Result; Assert.AreEqual(sceneCount, unloadedScenes.Length); Assert.AreEqual(sceneCount, reportedScenes.Count); - Assert.AreEqual(1, AdvancedSceneManager.LoadedSceneCount); + Assert.AreEqual(1, MySceneManager.LoadedSceneCount); Assert.AreEqual(sceneCount, _scenesLoaded); Assert.AreEqual(sceneCount, _scenesUnloaded); @@ -169,20 +169,20 @@ bool hasReference(int handle, List scenes) /// /// Required to test some transition scenarios. /// - public static WaitTask LoadFirstScene() => AdvancedSceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); + public static WaitTask LoadFirstScene() => MySceneManager.LoadAsync(SceneBuilder.SceneNames[1], true).ToWaitTask(); public static IEnumerator UnloadManagerScenes() { - var lastScene = AdvancedSceneManager.GetLastLoadedScene(); - // The AdvancedSceneManager registers the init scene as one of its managed scenes - while (AdvancedSceneManager.LoadedSceneCount > 1 && lastScene.IsValid()) + var lastScene = MySceneManager.GetLastLoadedScene(); + // MySceneManager registers the init scene as one of its managed scenes + while (MySceneManager.LoadedSceneCount > 1 && lastScene.IsValid()) { - yield return AdvancedSceneManager.UnloadAsync(lastScene).ToWaitTask(); - lastScene = AdvancedSceneManager.GetLastLoadedScene(); + yield return MySceneManager.UnloadAsync(lastScene).ToWaitTask(); + lastScene = MySceneManager.GetLastLoadedScene(); } - Assert.AreEqual(1, AdvancedSceneManager.LoadedSceneCount); - Assert.True(AdvancedSceneManager.GetActiveScene().IsValid()); + Assert.AreEqual(1, MySceneManager.LoadedSceneCount); + Assert.True(MySceneManager.GetActiveScene().IsValid()); } public static IEnumerator UnloadAllScenes() diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs.meta b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_Tests.cs.meta similarity index 100% rename from Packages/com.mygamedevtools.scene-loader/Tests/Runtime/AdvancedSceneManager_Tests.cs.meta rename to Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_Tests.cs.meta diff --git a/Packages/com.mygamedevtools.scene-loader/package.json b/Packages/com.mygamedevtools.scene-loader/package.json index 8f5a6e98..8c75284f 100644 --- a/Packages/com.mygamedevtools.scene-loader/package.json +++ b/Packages/com.mygamedevtools.scene-loader/package.json @@ -1,8 +1,8 @@ { "name": "com.mygamedevtools.scene-loader", "version": "3.1.0", - "displayName": "Advanced Scene Manager", - "description": "This package simplifies scene operations: load, unload and transition.\nFor example, this is how you perform a scene transition:\n\n\u2503AdvancedSceneManager.TransitionAsync(\"my-target-scene\", \"my-loading-scene\");\n\nInstead of:\n\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503\n\u2503 SceneManager.SetActiveScene(\n\u2503 SceneManager.GetSceneByName(\"my-target-scene\"));\n\u2503\n\u2503 SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n\u2503 SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n\nYou can also take advantage of these features:\n\n\u25aa Unified API for addressable and non-addressable scenes.\n\u25aa Awaitable scene operations.\n\u25aa Modular implementation with interfaces.\n\u25aa Load, unload or transition to multiple scenes.", + "displayName": "My Scene Manager", + "description": "This package simplifies scene operations: load, unload and transition.\nFor example, this is how you perform a scene transition:\n\n\u2503MySceneManager.TransitionAsync(\"my-target-scene\", \"my-loading-scene\");\n\nInstead of:\n\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-loading-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503 yield return SceneManager.LoadSceneAsync(\"my-target-scene\",\n\u2503 LoadSceneMode.Additive);\n\u2503\n\u2503 SceneManager.SetActiveScene(\n\u2503 SceneManager.GetSceneByName(\"my-target-scene\"));\n\u2503\n\u2503 SceneManager.UnloadSceneAsync(\"my-loading-scene\");\n\u2503 SceneManager.UnloadSceneAsync(\"my-previous-scene\");\n\nYou can also take advantage of these features:\n\n\u25aa Unified API for addressable and non-addressable scenes.\n\u25aa Awaitable scene operations.\n\u25aa Modular implementation with interfaces.\n\u25aa Load, unload or transition to multiple scenes.", "unity": "2021.3", "keywords": [], "author": { diff --git a/README.md b/README.md index 3c8a7ee0..4b32a3c1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Advanced Scene Manager + My Scene Manager

@@ -19,10 +19,10 @@ ## ⚑ Overview -The **Advanced Scene Manager** is a Unity package to **simplify** scene operations: **load**, **unload** and **transition**. In a quick example: +**My Scene Manager** is a Unity package to **simplify** scene operations: **load**, **unload** and **transition**. In a quick example: ```cs -AdvancedSceneManager.TransitionAsync("my-target-scene", "my-loading-scene"); +MySceneManager.TransitionAsync("my-target-scene", "my-loading-scene"); ``` Instead of: @@ -45,30 +45,43 @@ SceneManager.UnloadSceneAsync("my-previous-scene"); ## πŸ“¦ Installation -Follow the full installation guide in the [documentation](https://mygamedevtools.github.io/scene-loader/docs/next/getting-started/installation). +You can install the package via **[OpenUPM](https://openupm.com/packages/com.mygamedevtools.scene-loader)**, **Git** or **Tarball**. +Check the full installation guide in the [documentation](https://mygamedevtools.com/scene-loader/docs/next/getting-started/installation). -#### Via OpenUPM: +#### OpenUPM -```bash -# Install via OpenUPM -openupm add com.mygamedevtools.scenemanager -``` +* Open `Edit/Project Settings/Package Manager`. +* Add a new **Scoped Registry** (or edit the existing _OpenUPM_ entry): + ``` + Name: Open UPM + URL: https://package.openupm.com + Scope(s): com.mygamedevtools + ``` +* Click `Apply`. +* Open `Window/Package Manager`. +* In the left column, select `Open UPM` inside `My Registries`. +* Select `Advanced Scene Manager` under `My GameDev Tools`. +* Click `Install`. -#### Via Git URL: +#### Git -Add this to your Packages/manifest.json: +1. Open `Window/Package Manager`. +2. Click +. +3. Select `Install package from git URL...`. +4. Paste `https://github.com/mygamedevtools/scene-loader.git#upm` into url. +5. Click `Add`. -```json -{ - "dependencies": { - "com.mygamedevtools.scenemanager": "https://github.com/MyGameDevTools/SceneManager.git" - } -} -``` +#### Tarball + +1. Choose the [release](https://github.com/mygamedevtools/scene-loader/releases) you want to install and download the `com.mygamedevtools.scene-loader-.tgz` asset. +2. Open `Window/Package Manager`. +3. Click +. +4. Select `Install package from tarball...`. +5. Select the `com.mygamedevtools.scene-loader-.tgz` file you downloaded. ## πŸ“š Documentation -The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://mygamedevtools.github.io/scene-loader/). +The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://mygamedevtools.com/scene-loader/). ## 🀝 Contributing diff --git a/docs/img/banner.jpg b/docs/img/banner.jpg index 005854b8bef92613b225f4ec4af71433ab7da8ab..6e32d4dd7d14eed7d9e8e1ef47755476c4d7563a 100644 GIT binary patch delta 69114 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

I;*s9T{maCGgjXG;d=bd5@NA`V}R`W3N6P) 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 delta 74451 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

P1tX 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 Date: Wed, 5 Mar 2025 13:49:40 -0300 Subject: [PATCH 39/53] fix readme links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b32a3c1..a90d645e 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ SceneManager.UnloadSceneAsync("my-previous-scene"); ## πŸ“¦ Installation You can install the package via **[OpenUPM](https://openupm.com/packages/com.mygamedevtools.scene-loader)**, **Git** or **Tarball**. -Check the full installation guide in the [documentation](https://mygamedevtools.com/scene-loader/docs/next/getting-started/installation). +Check the full installation guide in the [documentation](https://scene-loader.mygamedevtools.com/docs/next/getting-started/installation). #### OpenUPM @@ -81,7 +81,7 @@ Check the full installation guide in the [documentation](https://mygamedevtools. ## πŸ“š Documentation -The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://mygamedevtools.com/scene-loader/). +The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://scene-loader.mygamedevtools.com/). ## 🀝 Contributing From 3a5fd738aedf38ece1b48613df2bd43736607443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 5 Mar 2025 16:20:10 -0300 Subject: [PATCH 40/53] add asset store tools --- .../com.unity.asset-store-tools/CHANGELOG.md | 324 +++++++++ .../CHANGELOG.md.meta | 14 + .../com.unity.asset-store-tools/Editor.meta | 8 + .../Editor/Api.meta | 8 + .../Editor/Api/Abstractions.meta | 8 + .../Api/Abstractions/AuthenticationBase.cs | 48 ++ .../Abstractions/AuthenticationBase.cs.meta | 18 + .../Editor/Api/Abstractions/IAssetStoreApi.cs | 21 + .../Api/Abstractions/IAssetStoreApi.cs.meta | 18 + .../Api/Abstractions/IAssetStoreClient.cs | 18 + .../Abstractions/IAssetStoreClient.cs.meta | 18 + .../Api/Abstractions/IAuthenticationType.cs | 11 + .../Abstractions/IAuthenticationType.cs.meta | 18 + .../Api/Abstractions/IPackageUploader.cs | 12 + .../Api/Abstractions/IPackageUploader.cs.meta | 18 + .../Api/Abstractions/PackageUploaderBase.cs | 59 ++ .../Abstractions/PackageUploaderBase.cs.meta | 18 + .../Editor/Api/ApiUtility.cs | 76 ++ .../Editor/Api/ApiUtility.cs.meta | 18 + .../Editor/Api/AssetStoreApi.cs | 268 +++++++ .../Editor/Api/AssetStoreApi.cs.meta | 18 + .../Editor/Api/AssetStoreClient.cs | 55 ++ .../Editor/Api/AssetStoreClient.cs.meta | 18 + .../Editor/Api/CloudTokenAuthentication.cs | 25 + .../Api/CloudTokenAuthentication.cs.meta | 18 + .../Editor/Api/CredentialsAuthentication.cs | 26 + .../Api/CredentialsAuthentication.cs.meta | 18 + .../Editor/Api/Models.meta | 8 + .../Editor/Api/Models/Category.cs | 58 ++ .../Editor/Api/Models/Category.cs.meta | 18 + .../Editor/Api/Models/Package.cs | 80 +++ .../Editor/Api/Models/Package.cs.meta | 18 + .../Api/Models/PackageAdditionalData.cs | 41 ++ .../Api/Models/PackageAdditionalData.cs.meta | 18 + .../Editor/Api/Models/User.cs | 51 ++ .../Editor/Api/Models/User.cs.meta | 18 + .../Editor/Api/Responses.meta | 8 + .../Api/Responses/AssetStoreResponse.cs | 45 ++ .../Api/Responses/AssetStoreResponse.cs.meta | 18 + .../AssetStoreToolsVersionResponse.cs | 38 + .../AssetStoreToolsVersionResponse.cs.meta | 18 + .../Api/Responses/AuthenticationResponse.cs | 74 ++ .../Responses/AuthenticationResponse.cs.meta | 18 + .../Api/Responses/CategoryDataResponse.cs | 43 ++ .../Responses/CategoryDataResponse.cs.meta | 18 + .../Api/Responses/PackageThumbnailResponse.cs | 31 + .../PackageThumbnailResponse.cs.meta | 18 + ...PackageUploadedUnityVersionDataResponse.cs | 44 ++ ...geUploadedUnityVersionDataResponse.cs.meta | 18 + .../PackagesAdditionalDataResponse.cs | 59 ++ .../PackagesAdditionalDataResponse.cs.meta | 18 + .../Api/Responses/PackagesDataResponse.cs | 59 ++ .../Responses/PackagesDataResponse.cs.meta | 18 + .../Responses/RefreshedPackageDataResponse.cs | 12 + .../RefreshedPackageDataResponse.cs.meta | 18 + .../Editor/Api/Responses/UploadResponse.cs | 28 + .../Api/Responses/UploadResponse.cs.meta | 18 + .../Editor/Api/SessionAuthentication.cs | 25 + .../Editor/Api/SessionAuthentication.cs.meta | 18 + .../Editor/Api/UnityPackageUploader.cs | 99 +++ .../Editor/Api/UnityPackageUploader.cs.meta | 18 + .../Editor/Api/UploadStatus.cs | 11 + .../Editor/Api/UploadStatus.cs.meta | 18 + .../Editor/AssemblyInfo.cs | 5 + .../Editor/AssemblyInfo.cs.meta | 18 + .../Editor/AssetStoreTools.cs | 82 +++ .../Editor/AssetStoreTools.cs.meta | 18 + .../Editor/AssetStoreToolsWindow.cs | 23 + .../Editor/AssetStoreToolsWindow.cs.meta | 18 + .../Editor/Constants.cs | 178 +++++ .../Editor/Constants.cs.meta | 18 + .../Editor/Exporter.meta | 8 + .../Editor/Exporter/Abstractions.meta | 8 + .../Exporter/Abstractions/IPackageExporter.cs | 11 + .../Abstractions/IPackageExporter.cs.meta | 18 + .../Exporter/Abstractions/IPreviewInjector.cs | 7 + .../Abstractions/IPreviewInjector.cs.meta | 18 + .../Abstractions/PackageExporterBase.cs | 134 ++++ .../Abstractions/PackageExporterBase.cs.meta | 18 + .../Abstractions/PackageExporterSettings.cs | 7 + .../PackageExporterSettings.cs.meta | 18 + .../Exporter/DefaultExporterSettings.cs | 11 + .../Exporter/DefaultExporterSettings.cs.meta | 18 + .../Editor/Exporter/DefaultPackageExporter.cs | 304 ++++++++ .../Exporter/DefaultPackageExporter.cs.meta | 18 + .../Editor/Exporter/LegacyExporterSettings.cs | 8 + .../Exporter/LegacyExporterSettings.cs.meta | 18 + .../Editor/Exporter/LegacyPackageExporter.cs | 109 +++ .../Exporter/LegacyPackageExporter.cs.meta | 18 + .../Editor/Exporter/PackageExporterResult.cs | 13 + .../Exporter/PackageExporterResult.cs.meta | 18 + .../Editor/Exporter/PreviewInjector.cs | 41 ++ .../Editor/Exporter/PreviewInjector.cs.meta | 18 + .../Editor/Previews.meta | 8 + .../Editor/Previews/Scripts.meta | 8 + .../Editor/Previews/Scripts/Data.meta | 8 + .../Data/CustomPreviewGenerationSettings.cs | 19 + .../CustomPreviewGenerationSettings.cs.meta | 18 + .../Previews/Scripts/Data/FileNameFormat.cs | 9 + .../Scripts/Data/FileNameFormat.cs.meta | 18 + .../Previews/Scripts/Data/GenerationType.cs | 9 + .../Scripts/Data/GenerationType.cs.meta | 18 + .../Data/NativePreviewGenerationSettings.cs | 10 + .../NativePreviewGenerationSettings.cs.meta | 18 + .../Previews/Scripts/Data/PreviewDatabase.cs | 14 + .../Scripts/Data/PreviewDatabase.cs.meta | 18 + .../Previews/Scripts/Data/PreviewFormat.cs | 8 + .../Scripts/Data/PreviewFormat.cs.meta | 18 + .../Scripts/Data/PreviewGenerationResult.cs | 14 + .../Data/PreviewGenerationResult.cs.meta | 18 + .../Scripts/Data/PreviewGenerationSettings.cs | 12 + .../Data/PreviewGenerationSettings.cs.meta | 18 + .../Previews/Scripts/Data/PreviewMetadata.cs | 17 + .../Scripts/Data/PreviewMetadata.cs.meta | 18 + .../Editor/Previews/Scripts/Generators.meta | 8 + .../Previews/Scripts/Generators/Custom.meta | 8 + .../Scripts/Generators/Custom/AudioChannel.cs | 97 +++ .../Generators/Custom/AudioChannel.cs.meta | 18 + .../Custom/AudioChannelCoordinate.cs | 18 + .../Custom/AudioChannelCoordinate.cs.meta | 18 + .../Generators/Custom/Screenshotters.meta | 8 + .../Screenshotters/ISceneScreenshotter.cs | 12 + .../ISceneScreenshotter.cs.meta | 18 + .../Screenshotters/MaterialScreenshotter.cs | 32 + .../MaterialScreenshotter.cs.meta | 18 + .../Screenshotters/MeshScreenshotter.cs | 33 + .../Screenshotters/MeshScreenshotter.cs.meta | 18 + .../Screenshotters/SceneScreenshotterBase.cs | 124 ++++ .../SceneScreenshotterBase.cs.meta | 18 + .../SceneScreenshotterSettings.cs | 16 + .../SceneScreenshotterSettings.cs.meta | 18 + .../Generators/Custom/TypeGenerators.meta | 8 + .../AudioTypeGeneratorSettings.cs | 15 + .../AudioTypeGeneratorSettings.cs.meta | 18 + .../AudioTypePreviewGenerator.cs | 207 ++++++ .../AudioTypePreviewGenerator.cs.meta | 18 + .../TypeGenerators/ITypePreviewGenerator.cs | 16 + .../ITypePreviewGenerator.cs.meta | 18 + .../MaterialTypePreviewGenerator.cs | 85 +++ .../MaterialTypePreviewGenerator.cs.meta | 18 + .../ModelTypePreviewGenerator.cs | 86 +++ .../ModelTypePreviewGenerator.cs.meta | 18 + .../PrefabTypePreviewGenerator.cs | 113 +++ .../PrefabTypePreviewGenerator.cs.meta | 18 + .../TextureTypeGeneratorSettings.cs | 11 + .../TextureTypeGeneratorSettings.cs.meta | 18 + .../TextureTypePreviewGenerator.cs | 116 +++ .../TextureTypePreviewGenerator.cs.meta | 18 + .../TypeGenerators/TypeGeneratorSettings.cs | 12 + .../TypeGeneratorSettings.cs.meta | 18 + .../TypePreviewGeneratorBase.cs | 126 ++++ .../TypePreviewGeneratorBase.cs.meta | 18 + .../TypePreviewGeneratorFromScene.cs | 111 +++ .../TypePreviewGeneratorFromScene.cs.meta | 18 + .../TypePreviewGeneratorFromSceneSettings.cs | 9 + ...ePreviewGeneratorFromSceneSettings.cs.meta | 18 + .../Generators/CustomPreviewGenerator.cs | 213 ++++++ .../Generators/CustomPreviewGenerator.cs.meta | 18 + .../Scripts/Generators/IPreviewGenerator.cs | 15 + .../Generators/IPreviewGenerator.cs.meta | 18 + .../Generators/NativePreviewGenerator.cs | 362 ++++++++++ .../Generators/NativePreviewGenerator.cs.meta | 18 + .../Generators/PreviewGeneratorBase.cs | 45 ++ .../Generators/PreviewGeneratorBase.cs.meta | 18 + .../Editor/Previews/Scripts/Services.meta | 8 + .../Previews/Scripts/Services/Caching.meta | 8 + .../Services/Caching/CachingService.cs | 87 +++ .../Services/Caching/CachingService.cs.meta | 18 + .../Services/Caching/ICachingService.cs | 11 + .../Services/Caching/ICachingService.cs.meta | 18 + .../Scripts/Services/IPreviewService.cs | 4 + .../Scripts/Services/IPreviewService.cs.meta | 18 + .../Services/PreviewServiceProvider.cs | 17 + .../Services/PreviewServiceProvider.cs.meta | 18 + .../Editor/Previews/Scripts/UI.meta | 8 + .../Editor/Previews/Scripts/UI/Data.meta | 8 + .../Previews/Scripts/UI/Data/AssetPreview.cs | 56 ++ .../Scripts/UI/Data/AssetPreview.cs.meta | 18 + .../Scripts/UI/Data/AssetPreviewCollection.cs | 46 ++ .../UI/Data/AssetPreviewCollection.cs.meta | 18 + .../Previews/Scripts/UI/Data/IAssetPreview.cs | 13 + .../Scripts/UI/Data/IAssetPreview.cs.meta | 18 + .../UI/Data/IAssetPreviewCollection.cs | 15 + .../UI/Data/IAssetPreviewCollection.cs.meta | 18 + .../UI/Data/IPreviewGeneratorSettings.cs | 27 + .../UI/Data/IPreviewGeneratorSettings.cs.meta | 18 + .../UI/Data/PreviewGeneratorSettings.cs | 212 ++++++ .../UI/Data/PreviewGeneratorSettings.cs.meta | 18 + .../Editor/Previews/Scripts/UI/Elements.meta | 8 + .../UI/Elements/AssetPreviewElement.cs | 83 +++ .../UI/Elements/AssetPreviewElement.cs.meta | 18 + .../Scripts/UI/Elements/GridListElement.cs | 140 ++++ .../UI/Elements/GridListElement.cs.meta | 18 + .../UI/Elements/PreviewCollectionElement.cs | 116 +++ .../Elements/PreviewCollectionElement.cs.meta | 18 + .../Elements/PreviewGenerateButtonElement.cs | 50 ++ .../PreviewGenerateButtonElement.cs.meta | 18 + .../Elements/PreviewGeneratorPathsElement.cs | 122 ++++ .../PreviewGeneratorPathsElement.cs.meta | 18 + .../PreviewGeneratorSettingsElement.cs | 99 +++ .../PreviewGeneratorSettingsElement.cs.meta | 18 + .../PreviewWindowDescriptionElement.cs | 87 +++ .../PreviewWindowDescriptionElement.cs.meta | 18 + .../Scripts/UI/PreviewGeneratorWindow.cs | 51 ++ .../Scripts/UI/PreviewGeneratorWindow.cs.meta | 18 + .../Editor/Previews/Scripts/UI/Views.meta | 8 + .../Scripts/UI/Views/PreviewListView.cs | 142 ++++ .../Scripts/UI/Views/PreviewListView.cs.meta | 18 + .../Editor/Previews/Scripts/Utility.meta | 8 + .../Scripts/Utility/GraphicsUtility.cs | 96 +++ .../Scripts/Utility/GraphicsUtility.cs.meta | 18 + .../Scripts/Utility/PreviewConvertUtility.cs | 72 ++ .../Utility/PreviewConvertUtility.cs.meta | 18 + .../Scripts/Utility/PreviewSceneUtility.cs | 196 ++++++ .../Utility/PreviewSceneUtility.cs.meta | 18 + .../Scripts/Utility/RenderPipeline.cs | 10 + .../Scripts/Utility/RenderPipeline.cs.meta | 18 + .../Scripts/Utility/RenderPipelineUtility.cs | 32 + .../Utility/RenderPipelineUtility.cs.meta | 18 + .../Editor/Previews/Styles.meta | 8 + .../Editor/Previews/Styles/Style.uss | 210 ++++++ .../Editor/Previews/Styles/Style.uss.meta | 18 + .../Editor/Previews/Styles/ThemeDark.uss | 67 ++ .../Editor/Previews/Styles/ThemeDark.uss.meta | 18 + .../Editor/Previews/Styles/ThemeLight.uss | 67 ++ .../Previews/Styles/ThemeLight.uss.meta | 18 + .../Unity.AssetStoreTools.Editor.asmdef | 36 + .../Unity.AssetStoreTools.Editor.asmdef.meta | 14 + .../Editor/Uploader.meta | 8 + .../Editor/Uploader/Icons.meta | 8 + .../Editor/Uploader/Icons/account-dark.png | Bin 0 -> 337 bytes .../Uploader/Icons/account-dark.png.meta | 130 ++++ .../Editor/Uploader/Icons/account-light.png | Bin 0 -> 387 bytes .../Uploader/Icons/account-light.png.meta | 130 ++++ .../Editor/Uploader/Icons/open-in-browser.png | Bin 0 -> 878 bytes .../Uploader/Icons/open-in-browser.png.meta | 154 ++++ .../Uploader/Icons/publisher-portal-dark.png | Bin 0 -> 33588 bytes .../Icons/publisher-portal-dark.png.meta | 135 ++++ .../Uploader/Icons/publisher-portal-light.png | Bin 0 -> 33281 bytes .../Icons/publisher-portal-light.png.meta | 142 ++++ .../Editor/Uploader/Scripts.meta | 8 + .../Editor/Uploader/Scripts/Data.meta | 8 + .../Uploader/Scripts/Data/Abstractions.meta | 8 + .../Scripts/Data/Abstractions/IPackage.cs | 34 + .../Data/Abstractions/IPackage.cs.meta | 18 + .../Data/Abstractions/IPackageContent.cs | 14 + .../Data/Abstractions/IPackageContent.cs.meta | 18 + .../Data/Abstractions/IPackageGroup.cs | 17 + .../Data/Abstractions/IPackageGroup.cs.meta | 18 + .../Scripts/Data/Abstractions/IWorkflow.cs | 36 + .../Data/Abstractions/IWorkflow.cs.meta | 18 + .../Data/Abstractions/IWorkflowServices.cs | 18 + .../Abstractions/IWorkflowServices.cs.meta | 18 + .../Scripts/Data/Abstractions/WorkflowBase.cs | 253 +++++++ .../Data/Abstractions/WorkflowBase.cs.meta | 18 + .../Uploader/Scripts/Data/AssetsWorkflow.cs | 329 +++++++++ .../Scripts/Data/AssetsWorkflow.cs.meta | 18 + .../Scripts/Data/HybridPackageWorkflow.cs | 251 +++++++ .../Data/HybridPackageWorkflow.cs.meta | 18 + .../Editor/Uploader/Scripts/Data/Package.cs | 91 +++ .../Uploader/Scripts/Data/Package.cs.meta | 18 + .../Uploader/Scripts/Data/PackageContent.cs | 68 ++ .../Scripts/Data/PackageContent.cs.meta | 18 + .../Uploader/Scripts/Data/PackageGroup.cs | 64 ++ .../Scripts/Data/PackageGroup.cs.meta | 18 + .../Uploader/Scripts/Data/PackageSorting.cs | 9 + .../Scripts/Data/PackageSorting.cs.meta | 18 + .../Uploader/Scripts/Data/Serialization.meta | 8 + .../Scripts/Data/Serialization/AssetPath.cs | 59 ++ .../Data/Serialization/AssetPath.cs.meta | 18 + .../Serialization/AssetsWorkflowStateData.cs | 77 ++ .../AssetsWorkflowStateData.cs.meta | 18 + .../HybridPackageWorkflowState.cs | 41 ++ .../HybridPackageWorkflowState.cs.meta | 18 + .../UnityPackageWorkflowStateData.cs | 25 + .../UnityPackageWorkflowStateData.cs.meta | 18 + .../Data/Serialization/WorkflowStateData.cs | 68 ++ .../Serialization/WorkflowStateData.cs.meta | 18 + .../Scripts/Data/UnityPackageWorkflow.cs | 135 ++++ .../Scripts/Data/UnityPackageWorkflow.cs.meta | 18 + .../Uploader/Scripts/Data/WorkflowServices.cs | 53 ++ .../Scripts/Data/WorkflowServices.cs.meta | 18 + .../Editor/Uploader/Scripts/Services.meta | 8 + .../Uploader/Scripts/Services/Analytics.meta | 8 + .../Services/Analytics/AnalyticsService.cs | 45 ++ .../Analytics/AnalyticsService.cs.meta | 18 + .../Scripts/Services/Analytics/Data.meta | 8 + .../Analytics/Data/AuthenticationAnalytic.cs | 46 ++ .../Data/AuthenticationAnalytic.cs.meta | 18 + .../Services/Analytics/Data/BaseAnalytic.cs | 35 + .../Analytics/Data/BaseAnalytic.cs.meta | 18 + .../Analytics/Data/IAssetStoreAnalytic.cs | 16 + .../Data/IAssetStoreAnalytic.cs.meta | 18 + .../Analytics/Data/IAssetStoreAnalyticData.cs | 8 + .../Data/IAssetStoreAnalyticData.cs.meta | 18 + .../Analytics/Data/PackageUploadAnalytic.cs | 72 ++ .../Data/PackageUploadAnalytic.cs.meta | 18 + .../Data/ValidationResultsSerializer.cs | 91 +++ .../Data/ValidationResultsSerializer.cs.meta | 18 + .../Services/Analytics/IAnalyticsService.cs | 10 + .../Analytics/IAnalyticsService.cs.meta | 18 + .../Editor/Uploader/Scripts/Services/Api.meta | 8 + .../Services/Api/AuthenticationService.cs | 100 +++ .../Api/AuthenticationService.cs.meta | 18 + .../Services/Api/IAuthenticationService.cs | 16 + .../Api/IAuthenticationService.cs.meta | 18 + .../Api/IPackageDownloadingService.cs | 16 + .../Api/IPackageDownloadingService.cs.meta | 18 + .../Services/Api/IPackageUploadingService.cs | 16 + .../Api/IPackageUploadingService.cs.meta | 18 + .../Services/Api/PackageDownloadingService.cs | 109 +++ .../Api/PackageDownloadingService.cs.meta | 18 + .../Services/Api/PackageUploadingService.cs | 103 +++ .../Api/PackageUploadingService.cs.meta | 18 + .../Uploader/Scripts/Services/Caching.meta | 8 + .../Services/Caching/CachingService.cs | 157 +++++ .../Services/Caching/CachingService.cs.meta | 18 + .../Services/Caching/ICachingService.cs | 25 + .../Services/Caching/ICachingService.cs.meta | 18 + .../Scripts/Services/IUploaderService.cs | 4 + .../Scripts/Services/IUploaderService.cs.meta | 18 + .../Scripts/Services/PackageFactory.meta | 8 + .../PackageFactory/IPackageFactoryService.cs | 18 + .../IPackageFactoryService.cs.meta | 18 + .../PackageFactory/PackageFactoryService.cs | 95 +++ .../PackageFactoryService.cs.meta | 18 + .../Services/UploaderServiceProvider.cs | 26 + .../Services/UploaderServiceProvider.cs.meta | 18 + .../Editor/Uploader/Scripts/UI.meta | 8 + .../Editor/Uploader/Scripts/UI/Elements.meta | 8 + .../Scripts/UI/Elements/Abstractions.meta | 8 + .../Abstractions/ValidationElementBase.cs | 170 +++++ .../ValidationElementBase.cs.meta | 18 + .../Abstractions/WorkflowElementBase.cs | 151 ++++ .../Abstractions/WorkflowElementBase.cs.meta | 18 + .../Scripts/UI/Elements/AccountToolbar.cs | 102 +++ .../UI/Elements/AccountToolbar.cs.meta | 18 + .../UI/Elements/AssetsWorkflowElement.cs | 215 ++++++ .../UI/Elements/AssetsWorkflowElement.cs.meta | 18 + .../CurrentProjectValidationElement.cs | 31 + .../CurrentProjectValidationElement.cs.meta | 18 + .../ExternalProjectValidationElement.cs | 92 +++ .../ExternalProjectValidationElement.cs.meta | 18 + .../Elements/HybridPackageWorkflowElement.cs | 116 +++ .../HybridPackageWorkflowElement.cs.meta | 18 + .../Scripts/UI/Elements/LoadingSpinner.cs | 52 ++ .../UI/Elements/LoadingSpinner.cs.meta | 18 + .../Elements/MultiToggleSelectionElement.cs | 187 +++++ .../MultiToggleSelectionElement.cs.meta | 18 + .../UI/Elements/PackageContentElement.cs | 137 ++++ .../UI/Elements/PackageContentElement.cs.meta | 18 + .../Scripts/UI/Elements/PackageElement.cs | 215 ++++++ .../UI/Elements/PackageElement.cs.meta | 18 + .../UI/Elements/PackageGroupElement.cs | 149 ++++ .../UI/Elements/PackageGroupElement.cs.meta | 18 + .../Scripts/UI/Elements/PackageListToolbar.cs | 58 ++ .../UI/Elements/PackageListToolbar.cs.meta | 18 + .../UI/Elements/PackageUploadElement.cs | 321 +++++++++ .../UI/Elements/PackageUploadElement.cs.meta | 18 + .../UI/Elements/PathSelectionElement.cs | 63 ++ .../UI/Elements/PathSelectionElement.cs.meta | 18 + .../UI/Elements/PreviewGenerationElement.cs | 109 +++ .../Elements/PreviewGenerationElement.cs.meta | 18 + .../Elements/UnityPackageWorkflowElement.cs | 58 ++ .../UnityPackageWorkflowElement.cs.meta | 18 + .../Editor/Uploader/Scripts/UI/Views.meta | 8 + .../Uploader/Scripts/UI/Views/LoginView.cs | 284 ++++++++ .../Scripts/UI/Views/LoginView.cs.meta | 18 + .../Scripts/UI/Views/PackageListView.cs | 249 +++++++ .../Scripts/UI/Views/PackageListView.cs.meta | 18 + .../Editor/Uploader/Styles.meta | 8 + .../Editor/Uploader/Styles/LoginView.meta | 8 + .../Uploader/Styles/LoginView/Style.uss | 134 ++++ .../Uploader/Styles/LoginView/Style.uss.meta | 18 + .../Uploader/Styles/LoginView/ThemeDark.uss | 44 ++ .../Styles/LoginView/ThemeDark.uss.meta | 18 + .../Uploader/Styles/LoginView/ThemeLight.uss | 44 ++ .../Styles/LoginView/ThemeLight.uss.meta | 18 + .../Uploader/Styles/PackageListView.meta | 8 + .../Uploader/Styles/PackageListView/Style.uss | 485 +++++++++++++ .../Styles/PackageListView/Style.uss.meta | 18 + .../Styles/PackageListView/ThemeDark.uss | 238 +++++++ .../Styles/PackageListView/ThemeDark.uss.meta | 18 + .../Styles/PackageListView/ThemeLight.uss | 238 +++++++ .../PackageListView/ThemeLight.uss.meta | 18 + .../Editor/Uploader/Styles/Style.uss | 74 ++ .../Editor/Uploader/Styles/Style.uss.meta | 18 + .../Editor/Uploader/Styles/ThemeDark.uss | 9 + .../Editor/Uploader/Styles/ThemeDark.uss.meta | 18 + .../Editor/Uploader/Styles/ThemeLight.uss | 9 + .../Uploader/Styles/ThemeLight.uss.meta | 18 + .../Editor/Uploader/UploaderWindow.cs | 232 ++++++ .../Editor/Uploader/UploaderWindow.cs.meta | 18 + .../Editor/Utility.meta | 8 + .../Editor/Utility/ASDebug.cs | 65 ++ .../Editor/Utility/ASDebug.cs.meta | 18 + .../Editor/Utility/ASToolsPreferences.cs | 134 ++++ .../Editor/Utility/ASToolsPreferences.cs.meta | 18 + .../Editor/Utility/ASToolsUpdater.cs | 250 +++++++ .../Editor/Utility/ASToolsUpdater.cs.meta | 18 + .../Editor/Utility/CacheUtil.cs | 266 +++++++ .../Editor/Utility/CacheUtil.cs.meta | 18 + .../Editor/Utility/FileUtility.cs | 207 ++++++ .../Editor/Utility/FileUtility.cs.meta | 18 + .../Editor/Utility/LegacyToolsRemover.cs | 86 +++ .../Editor/Utility/LegacyToolsRemover.cs.meta | 18 + .../Editor/Utility/PackageUtility.cs | 170 +++++ .../Editor/Utility/PackageUtility.cs.meta | 18 + .../Editor/Utility/ServiceProvider.cs | 113 +++ .../Editor/Utility/ServiceProvider.cs.meta | 18 + .../Editor/Utility/StyleSelector.cs | 55 ++ .../Editor/Utility/StyleSelector.cs.meta | 18 + .../Editor/Utility/Styles.meta | 8 + .../Editor/Utility/Styles/Updater.meta | 8 + .../Editor/Utility/Styles/Updater/Style.uss | 76 ++ .../Utility/Styles/Updater/Style.uss.meta | 18 + .../Utility/Styles/Updater/ThemeDark.uss | 3 + .../Utility/Styles/Updater/ThemeDark.uss.meta | 18 + .../Utility/Styles/Updater/ThemeLight.uss | 3 + .../Styles/Updater/ThemeLight.uss.meta | 18 + .../Editor/Utility/SymlinkUtil.cs | 67 ++ .../Editor/Utility/SymlinkUtil.cs.meta | 10 + .../Editor/Validator.meta | 8 + .../Editor/Validator/Icons.meta | 8 + .../Editor/Validator/Icons/error.png | Bin 0 -> 1057 bytes .../Editor/Validator/Icons/error.png.meta | 135 ++++ .../Editor/Validator/Icons/error_d.png | Bin 0 -> 1024 bytes .../Editor/Validator/Icons/error_d.png.meta | 135 ++++ .../Editor/Validator/Icons/success.png | Bin 0 -> 1583 bytes .../Editor/Validator/Icons/success.png.meta | 135 ++++ .../Editor/Validator/Icons/success_d.png | Bin 0 -> 1617 bytes .../Editor/Validator/Icons/success_d.png.meta | 135 ++++ .../Editor/Validator/Icons/undefined.png | Bin 0 -> 1561 bytes .../Editor/Validator/Icons/undefined.png.meta | 135 ++++ .../Editor/Validator/Icons/undefined_d.png | Bin 0 -> 1600 bytes .../Validator/Icons/undefined_d.png.meta | 135 ++++ .../Editor/Validator/Icons/warning.png | Bin 0 -> 1141 bytes .../Editor/Validator/Icons/warning.png.meta | 135 ++++ .../Editor/Validator/Icons/warning_d.png | Bin 0 -> 1185 bytes .../Editor/Validator/Icons/warning_d.png.meta | 135 ++++ .../Editor/Validator/Scripts.meta | 8 + .../Editor/Validator/Scripts/Categories.meta | 3 + .../Scripts/Categories/CategoryEvaluator.cs | 52 ++ .../Categories/CategoryEvaluator.cs.meta | 10 + .../Scripts/Categories/ValidatorCategory.cs | 38 + .../Categories/ValidatorCategory.cs.meta | 10 + .../Scripts/CurrentProjectValidator.cs | 71 ++ .../Scripts/CurrentProjectValidator.cs.meta | 18 + .../Editor/Validator/Scripts/Data.meta | 8 + .../Data/CurrentProjectValidationSettings.cs | 33 + .../CurrentProjectValidationSettings.cs.meta | 18 + .../Data/ExternalProjectValidationSettings.cs | 7 + .../ExternalProjectValidationSettings.cs.meta | 18 + .../Scripts/Data/MessageActions.meta | 8 + .../MessageActions/HighlightObjectAction.cs | 31 + .../HighlightObjectAction.cs.meta | 18 + .../Data/MessageActions/IMessageAction.cs | 16 + .../MessageActions/IMessageAction.cs.meta | 18 + .../Data/MessageActions/OpenAssetAction.cs | 38 + .../MessageActions/OpenAssetAction.cs.meta | 18 + .../Validator/Scripts/Data/TestResult.cs | 52 ++ .../Validator/Scripts/Data/TestResult.cs.meta | 18 + .../Scripts/Data/TestResultMessage.cs | 53 ++ .../Scripts/Data/TestResultMessage.cs.meta | 18 + .../Scripts/Data/TestResultObject.cs | 35 + .../Scripts/Data/TestResultObject.cs.meta | 18 + .../Scripts/Data/TestResultStatus.cs | 11 + .../Scripts/Data/TestResultStatus.cs.meta | 18 + .../Scripts/Data/ValidationResult.cs | 24 + .../Scripts/Data/ValidationResult.cs.meta | 18 + .../Scripts/Data/ValidationSettings.cs | 7 + .../Scripts/Data/ValidationSettings.cs.meta | 18 + .../Scripts/Data/ValidationStatus.cs | 10 + .../Scripts/Data/ValidationStatus.cs.meta | 18 + .../Validator/Scripts/Data/ValidationType.cs | 8 + .../Scripts/Data/ValidationType.cs.meta | 18 + .../Scripts/ExternalProjectValidator.cs | 259 +++++++ .../Scripts/ExternalProjectValidator.cs.meta | 18 + .../Editor/Validator/Scripts/IValidator.cs | 11 + .../Validator/Scripts/IValidator.cs.meta | 18 + .../Editor/Validator/Scripts/Services.meta | 8 + .../Scripts/Services/CachingService.meta | 8 + .../Services/CachingService/CachingService.cs | 55 ++ .../CachingService/CachingService.cs.meta | 18 + .../CachingService/ICachingService.cs | 11 + .../CachingService/ICachingService.cs.meta | 18 + .../PreviewDatabaseContractResolver.cs | 26 + .../PreviewDatabaseContractResolver.cs.meta | 18 + .../Scripts/Services/IValidatorService.cs | 4 + .../Services/IValidatorService.cs.meta | 18 + .../Scripts/Services/Validation.meta | 8 + .../Services/Validation/Abstractions.meta | 8 + .../Abstractions/IAssetUtilityService.cs | 18 + .../Abstractions/IAssetUtilityService.cs.meta | 18 + .../IFileSignatureUtilityService.cs | 7 + .../IFileSignatureUtilityService.cs.meta | 18 + .../Abstractions/IMeshUtilityService.cs | 10 + .../Abstractions/IMeshUtilityService.cs.meta | 18 + .../Abstractions/IModelUtilityService.cs | 10 + .../Abstractions/IModelUtilityService.cs.meta | 18 + .../Abstractions/ISceneUtilityService.cs | 13 + .../Abstractions/ISceneUtilityService.cs.meta | 18 + .../Abstractions/IScriptUtilityService.cs | 14 + .../IScriptUtilityService.cs.meta | 18 + .../Validation/AssetUtilityService.cs | 216 ++++++ .../Validation/AssetUtilityService.cs.meta | 18 + .../Scripts/Services/Validation/Data.meta | 8 + .../Services/Validation/Data/ArchiveType.cs | 19 + .../Validation/Data/ArchiveType.cs.meta | 18 + .../Validation/Data/AssetEnumerator.cs | 84 +++ .../Validation/Data/AssetEnumerator.cs.meta | 18 + .../Services/Validation/Data/AssetType.cs | 25 + .../Validation/Data/AssetType.cs.meta | 18 + .../Services/Validation/Data/LogEntry.cs | 10 + .../Services/Validation/Data/LogEntry.cs.meta | 18 + .../Validation/FileSignatureUtilityService.cs | 78 +++ .../FileSignatureUtilityService.cs.meta | 18 + .../Services/Validation/MeshUtilityService.cs | 26 + .../Validation/MeshUtilityService.cs.meta | 18 + .../Validation/ModelUtilityService.cs | 147 ++++ .../Validation/ModelUtilityService.cs.meta | 18 + .../Validation/SceneUtilityService.cs | 26 + .../Validation/SceneUtilityService.cs.meta | 18 + .../Validation/ScriptUtilityService.cs | 658 ++++++++++++++++++ .../Validation/ScriptUtilityService.cs.meta | 18 + .../Services/ValidatorServiceProvider.cs | 24 + .../Services/ValidatorServiceProvider.cs.meta | 18 + .../Validator/Scripts/Test Definitions.meta | 8 + .../Scripts/Test Definitions/AutomatedTest.cs | 121 ++++ .../Test Definitions/AutomatedTest.cs.meta | 18 + .../Test Definitions/GenericTestConfig.cs | 7 + .../GenericTestConfig.cs.meta | 18 + .../Scripts/Test Definitions/ITestConfig.cs | 4 + .../Test Definitions/ITestConfig.cs.meta | 18 + .../Scripts/Test Definitions/ITestScript.cs | 9 + .../Test Definitions/ITestScript.cs.meta | 18 + .../Test Definitions/Scriptable Objects.meta | 8 + .../AutomatedTestScriptableObject.cs | 11 + .../AutomatedTestScriptableObject.cs.meta | 19 + .../Scriptable Objects/Editor.meta | 8 + ...ValidationTestScriptableObjectInspector.cs | 196 ++++++ ...ationTestScriptableObjectInspector.cs.meta | 19 + .../ValidationTestScriptableObject.cs | 35 + .../ValidationTestScriptableObject.cs.meta | 19 + .../Test Definitions/ValidationTest.cs | 38 + .../Test Definitions/ValidationTest.cs.meta | 18 + .../Validator/Scripts/Test Methods.meta | 8 + .../Scripts/Test Methods/Generic.meta | 8 + .../Generic/CheckAnimationClips.cs | 64 ++ .../Generic/CheckAnimationClips.cs.meta | 18 + .../Generic/CheckAudioClipping.cs | 128 ++++ .../Generic/CheckAudioClipping.cs.meta | 18 + .../Test Methods/Generic/CheckColliders.cs | 55 ++ .../Generic/CheckColliders.cs.meta | 18 + .../Generic/CheckCompressedFiles.cs | 121 ++++ .../Generic/CheckCompressedFiles.cs.meta | 18 + .../Test Methods/Generic/CheckEmptyPrefabs.cs | 46 ++ .../Generic/CheckEmptyPrefabs.cs.meta | 18 + .../Generic/CheckFileMenuNames.cs | 153 ++++ .../Generic/CheckFileMenuNames.cs.meta | 18 + .../Scripts/Test Methods/Generic/CheckLODs.cs | 79 +++ .../Test Methods/Generic/CheckLODs.cs.meta | 18 + .../Test Methods/Generic/CheckLineEndings.cs | 77 ++ .../Generic/CheckLineEndings.cs.meta | 18 + .../Test Methods/Generic/CheckMeshPrefabs.cs | 106 +++ .../Generic/CheckMeshPrefabs.cs.meta | 18 + .../Generic/CheckMissingComponentsinAssets.cs | 66 ++ .../CheckMissingComponentsinAssets.cs.meta | 18 + .../Generic/CheckMissingComponentsinScenes.cs | 93 +++ .../CheckMissingComponentsinScenes.cs.meta | 18 + .../Generic/CheckModelImportLogs.cs | 64 ++ .../Generic/CheckModelImportLogs.cs.meta | 18 + .../Generic/CheckModelOrientation.cs | 71 ++ .../Generic/CheckModelOrientation.cs.meta | 18 + .../Test Methods/Generic/CheckModelTypes.cs | 58 ++ .../Generic/CheckModelTypes.cs.meta | 18 + .../Generic/CheckNormalMapTextures.cs | 94 +++ .../Generic/CheckNormalMapTextures.cs.meta | 18 + .../Generic/CheckPackageNaming.cs | 295 ++++++++ .../Generic/CheckPackageNaming.cs.meta | 18 + .../Generic/CheckParticleSystems.cs | 76 ++ .../Generic/CheckParticleSystems.cs.meta | 18 + .../Test Methods/Generic/CheckPathLengths.cs | 98 +++ .../Generic/CheckPathLengths.cs.meta | 18 + .../Generic/CheckPrefabTransforms.cs | 71 ++ .../Generic/CheckPrefabTransforms.cs.meta | 18 + .../Generic/CheckScriptCompilation.cs | 30 + .../Generic/CheckScriptCompilation.cs.meta | 18 + .../Generic/CheckShaderCompilation.cs | 63 ++ .../Generic/CheckShaderCompilation.cs.meta | 18 + .../Generic/CheckTextureDimensions.cs | 57 ++ .../Generic/CheckTextureDimensions.cs.meta | 18 + .../Generic/CheckTypeNamespaces.cs | 233 +++++++ .../Generic/CheckTypeNamespaces.cs.meta | 18 + .../Generic/RemoveExecutableFiles.cs | 38 + .../Generic/RemoveExecutableFiles.cs.meta | 18 + .../Test Methods/Generic/RemoveJPGFiles.cs | 38 + .../Generic/RemoveJPGFiles.cs.meta | 18 + .../Generic/RemoveJavaScriptFiles.cs | 38 + .../Generic/RemoveJavaScriptFiles.cs.meta | 18 + .../Generic/RemoveLossyAudioFiles.cs | 83 +++ .../Generic/RemoveLossyAudioFiles.cs.meta | 18 + .../Test Methods/Generic/RemoveMixamoFiles.cs | 38 + .../Generic/RemoveMixamoFiles.cs.meta | 18 + .../Generic/RemoveSpeedTreeFiles.cs | 38 + .../Generic/RemoveSpeedTreeFiles.cs.meta | 18 + .../Test Methods/Generic/RemoveVideoFiles.cs | 38 + .../Generic/RemoveVideoFiles.cs.meta | 18 + .../Scripts/Test Methods/UnityPackage.meta | 8 + .../UnityPackage/CheckDemoScenes.cs | 172 +++++ .../UnityPackage/CheckDemoScenes.cs.meta | 18 + .../UnityPackage/CheckDocumentation.cs | 73 ++ .../UnityPackage/CheckDocumentation.cs.meta | 18 + .../UnityPackage/CheckPackageSize.cs | 69 ++ .../UnityPackage/CheckPackageSize.cs.meta | 18 + .../CheckProjectTemplateAssets.cs | 217 ++++++ .../CheckProjectTemplateAssets.cs.meta | 18 + .../Editor/Validator/Scripts/UI.meta | 8 + .../Editor/Validator/Scripts/UI/Data.meta | 8 + .../Scripts/UI/Data/Abstractions.meta | 8 + .../UI/Data/Abstractions/IValidatorResults.cs | 15 + .../Abstractions/IValidatorResults.cs.meta | 18 + .../Data/Abstractions/IValidatorSettings.cs | 31 + .../Abstractions/IValidatorSettings.cs.meta | 18 + .../UI/Data/Abstractions/IValidatorTest.cs | 15 + .../Data/Abstractions/IValidatorTest.cs.meta | 18 + .../Data/Abstractions/IValidatorTestGroup.cs | 12 + .../Abstractions/IValidatorTestGroup.cs.meta | 18 + .../Scripts/UI/Data/Serialization.meta | 8 + .../Data/Serialization/ValidatorStateData.cs | 28 + .../Serialization/ValidatorStateData.cs.meta | 18 + .../ValidatorStateDataContractResolver.cs | 26 + ...ValidatorStateDataContractResolver.cs.meta | 18 + .../Serialization/ValidatorStateResults.cs | 83 +++ .../ValidatorStateResults.cs.meta | 18 + .../Serialization/ValidatorStateSettings.cs | 63 ++ .../ValidatorStateSettings.cs.meta | 18 + .../Scripts/UI/Data/ValidatorResults.cs | 137 ++++ .../Scripts/UI/Data/ValidatorResults.cs.meta | 18 + .../Scripts/UI/Data/ValidatorSettings.cs | 236 +++++++ .../Scripts/UI/Data/ValidatorSettings.cs.meta | 18 + .../Scripts/UI/Data/ValidatorTest.cs | 28 + .../Scripts/UI/Data/ValidatorTest.cs.meta | 18 + .../Scripts/UI/Data/ValidatorTestGroup.cs | 18 + .../UI/Data/ValidatorTestGroup.cs.meta | 18 + .../Editor/Validator/Scripts/UI/Elements.meta | 8 + .../UI/Elements/ValidatorButtonElement.cs | 50 ++ .../Elements/ValidatorButtonElement.cs.meta | 18 + .../Elements/ValidatorDescriptionElement.cs | 114 +++ .../ValidatorDescriptionElement.cs.meta | 10 + .../UI/Elements/ValidatorPathsElement.cs | 128 ++++ .../UI/Elements/ValidatorPathsElement.cs.meta | 18 + .../UI/Elements/ValidatorResultsElement.cs | 47 ++ .../Elements/ValidatorResultsElement.cs.meta | 18 + .../UI/Elements/ValidatorSettingsElement.cs | 96 +++ .../Elements/ValidatorSettingsElement.cs.meta | 18 + .../UI/Elements/ValidatorTestElement.cs | 239 +++++++ .../UI/Elements/ValidatorTestElement.cs.meta | 18 + .../UI/Elements/ValidatorTestGroupElement.cs | 102 +++ .../ValidatorTestGroupElement.cs.meta | 18 + .../Validator/Scripts/UI/ValidatorWindow.cs | 56 ++ .../Scripts/UI/ValidatorWindow.cs.meta | 18 + .../Editor/Validator/Scripts/UI/Views.meta | 8 + .../Scripts/UI/Views/ValidatorTestsView.cs | 103 +++ .../UI/Views/ValidatorTestsView.cs.meta | 18 + .../Editor/Validator/Scripts/Utility.meta | 8 + .../Scripts/Utility/ValidatorUtility.cs | 142 ++++ .../Scripts/Utility/ValidatorUtility.cs.meta | 18 + .../Editor/Validator/Scripts/ValidatorBase.cs | 108 +++ .../Validator/Scripts/ValidatorBase.cs.meta | 18 + .../Editor/Validator/Styles.meta | 8 + .../Editor/Validator/Styles/Style.uss | 337 +++++++++ .../Editor/Validator/Styles/Style.uss.meta | 18 + .../Editor/Validator/Styles/ThemeDark.uss | 166 +++++ .../Validator/Styles/ThemeDark.uss.meta | 18 + .../Editor/Validator/Styles/ThemeLight.uss | 166 +++++ .../Validator/Styles/ThemeLight.uss.meta | 18 + .../Editor/Validator/Tests.meta | 8 + .../Editor/Validator/Tests/Generic.meta | 8 + .../Tests/Generic/Check Animation Clips.asset | 27 + .../Generic/Check Animation Clips.asset.meta | 16 + .../Tests/Generic/Check Audio Clipping.asset | 32 + .../Generic/Check Audio Clipping.asset.meta | 16 + .../Tests/Generic/Check Colliders.asset | 26 + .../Tests/Generic/Check Colliders.asset.meta | 16 + .../Generic/Check Compressed Files.asset | 31 + .../Generic/Check Compressed Files.asset.meta | 16 + .../Tests/Generic/Check Empty Prefabs.asset | 31 + .../Generic/Check Empty Prefabs.asset.meta | 16 + .../Tests/Generic/Check File Menu Names.asset | 26 + .../Generic/Check File Menu Names.asset.meta | 16 + .../Validator/Tests/Generic/Check LODs.asset | 33 + .../Tests/Generic/Check LODs.asset.meta | 16 + .../Tests/Generic/Check Line Endings.asset | 26 + .../Generic/Check Line Endings.asset.meta | 16 + .../Tests/Generic/Check Mesh Prefabs.asset | 26 + .../Generic/Check Mesh Prefabs.asset.meta | 16 + .../Check Missing Components in Assets.asset | 25 + ...ck Missing Components in Assets.asset.meta | 16 + .../Check Missing Components in Scenes.asset | 25 + ...ck Missing Components in Scenes.asset.meta | 16 + .../Generic/Check Model Import Logs.asset | 26 + .../Check Model Import Logs.asset.meta | 16 + .../Generic/Check Model Orientation.asset | 25 + .../Check Model Orientation.asset.meta | 16 + .../Tests/Generic/Check Model Types.asset | 24 + .../Generic/Check Model Types.asset.meta | 16 + .../Generic/Check Normal Map Textures.asset | 25 + .../Check Normal Map Textures.asset.meta | 16 + .../Tests/Generic/Check Package Naming.asset | 30 + .../Generic/Check Package Naming.asset.meta | 16 + .../Generic/Check Particle Systems.asset | 25 + .../Generic/Check Particle Systems.asset.meta | 16 + .../Tests/Generic/Check Path Lengths.asset | 25 + .../Generic/Check Path Lengths.asset.meta | 16 + .../Generic/Check Prefab Transforms.asset | 28 + .../Check Prefab Transforms.asset.meta | 16 + .../Generic/Check Script Compilation.asset | 25 + .../Check Script Compilation.asset.meta | 16 + .../Generic/Check Shader Compilation.asset | 25 + .../Check Shader Compilation.asset.meta | 16 + .../Generic/Check Texture Dimensions.asset | 25 + .../Check Texture Dimensions.asset.meta | 16 + .../Tests/Generic/Check Type Namespaces.asset | 31 + .../Generic/Check Type Namespaces.asset.meta | 16 + .../Generic/Remove Executable Files.asset | 27 + .../Remove Executable Files.asset.meta | 16 + .../Tests/Generic/Remove JPG Files.asset | 30 + .../Tests/Generic/Remove JPG Files.asset.meta | 16 + .../Generic/Remove JavaScript Files.asset | 25 + .../Remove JavaScript Files.asset.meta | 16 + .../Generic/Remove Lossy Audio Files.asset | 32 + .../Remove Lossy Audio Files.asset.meta | 16 + .../Tests/Generic/Remove Mixamo Files.asset | 26 + .../Generic/Remove Mixamo Files.asset.meta | 16 + .../Generic/Remove SpeedTree Files.asset | 25 + .../Generic/Remove SpeedTree Files.asset.meta | 16 + .../Tests/Generic/Remove Video Files.asset | 26 + .../Generic/Remove Video Files.asset.meta | 16 + .../Editor/Validator/Tests/UnityPackage.meta | 8 + .../UnityPackage/Check Demo Scenes.asset | 34 + .../UnityPackage/Check Demo Scenes.asset.meta | 16 + .../UnityPackage/Check Documentation.asset | 32 + .../Check Documentation.asset.meta | 16 + .../UnityPackage/Check Package Size.asset | 25 + .../Check Package Size.asset.meta | 16 + .../Check Project Template Assets.asset | 36 + .../Check Project Template Assets.asset.meta | 16 + .../com.unity.asset-store-tools/LICENSE.md | 5 + .../LICENSE.md.meta | 14 + .../com.unity.asset-store-tools/package.json | 11 + .../package.json.meta | 14 + Packages/packages-lock.json | 15 + ProjectSettings/ProjectSettings.asset | 3 +- 754 files changed, 32567 insertions(+), 1 deletion(-) create mode 100644 Packages/com.unity.asset-store-tools/CHANGELOG.md create mode 100644 Packages/com.unity.asset-store-tools/CHANGELOG.md.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Constants.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Constants.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef create mode 100644 Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-dark.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-dark.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/open-in-browser.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/open-in-browser.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined_d.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/CategoryEvaluator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset create mode 100644 Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset.meta create mode 100644 Packages/com.unity.asset-store-tools/LICENSE.md create mode 100644 Packages/com.unity.asset-store-tools/LICENSE.md.meta create mode 100644 Packages/com.unity.asset-store-tools/package.json create mode 100644 Packages/com.unity.asset-store-tools/package.json.meta diff --git a/Packages/com.unity.asset-store-tools/CHANGELOG.md b/Packages/com.unity.asset-store-tools/CHANGELOG.md new file mode 100644 index 00000000..d51cbe89 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/CHANGELOG.md @@ -0,0 +1,324 @@ +# Changelog +All notable changes to this package will be documented in this file. + +## [12.0.1] - 2025-01-16 + +### Preview Generator changes +- Updated generated preview collection UI to display the asset extension +- Fixed an issue with some prefab and model asset types not generating previews +- Fixed an error that could occur when changing scenes after deleting a preview source asset + +## [12.0.0] - 2025-01-13 + +### General changes +- The code comprising the Asset Store Publishing Tools has been refactored. +- Added dependency on Newtonsoft Json + +### Uploader changes +- Updated window to retain its state if closed unless a domain reload occurs +- Added option to generate higher resolution asset previews when exporting +- Fixed a rare issue where authentication would fail +- Minor UI tweaks + +### Validator changes +- Added validation tests for: + - Package naming + - Project Template assets +- Updated the Type Namespace validation test to check for Unity top level namespaces + +### Exporter changes +- Updated how asset previews are generated/included for the package that is being exported + +### Preview Generator +- Added a Preview Generator window that can be used to pre-generate and inspect package previews before exporting + +## [11.4.4] - 2024-11-29 + +### Validator Changes +- The validator UI window description section can now be expanded or shrunk to take up less screen space +- Updated severity of the Model Importer Logs validation test + +### Exporter Changes +- Updated exporter to always exclude hidden files and folders beginning with the dot symbol (e.g.: .hiddenFolder/ or .hiddenfile.txt) +- Updated exporter to explicitly exclude extended attribute files when exporting packages on macOS systems + +### Other +- Moved the Asset Store Tools toolbar items into the Tools section +- Fixed several window-related compilation warnings when using Unity 6 versions of the Editor + +## [11.4.3] - 2024-08-01 + +### Validator Changes +- Hotfix: Remove non-ascii characters from the demo scene validation + +## [11.4.2] - 2024-07-30 + +### Validator Changes +- Check for nested .unitypackage files in the demo scene validation +- Prevent normal map test from erroring when misc importer types are detected +- Remove Templates category from the uncompressed images requirement list + +## [11.4.1] - 2024-05-10 + +### Exporter Changes +- Fixed an issue with bundled plugin folder contents not being exported + +### Other +- Miscellaneous internal changes + +## [11.4.0] - 2024-01-23 + +### Uploader Changes +- Added prevention of uploading packages larger than 6 GB +- Added a prompt to allow automatically generating meta files within hidden folders +- Fixed some obsolete API usage warnings in newer Unity versions + +### Validator Changes +- Added validation tests for: + - Animation Clip take names + - Model import logs + - Uncompressed Package size +- Updated the fail severity of Audio Clipping validation test +- Updated the Demo Scene test to treat default scenes with custom skyboxes as valid demo scenes +- Fixed some obsolete API usage warnings in newer Unity versions + +### Other +- Added an option to check for Asset Store Publishing Tools updates + +## [11.3.1] - 2023-08-14 + +### Uploader Changes +- Added the option to select indirect package dependencies from the project (e.g. Mathematics package installed by the Burst package) + +### Validator Changes +- Updated the Texture Dimensions test to ignore 'Sprite' and 'Editor GUI' texture types + +### Exporter Changes +- Updated exporter to ignore the 'ProjectSettings/ProjectVersion.txt' asset when exporting 'Complete Project' category packages + +## [11.3.0] - 2023-07-04 + +### Uploader Changes + +- Added the option to validate a pre-exported package +- Added the option to export a .unitypackage file without uploading +- Updated the dependency selection UI + +### Validator Changes + +- Added the option to validate several asset paths at once + - Note: when validating package that is comprised of several folders (e.g. Assets/MyPackage + + Assets/StreamingAssets + Assets/WebGLTemplates), please select all applicable paths that would be included in the package +- Added several new validation tests for: + - File Menu Names + - Compressed files + - Model Types + - Texture Dimensions + - Particle Systems + - Normal Map Textures + - Audio Clipping + - Path Lengths + - Script Compilation +- Updated validation test severities based on package category +- Updated validation tests to each have their own test logic class +- Updated validation tests to be displayed in alphabetical order +- Fixed several issues with the namespace check test +- Fixed scenes in Samples~ folders not being taken into account for the sample scene check test +- Other internal changes + +### Exporter Changes + +- Package exporter is now a separate module (similar to Uploader and Validator) +- Fixed hidden folders being included when exporting package content + - Note: this prevents an issue with the Unity Editor, where exported hidden folders would appear in the Project window + as empty folders when imported, despite having content on disk. Content nested within hidden folders is still collected, + provided it contains unique .meta files + +## [11.2.2] - 2023-02-23 + +### Validator Changes + +- Updated the 'LOD Setup' test to address some issues + - Added additional checks for LOD renderers (inactive renderer check, LOD Group reference check, relative hierarchy position to LOD Group check) + - LOD Group Component is no longer required to be on the root of the Prefab + - Updated the test result message interface when invalid Prefabs are found + +## [11.2.1] - 2023-01-17 + +### Uploader Changes + +- Added a more informative error when exporting content with clashing guid meta files in hidden folders +- Fixed a compilation issue for Unity 2020.1 and 2020.2 +- Fixed a rare error condition when queueing multiple package uploads in quick succession +- Fixed Asset Store Uploader state not being properly reset if the uploading process fails + +### Validator Changes + +- Updated the Asset Store Validator description +- Fixed a rare memory overflow issue when performing package validation + +## [11.2.0] - 2022-11-03 + +### Uploader Changes + +- Uploader will now use the custom package exporter by default + - An option to use the legacy (native) exporter can be found in the Asset Store Publishing Tools' settings window +- When exporting from the Assets folder, package dependencies can now be selected individually instead of being a choice between 'All' or 'None' + - This option is only available with the custom exporter +- Changed the way the Uploader reports completed uploading tasks + - Modal pop-up has been replaced by a new UI view state + - Added an option to the Asset Store Publishing Tools' Settings to display the pop-up after a completed upload +- Changed exported .unitypackage files to have distinguishable file names +- Fixed the Uploader window indefinitely stalling at 100% upload progress when a response from the Asset Store server is not received +- Fixed native package exporter producing broken packages when the export path contained hidden folders +- Fixed an issue with high CPU usage when uploading packages +- Fixed Asset Store Publishing Tools' settings not being saved between Editor sessions on macOS +- Other minor changes and tweaks + +### Validator Changes + +- Added two new tests: + - 'Types have namespaces': checks whether scripts and native libraries under the validated path are nested under a namespace + - 'Consistent line endings': checks whether scripts under the validated path have consistent line endings. This is similar to the warning from the Unity Editor compilation pipeline when a script contains both Windows and UNIX line endings. +- Improved 'Reset Prefabs' test to display and be more informative about prefabs with unusually low transform values +- Improved 'SpeedTree asset inclusion' test to search for '.st' files +- Improved 'Documentation inclusion' test to treat '.md' files as valid documentation files +- Improved 'Lossy audio file inclusion' test to treat '.aif' and '.aiff' files as valid non-lossy audio files +- Improved 'Lossy audio file inclusion' test to search the project for non-lossy variants of existing lossy audio files +- Removed 'Duplicate animation names' test +- Tweaked validation severities for several tests +- Other minor changes and tweaks + +## [11.1.0] - 2022-09-14 + +### Uploader Changes + +- Package Publisher Portal links can now be opened for all packages regardless of package status +- External Dependency Manager can now be selected as a 'Special Folder' if found in the root Assets folder + +### Validator Changes + +- Added category selection for the Validator + - Categories help determine the outcome of package validation more accurately. For example, documentation is not crucial for art packages, but is required for tooling packages. +- Added a list of prefabs with missing mesh references to 'Meshes have Prefabs' test when the test fails +- Corrected the message for a passing 'Shader compilation errors' test +- Improved the floating point precision accuracy of 'Reset Prefabs' test +- Fixed 'Missing Components in Assets' test checking all project folders instead of only the set path +- Fixed 'Prefabs for meshes' test not checking meshes in certain paths +- Fixed 'Reset Prefabs' test failing because of Prefabs with a Rect Transform Component +- Fixed 'Reset Prefabs' test ignoring Transform rotation +- Fixed test description text overlapping in some cases +- Other minor changes and tweaks + +## [11.0.2] - 2022-08-09 + +- Corrected some namespaces which were causing issues when deriving classes from Editor class + +## [11.0.1] - 2022-08-05 + +### Uploader Changes + +- Added Settings window (Asset Store Tools > Settings) +- Added Soft/Junction Symlink support (enable through Settings) +- Added workflow and path selection serialization (workflow saved locally, paths locally and online) +- No more logs when using the `-nullable` compiler option (thanks @alfish) +- Some API refactoring in preparation for CLI support +- Other minor fixes/improvements + +**Note:** when updating Asset Store Tools from the Package Manager, don't forget to remove the old version from the project (V11.0.0) before importing the new one (V11.0.1) + + +## [11.0.0] - 2022-07-20 + +### Uploader changes + +- UI has been reworked using UI Toolkit +- New login window, allowing to login using Unity Cloud Services +- Improved top bar, including search and sorting +- Draft packages moved to the top +- Added category, size, and last modified date next to the package +- Added a link to the publishing portal next to the package +- New uploading flow: β€œPre-exported .unitypackage” +- Previous uploading flow (folder selection) has been renamed to β€œFrom Assets Folder” +- Dependencies check has been renamed to β€œInclude Package Manifest” for clarity +- Special Folders can now be selected and uploaded together with the package’s main folder (i.e. StreamingAssets, Plugins) +- You can now upload to multiple packages at the same time without waiting for the first one to finish +- Package can now be validated in the Uploading window by pressing the β€œValidate” button +- Added refresh and logout buttons to the bottom toolbar for easier access +- Packages caching - package information will no longer be redownloaded every time you open the Uploader window during the same Editor session +- (Experimental) Custom exporter - will export your package ~2 times faster, but may miss some asset previews in the final product. To enable it - click three dots on the top left side of the window and enable β€œUse Custom Exporting” + + +### Validator changes + +- UI has been reworked using UI Toolkit +- New tests based on the new guidelines +- Updated tests’ titles, descriptions, and error reporting + +## [5.0.5] - 2021-11-04 + +- Fixed namespace issues + +## [5.0.4] - 2020-07-28 + +- Fixed issues with Unity 2020.1 + +## [5.0.3] - 2020-05-07 + +- Remove "Remove Standard Assets" check + +## [5.0.2] - 2020-04-21 + +- Enable auto login with Unity account +- Upload package with thread + +## [5.0.1] - 2020-03-23 + +- Fix domain resolve issue + +## [5.0.0] - 2019-10-09 + +- Added "Package Validator" tool +- Added Help window +- Added logout confirmation popup +- Updated toolbar menu layout +- Removed "Mass Labeler" tool +- Updated layout of Login and Package Upload windows +- Error messages are now more elaborate and user-friendly +- Removed deprecated "Main Assets" step from the Package Upload window +- Package Upload window now has a step for including package manager dependencies +- Tooltips are now added to each upload process step + + +## [4.1.0] - 2018-05-14 + +- Made Tool compatible with 2017.1 + +## [4.0.7] - 2017-07-10 + +- Tweaked menu items. + +## [4.0.6] - 2016-07-15 + +- Improved error messages. + +## [4.0.5] - 2016-03-17 + +- Enabling upload of fbm files. + +## [4.0.4] - 2015-11-16 + +- Login improvements + +## [4.0.3] - 2015-11-16 + +- Prepare the Tools for Unity 5.3 + +## [4.0.2] - 2015-10-23 + +- Fixed issue where Upload button would not work for some projects. +- Fixed issues for publishers that only had one package. + +## [4.0.0] - 2015-09-01 + +- Replaced Package Manager with Package Upload. Package management is now handled by Publisher Administration \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/CHANGELOG.md.meta b/Packages/com.unity.asset-store-tools/CHANGELOG.md.meta new file mode 100644 index 00000000..9ca86c3d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/CHANGELOG.md.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 06607220dbd46414e8f66bf9c5e3eb79 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/CHANGELOG.md + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor.meta b/Packages/com.unity.asset-store-tools/Editor.meta new file mode 100644 index 00000000..8521ad69 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 166da5c6fc70e814a8262463903b2714 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Api.meta b/Packages/com.unity.asset-store-tools/Editor/Api.meta new file mode 100644 index 00000000..0cf8e3fb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d48a2325d352e7a4cae56d3f8eeaab2d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions.meta new file mode 100644 index 00000000..80ccfb13 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 25799fb31cd475347af7f5442c231797 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs new file mode 100644 index 00000000..84d1fa83 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs @@ -0,0 +1,48 @@ +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; + +namespace AssetStoreTools.Api +{ + internal abstract class AuthenticationBase : IAuthenticationType + { + protected Uri LoginUrl = ApiUtility.CreateUri(Constants.Api.AuthenticateUrl, true); + protected FormUrlEncodedContent AuthenticationContent; + + protected FormUrlEncodedContent GetAuthenticationContent(params KeyValuePair[] content) + { + var baseContent = Constants.Api.DefaultAssetStoreQuery(); + + try { baseContent.Add("license_hash", ApiUtility.GetLicenseHash()); } catch { ASDebug.LogWarning("Could not retrieve license hash"); } + try { baseContent.Add("hardware_hash", ApiUtility.GetHardwareHash()); } catch { ASDebug.LogWarning("Could not retrieve hardware hash"); } + + foreach (var extraContent in content) + { + baseContent.Add(extraContent.Key, extraContent.Value); + } + + return new FormUrlEncodedContent(baseContent); + } + + protected AuthenticationResponse ParseResponse(HttpResponseMessage response) + { + try + { + response.EnsureSuccessStatusCode(); + var responseString = response.Content.ReadAsStringAsync().Result; + return new AuthenticationResponse(responseString); + } + catch (HttpRequestException e) + { + return new AuthenticationResponse(response.StatusCode, e) { Success = false }; + } + } + + public abstract Task Authenticate(IAssetStoreClient client, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs.meta new file mode 100644 index 00000000..2607489c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f677e03f1be1048439a1fa5e7a0a37b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/AuthenticationBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs new file mode 100644 index 00000000..86db5cdb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs @@ -0,0 +1,21 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Api.Responses; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal interface IAssetStoreApi + { + Task GetLatestAssetStoreToolsVersion(CancellationToken cancellationToken = default); + Task Authenticate(IAuthenticationType authenticationType, CancellationToken cancellationToken = default); + void Deauthenticate(); + Task GetPackages(CancellationToken cancellationToken = default); + Task GetCategories(CancellationToken cancellationToken = default); + Task GetPackageThumbnail(Package package, CancellationToken cancellationToken = default); + Task RefreshPackageMetadata(Package package, CancellationToken cancellationToken = default); + Task GetPackageUploadedVersions(Package package, CancellationToken cancellationToken = default); + Task UploadPackage(IPackageUploader uploader, IProgress progress = null, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs.meta new file mode 100644 index 00000000..6caa9aaa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e616488c25d278741bb0d08168219309 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreApi.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs new file mode 100644 index 00000000..f6a6d3e1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs @@ -0,0 +1,18 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal interface IAssetStoreClient + { + void SetSessionId(string sessionId); + void ClearSessionId(); + + Task Get(Uri uri, CancellationToken cancellationToken = default); + Task Post(Uri uri, HttpContent content, CancellationToken cancellationToken = default); + Task Put(Uri uri, HttpContent content, CancellationToken cancellationToken = default); + Task Send(HttpRequestMessage request, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs.meta new file mode 100644 index 00000000..eeb360c3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b2bbadec62178cc4189e605367b219e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAssetStoreClient.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs new file mode 100644 index 00000000..8fa5c78e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Api.Responses; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal interface IAuthenticationType + { + Task Authenticate(IAssetStoreClient client, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs.meta new file mode 100644 index 00000000..a713c84f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0000dcd6975bc8e4abc546a19f194040 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IAuthenticationType.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs new file mode 100644 index 00000000..ef7c89f9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs @@ -0,0 +1,12 @@ +using AssetStoreTools.Api.Responses; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal interface IPackageUploader + { + Task Upload(IAssetStoreClient client, IProgress progress, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs.meta new file mode 100644 index 00000000..b8c5fa08 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0fc6c47b1c0a65540a40efbf1491193b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/IPackageUploader.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs new file mode 100644 index 00000000..e26bfc18 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs @@ -0,0 +1,59 @@ +using AssetStoreTools.Api.Responses; +using System; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal abstract class PackageUploaderBase : IPackageUploader + { + protected const int UploadChunkSizeBytes = 32768; + protected const int UploadResponseTimeoutMs = 10000; + + protected abstract void ValidateSettings(); + public abstract Task Upload(IAssetStoreClient client, IProgress progress = null, CancellationToken cancellationToken = default); + + protected void EnsureSuccessResponse(HttpResponseMessage response) + { + try + { + response.EnsureSuccessStatusCode(); + } + catch + { + throw new Exception(response.Content.ReadAsStringAsync().Result); + } + } + + protected void WaitForUploadCompletion(Task response, FileStream requestFileStream, IProgress progress, CancellationToken cancellationToken) + { + // Progress tracking + int updateIntervalMs = 100; + bool allBytesSent = false; + DateTime timeOfCompletion = default; + + while (!response.IsCompleted) + { + float uploadProgress = (float)requestFileStream.Position / requestFileStream.Length * 100; + progress?.Report(uploadProgress); + Thread.Sleep(updateIntervalMs); + + // A timeout for rare cases, when package uploading reaches 100%, but Put task IsComplete value remains 'False' + if (requestFileStream.Position == requestFileStream.Length) + { + if (!allBytesSent) + { + allBytesSent = true; + timeOfCompletion = DateTime.UtcNow; + } + else if (DateTime.UtcNow.Subtract(timeOfCompletion).TotalMilliseconds > UploadResponseTimeoutMs) + { + throw new TimeoutException(); + } + } + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs.meta new file mode 100644 index 00000000..3b255ee9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2718ddd16e425ba4a82ab973724bcff7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Abstractions/PackageUploaderBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs new file mode 100644 index 00000000..545d6d47 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs @@ -0,0 +1,76 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditorInternal; + +namespace AssetStoreTools.Api +{ + internal class ApiUtility + { + public static Uri CreateUri(string url, bool includeDefaultAssetStoreQuery) => CreateUri(url, null, includeDefaultAssetStoreQuery); + public static Uri CreateUri(string url, IDictionary queryParameters, bool includeDefaultAssetStoreQuery) + { + IDictionary fullQueryParameters = includeDefaultAssetStoreQuery ? + Constants.Api.DefaultAssetStoreQuery() : new Dictionary(); + + if (queryParameters != null && queryParameters.Count > 0) + { + foreach (var kvp in queryParameters) + fullQueryParameters.Add(kvp); + } + + var builder = new UriBuilder(url); + if (fullQueryParameters.Count == 0) + return builder.Uri; + + var fullQueryParameterString = string.Empty; + foreach (var queryParam in fullQueryParameters) + { + var escapedValue = queryParam.Value != null ? Uri.EscapeDataString(queryParam.Value) : string.Empty; + fullQueryParameterString += $"{queryParam.Key}={escapedValue}&"; + } + fullQueryParameterString = fullQueryParameterString.Remove(fullQueryParameterString.Length - 1); + + builder.Query = fullQueryParameterString; + return builder.Uri; + } + + public static List CombinePackageData(List mainPackageData, List extraPackageData, List categoryData) + { + foreach (var package in mainPackageData) + { + var extraData = extraPackageData.FirstOrDefault(x => package.PackageId == x.PackageId); + + if (extraData == null) + { + ASDebug.LogWarning($"Could not find extra data for Package {package.PackageId}"); + continue; + } + + var categoryId = extraData.CategoryId; + var category = categoryData.FirstOrDefault(x => x.Id.ToString() == categoryId); + if (category != null) + package.Category = category.Name; + else + package.Category = "Unknown"; + + package.Modified = extraData.Modified; + package.Size = extraData.Size; + } + + return mainPackageData; + } + + public static string GetLicenseHash() + { + return InternalEditorUtility.GetAuthToken().Substring(0, 40); + } + + public static string GetHardwareHash() + { + return InternalEditorUtility.GetAuthToken().Substring(40, 40); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs.meta new file mode 100644 index 00000000..0259bfc3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5becec0b3c0ba274fb0b01544e63b6c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/ApiUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs new file mode 100644 index 00000000..a8530dcc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs @@ -0,0 +1,268 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Api.Responses; +using Newtonsoft.Json.Linq; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class AssetStoreApi : IAssetStoreApi + { + private IAssetStoreClient _client; + + public AssetStoreApi(IAssetStoreClient client) + { + _client = client; + } + + public async Task GetLatestAssetStoreToolsVersion(CancellationToken cancellationToken = default) + { + try + { + var uri = ApiUtility.CreateUri(Constants.Api.AssetStoreToolsLatestVersionUrl, false); + var response = await _client.Get(uri, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + var responseStr = response.Content.ReadAsStringAsync().Result; + return new AssetStoreToolsVersionResponse(responseStr); + } + catch (OperationCanceledException e) + { + return new AssetStoreToolsVersionResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new AssetStoreToolsVersionResponse() { Success = false, Exception = e }; + } + } + + public async Task Authenticate(IAuthenticationType authenticationType, CancellationToken cancellationToken = default) + { + try + { + var loginResponse = await authenticationType.Authenticate(_client, cancellationToken); + if (loginResponse.Success) + { + _client.SetSessionId(loginResponse.User.SessionId); + } + + return loginResponse; + } + catch (OperationCanceledException e) + { + return new AuthenticationResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new AuthenticationResponse() { Success = false, Exception = e }; + } + } + + public void Deauthenticate() + { + _client.ClearSessionId(); + } + + public async Task GetPackages(CancellationToken cancellationToken = default) + { + try + { + var mainDataResponse = await GetPackageDataMain(cancellationToken); + if (!mainDataResponse.Success) + throw mainDataResponse.Exception; + var additionalDataResponse = await GetPackageDataExtra(cancellationToken); + if (!additionalDataResponse.Success) + throw additionalDataResponse.Exception; + var categoryDataResponse = await GetCategories(cancellationToken); + if (!categoryDataResponse.Success) + throw categoryDataResponse.Exception; + + var joinedData = ApiUtility.CombinePackageData(mainDataResponse.Packages, additionalDataResponse.Packages, categoryDataResponse.Categories); + return new PackagesDataResponse() { Success = true, Packages = joinedData }; + } + catch (OperationCanceledException e) + { + return new PackagesDataResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackagesDataResponse() { Success = false, Exception = e }; + } + } + + private async Task GetPackageDataMain(CancellationToken cancellationToken) + { + try + { + var uri = ApiUtility.CreateUri(Constants.Api.GetPackagesUrl, true); + var response = await _client.Get(uri, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + + var responseStr = response.Content.ReadAsStringAsync().Result; + return new PackagesDataResponse(responseStr); + } + catch (OperationCanceledException e) + { + return new PackagesDataResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackagesDataResponse() { Success = false, Exception = e }; + } + } + + private async Task GetPackageDataExtra(CancellationToken cancellationToken) + { + try + { + var uri = ApiUtility.CreateUri(Constants.Api.GetPackagesAdditionalDataUrl, true); + var response = await _client.Get(uri, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + + var responseStr = response.Content.ReadAsStringAsync().Result; + return new PackagesAdditionalDataResponse(responseStr); + } + catch (OperationCanceledException e) + { + return new PackagesAdditionalDataResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackagesAdditionalDataResponse() { Success = false, Exception = e }; + } + } + + public async Task GetCategories(CancellationToken cancellationToken) + { + try + { + var uri = ApiUtility.CreateUri(Constants.Api.GetCategoriesUrl, true); + var response = await _client.Get(uri, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + + var responseStr = response.Content.ReadAsStringAsync().Result; + return new CategoryDataResponse(responseStr); + } + catch (OperationCanceledException e) + { + return new CategoryDataResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new CategoryDataResponse() { Success = false, Exception = e }; + } + } + + public async Task GetPackageThumbnail(Package package, CancellationToken cancellationToken = default) + { + try + { + if (string.IsNullOrEmpty(package.IconUrl)) + throw new Exception($"Could not retrieve thumbnail for package {package.PackageId} - icon url is null"); + + var response = await _client.Get(new Uri(package.IconUrl), cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + + var responseBytes = response.Content.ReadAsByteArrayAsync().Result; + return new PackageThumbnailResponse(responseBytes); + } + catch (OperationCanceledException e) + { + return new PackageThumbnailResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackageThumbnailResponse() { Success = false, Exception = e }; + } + } + + public async Task RefreshPackageMetadata(Package package, CancellationToken cancellationToken = default) + { + try + { + var refreshedPackage = JObject.FromObject(package).DeepClone().ToObject(); + + var packagesResponse = await GetPackageDataExtra(cancellationToken); + if (!packagesResponse.Success) + throw packagesResponse.Exception; + + // Find the updated package data in the latest data json + var packageRefreshSource = packagesResponse.Packages.FirstOrDefault(x => x.PackageId == refreshedPackage.PackageId); + if (packageRefreshSource == null) + return new RefreshedPackageDataResponse() { Success = false, Exception = new MissingMemberException($"Unable to find downloaded package data for package id {package.PackageId}") }; + + // Retrieve the category map + var categoryData = await GetCategories(cancellationToken); + if (!categoryData.Success) + return new RefreshedPackageDataResponse() { Success = false, Exception = packagesResponse.Exception }; + + // Update the package data + refreshedPackage.Name = packageRefreshSource.Name; + refreshedPackage.Status = packageRefreshSource.Status; + var newCategory = categoryData.Categories.FirstOrDefault(x => x.Id.ToString() == packageRefreshSource.CategoryId); + refreshedPackage.Category = newCategory != null ? newCategory.Name : "Unknown"; + refreshedPackage.Modified = packageRefreshSource.Modified; + refreshedPackage.Size = packageRefreshSource.Size; + + return new RefreshedPackageDataResponse() { Success = true, Package = refreshedPackage }; + } + catch (OperationCanceledException) + { + return new RefreshedPackageDataResponse() { Success = false, Cancelled = true }; + } + catch (Exception e) + { + return new RefreshedPackageDataResponse() { Success = false, Exception = e }; + } + } + + public async Task GetPackageUploadedVersions(Package package, CancellationToken cancellationToken = default) + { + try + { + var uri = ApiUtility.CreateUri(Constants.Api.GetPackageUploadedVersionsUrl(package.PackageId, package.VersionId), true); + var response = await _client.Get(uri, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + response.EnsureSuccessStatusCode(); + + var responseStr = response.Content.ReadAsStringAsync().Result; + return new PackageUploadedUnityVersionDataResponse(responseStr); + } + catch (OperationCanceledException e) + { + return new PackageUploadedUnityVersionDataResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackageUploadedUnityVersionDataResponse() { Success = false, Exception = e }; + } + } + + public async Task UploadPackage(IPackageUploader uploader, IProgress progress = null, CancellationToken cancellationToken = default) + { + try + { + return await uploader.Upload(_client, progress, cancellationToken); + } + catch (OperationCanceledException e) + { + return new PackageUploadResponse() { Success = false, Cancelled = true, Exception = e }; + } + catch (Exception e) + { + return new PackageUploadResponse() { Success = false, Exception = e }; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs.meta new file mode 100644 index 00000000..3763396d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 684fca3fffd79d944a32d9b3adbfc007 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreApi.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs new file mode 100644 index 00000000..f71bff81 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs @@ -0,0 +1,55 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class AssetStoreClient : IAssetStoreClient + { + private HttpClient _httpClient; + + public AssetStoreClient() + { + ServicePointManager.DefaultConnectionLimit = 500; + _httpClient = new HttpClient(); + _httpClient.DefaultRequestHeaders.ConnectionClose = false; + _httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); + _httpClient.Timeout = TimeSpan.FromMinutes(1320); + } + + public void SetSessionId(string sessionId) + { + ClearSessionId(); + + if (!string.IsNullOrEmpty(sessionId)) + _httpClient.DefaultRequestHeaders.Add("X-Unity-Session", sessionId); + } + + public void ClearSessionId() + { + _httpClient.DefaultRequestHeaders.Remove("X-Unity-Session"); + } + + public Task Get(Uri uri, CancellationToken cancellationToken = default) + { + return _httpClient.GetAsync(uri, cancellationToken); + } + + public Task Post(Uri uri, HttpContent content, CancellationToken cancellationToken = default) + { + return _httpClient.PostAsync(uri, content, cancellationToken); + } + + public Task Put(Uri uri, HttpContent content, CancellationToken cancellationToken = default) + { + return _httpClient.PutAsync(uri, content, cancellationToken); + } + + public Task Send(HttpRequestMessage request, CancellationToken cancellationToken = default) + { + return _httpClient.SendAsync(request, cancellationToken); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs.meta new file mode 100644 index 00000000..10ea6ae6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 80b4527c908161a4b9f06dc393b502f9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/AssetStoreClient.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs b/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs new file mode 100644 index 00000000..5a1bd5e7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs @@ -0,0 +1,25 @@ +using AssetStoreTools.Api.Responses; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class CloudTokenAuthentication : AuthenticationBase + { + public CloudTokenAuthentication(string cloudToken) + { + AuthenticationContent = GetAuthenticationContent( + new KeyValuePair("user_access_token", cloudToken) + ); + } + + public override async Task Authenticate(IAssetStoreClient client, CancellationToken cancellationToken) + { + var result = await client.Post(LoginUrl, AuthenticationContent, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + + return ParseResponse(result); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs.meta new file mode 100644 index 00000000..06064fcc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 99f1baec74f26a34bb972b19c92d523f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/CloudTokenAuthentication.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs b/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs new file mode 100644 index 00000000..2c515059 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs @@ -0,0 +1,26 @@ +using AssetStoreTools.Api.Responses; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class CredentialsAuthentication : AuthenticationBase + { + public CredentialsAuthentication(string email, string password) + { + AuthenticationContent = GetAuthenticationContent( + new KeyValuePair("user", email), + new KeyValuePair("pass", password) + ); + } + + public override async Task Authenticate(IAssetStoreClient client, CancellationToken cancellationToken) + { + var result = await client.Post(LoginUrl, AuthenticationContent, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + + return ParseResponse(result); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs.meta new file mode 100644 index 00000000..53e59db3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 353e556b63fd441428f387bc85aa612c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/CredentialsAuthentication.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Models.meta new file mode 100644 index 00000000..bfcab0b6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f83e4b5507886f4b873c22c146b8f6a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs new file mode 100644 index 00000000..2cb1298e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs @@ -0,0 +1,58 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Models +{ + internal class Category + { + public int Id { get; set; } + public string Name { get; set; } + public string Status { get; set; } + + public class AssetStoreCategoryResolver : DefaultContractResolver + { + private Dictionary _propertyConversions; + + public AssetStoreCategoryResolver() + { + _propertyConversions = new Dictionary() + { + { nameof(Category.Name), "assetstore_name" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversions.ContainsKey(propertyName)) + return _propertyConversions[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + + public class CachedCategoryResolver : DefaultContractResolver + { + private static CachedCategoryResolver _instance; + public static CachedCategoryResolver Instance => _instance ?? (_instance = new CachedCategoryResolver()); + + private Dictionary _propertyConversion; + + private CachedCategoryResolver() + { + this.NamingStrategy = new SnakeCaseNamingStrategy(); + _propertyConversion = new Dictionary() + { + { nameof(Category.Name), "name" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversion.ContainsKey(propertyName)) + return _propertyConversion[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs.meta new file mode 100644 index 00000000..8a88ac86 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5897866bc65f5834dab1f17371daada7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Models/Category.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs new file mode 100644 index 00000000..442c919d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs @@ -0,0 +1,80 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Models +{ + internal class Package + { + public string PackageId { get; set; } + public string VersionId { get; set; } + public string Name { get; set; } + public string Status { get; set; } + public string Category { get; set; } + public bool IsCompleteProject { get; set; } + public string RootGuid { get; set; } + public string RootPath { get; set; } + public string ProjectPath { get; set; } + public string Modified { get; set; } + public string Size { get; set; } + public string IconUrl { get; set; } + + public class AssetStorePackageResolver : DefaultContractResolver + { + private static AssetStorePackageResolver _instance; + public static AssetStorePackageResolver Instance => _instance ?? (_instance = new AssetStorePackageResolver()); + + private Dictionary _propertyConversions; + + private AssetStorePackageResolver() + { + _propertyConversions = new Dictionary() + { + { nameof(Package.VersionId), "id" }, + { nameof(Package.IsCompleteProject), "is_complete_project" }, + { nameof(Package.RootGuid), "root_guid" }, + { nameof(Package.RootPath), "root_path" }, + { nameof(Package.ProjectPath), "project_path" }, + { nameof(Package.IconUrl), "icon_url" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversions.ContainsKey(propertyName)) + return _propertyConversions[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + + public class CachedPackageResolver : DefaultContractResolver + { + private static CachedPackageResolver _instance; + public static CachedPackageResolver Instance => _instance ?? (_instance = new CachedPackageResolver()); + + private Dictionary _propertyConversion; + + private CachedPackageResolver() + { + this.NamingStrategy = new SnakeCaseNamingStrategy(); + _propertyConversion = new Dictionary() + { + { nameof(Package.PackageId), "package_id" }, + { nameof(Package.VersionId), "version_id" }, + { nameof(Package.IsCompleteProject), "is_complete_project" }, + { nameof(Package.RootGuid), "root_guid" }, + { nameof(Package.RootPath), "root_path" }, + { nameof(Package.IconUrl), "icon_url" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversion.ContainsKey(propertyName)) + return _propertyConversion[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs.meta new file mode 100644 index 00000000..79fb6c2b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7e9f0b99820061b49abf6e8cf544a727 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Models/Package.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs new file mode 100644 index 00000000..8686ccc1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Models +{ + internal class PackageAdditionalData + { + public string Name { get; set; } + public string Status { get; set; } + public string PackageId { get; set; } + public string VersionId { get; set; } + public string CategoryId { get; set; } + public string Modified { get; set; } + public string Size { get; set; } + + public class AssetStorePackageResolver : DefaultContractResolver + { + private static AssetStorePackageResolver _instance; + public static AssetStorePackageResolver Instance => _instance ?? (_instance = new AssetStorePackageResolver()); + + private Dictionary _propertyConversions; + + private AssetStorePackageResolver() + { + _propertyConversions = new Dictionary() + { + { nameof(PackageAdditionalData.PackageId), "id" }, + { nameof(PackageAdditionalData.CategoryId), "category_id" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversions.ContainsKey(propertyName)) + return _propertyConversions[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs.meta new file mode 100644 index 00000000..41f8b1f0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0663f29f3fcd0e34ab77338d1bdbb528 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Models/PackageAdditionalData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs new file mode 100644 index 00000000..c80a5067 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs @@ -0,0 +1,51 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Models +{ + internal class User + { + public string Id { get; set; } + public string SessionId { get; set; } + public string Name { get; set; } + public string Username { get; set; } + public string PublisherId { get; set; } + public bool IsPublisher => !string.IsNullOrEmpty(PublisherId); + + public override string ToString() + { + return + $"{nameof(Id)}: {Id}\n" + + $"{nameof(Name)}: {Name}\n" + + $"{nameof(Username)}: {Username}\n" + + $"{nameof(PublisherId)}: {PublisherId}\n" + + $"{nameof(IsPublisher)}: {IsPublisher}\n" + + $"{nameof(SessionId)}: [HIDDEN]"; + } + + public class AssetStoreUserResolver : DefaultContractResolver + { + private static AssetStoreUserResolver _instance; + public static AssetStoreUserResolver Instance => _instance ?? (_instance = new AssetStoreUserResolver()); + + private Dictionary _propertyConversions; + + private AssetStoreUserResolver() + { + _propertyConversions = new Dictionary() + { + { nameof(User.SessionId), "xunitysession" }, + { nameof(User.PublisherId), "publisher" } + }; + } + + protected override string ResolvePropertyName(string propertyName) + { + if (_propertyConversions.ContainsKey(propertyName)) + return _propertyConversions[propertyName]; + + return base.ResolvePropertyName(propertyName); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs.meta new file mode 100644 index 00000000..76244dac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: caf38df5cd685a345a1ebec8f7651c93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Models/User.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses.meta new file mode 100644 index 00000000..534c529f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 49581213e7b6ca645955cce8ce23ac4b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs new file mode 100644 index 00000000..2e7a6b24 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs @@ -0,0 +1,45 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; + +namespace AssetStoreTools.Api.Responses +{ + ///

+ /// A structure used to return the success outcome and the result of Asset Store API calls + /// + internal class AssetStoreResponse + { + public bool Success { get; set; } = false; + public bool Cancelled { get; set; } = false; + public Exception Exception { get; set; } + + public AssetStoreResponse() { } + + public AssetStoreResponse(Exception e) : this() + { + Exception = e; + } + + protected void ValidateAssetStoreResponse(string json) + { + var dict = JsonConvert.DeserializeObject(json); + if (dict == null) + throw new Exception("Response is empty"); + + // Some json responses return an error field on error + if (dict.ContainsKey("error")) + { + // Server side error message + // Do not write to console since this is an error that + // is "expected" ie. can be handled by the gui. + throw new Exception(dict.GetValue("error").ToString()); + } + // Some json responses return status+message fields instead of an error field. Go figure. + else if (dict.ContainsKey("status") && dict.GetValue("status").ToString() != "ok" + && dict.ContainsKey("message")) + { + throw new Exception(dict.GetValue("message").ToString()); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs.meta new file mode 100644 index 00000000..11f75b6f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ee338db031a0cfb459f7cac7f41a5d75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs new file mode 100644 index 00000000..ec3bb87d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs @@ -0,0 +1,38 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; + +namespace AssetStoreTools.Api.Responses +{ + internal class AssetStoreToolsVersionResponse : AssetStoreResponse + { + public string Version { get; set; } + + public AssetStoreToolsVersionResponse() : base() { } + public AssetStoreToolsVersionResponse(Exception e) : base(e) { } + + public AssetStoreToolsVersionResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + ParseVersion(json); + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + + private void ParseVersion(string json) + { + var dict = JsonConvert.DeserializeObject(json); + if (!dict.ContainsKey("version")) + throw new Exception("Version was not found"); + + Version = dict.GetValue("version").ToString(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs.meta new file mode 100644 index 00000000..64eb6257 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 40558675926f913478a654350149209e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/AssetStoreToolsVersionResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs new file mode 100644 index 00000000..09c786c2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs @@ -0,0 +1,74 @@ +using AssetStoreTools.Api.Models; +using Newtonsoft.Json; +using System; +using System.Net; +using System.Net.Http; + +namespace AssetStoreTools.Api.Responses +{ + internal class AuthenticationResponse : AssetStoreResponse + { + public User User { get; set; } + + public AuthenticationResponse() : base() { } + + public AuthenticationResponse(Exception e) : base(e) { } + + public AuthenticationResponse(HttpStatusCode statusCode, HttpRequestException fallbackException) + { + string message; + switch (statusCode) + { + case HttpStatusCode.Unauthorized: + message = "Incorrect email and/or password. Please try again."; + break; + case HttpStatusCode.InternalServerError: + message = "Authentication request failed\nIf you were logging in with your Unity Cloud account, please make sure you are still logged in.\n" + + "This might also be caused by too many invalid login attempts - if that is the case, please try again later."; + break; + default: + Exception = fallbackException; + return; + } + + Exception = new Exception(message); + } + + public AuthenticationResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = User.AssetStoreUserResolver.Instance + }; + User = JsonConvert.DeserializeObject(json, serializerSettings); + ValidateLoginData(); + ValidatePublisher(); + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + + private void ValidateLoginData() + { + if (string.IsNullOrEmpty(User.Id) + || string.IsNullOrEmpty(User.SessionId) + || string.IsNullOrEmpty(User.Name) + || string.IsNullOrEmpty(User.Username)) + throw new Exception("Could not parse the necessary publisher information from the response."); + } + + private void ValidatePublisher() + { + if (!User.IsPublisher) + throw new Exception($"Your Unity ID {User.Name} is not currently connected to a publisher account. " + + $"Please create a publisher profile."); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs.meta new file mode 100644 index 00000000..a37ebf9b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ec3a5cb59a7e78646b07f800d317874d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/AuthenticationResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs new file mode 100644 index 00000000..4ff740bc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs @@ -0,0 +1,43 @@ +using AssetStoreTools.Api.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Responses +{ + internal class CategoryDataResponse : AssetStoreResponse + { + public List Categories { get; set; } + + public CategoryDataResponse() : base() { } + public CategoryDataResponse(Exception e) : base(e) { } + + public CategoryDataResponse(string json) + { + try + { + var categoryArray = JsonConvert.DeserializeObject(json); + + Categories = new List(); + var serializer = new JsonSerializer() + { + ContractResolver = new Category.AssetStoreCategoryResolver() + }; + + foreach (var categoryData in categoryArray) + { + var category = categoryData.ToObject(serializer); + Categories.Add(category); + } + + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs.meta new file mode 100644 index 00000000..9684d202 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e3789323453f1604286b436f77bdca97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/CategoryDataResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs new file mode 100644 index 00000000..f4e8ac9e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs @@ -0,0 +1,31 @@ +using System; +using UnityEngine; + +namespace AssetStoreTools.Api.Responses +{ + internal class PackageThumbnailResponse : AssetStoreResponse + { + public Texture2D Thumbnail { get; set; } + public PackageThumbnailResponse() : base() { } + public PackageThumbnailResponse(Exception e) : base(e) { } + + public PackageThumbnailResponse(byte[] textureBytes) + { + try + { + var tex = new Texture2D(1, 1, TextureFormat.RGBA32, false); + var success = tex.LoadImage(textureBytes); + if (!success) + throw new Exception("Could not retrieve image from the provided texture bytes"); + + Thumbnail = tex; + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs.meta new file mode 100644 index 00000000..2f957f59 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: dacfba636b3757e408514b850d715e18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageThumbnailResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs new file mode 100644 index 00000000..4f57d645 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Responses +{ + internal class PackageUploadedUnityVersionDataResponse : AssetStoreResponse + { + public List UnityVersions { get; set; } + + public PackageUploadedUnityVersionDataResponse() : base() { } + public PackageUploadedUnityVersionDataResponse(Exception e) : base(e) { } + + public PackageUploadedUnityVersionDataResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + ParseVersionData(json); + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + + private void ParseVersionData(string json) + { + var data = JsonConvert.DeserializeObject(json); + try + { + var content = data.GetValue("content").ToObject(); + UnityVersions = content.GetValue("unity_versions").ToObject>(); + } + catch + { + throw new Exception("Could not parse the unity versions array"); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs.meta new file mode 100644 index 00000000..fa263ee5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2552f659a600e124aa952f3ba760ddf3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackageUploadedUnityVersionDataResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs new file mode 100644 index 00000000..df01e70d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs @@ -0,0 +1,59 @@ +using AssetStoreTools.Api.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Responses +{ + internal class PackagesAdditionalDataResponse : AssetStoreResponse + { + public List Packages { get; set; } + + public PackagesAdditionalDataResponse() : base() { } + public PackagesAdditionalDataResponse(Exception e) : base(e) { } + + public PackagesAdditionalDataResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + ParseExtraData(json); + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + + private void ParseExtraData(string json) + { + var packageDict = JsonConvert.DeserializeObject(json); + if (!packageDict.ContainsKey("packages")) + throw new Exception("Response did not not contain the list of packages"); + + Packages = new List(); + var serializer = new JsonSerializer() + { + ContractResolver = PackageAdditionalData.AssetStorePackageResolver.Instance + }; + + var packageArray = packageDict.GetValue("packages").ToObject(); + foreach (var packageData in packageArray) + { + var package = packageData.ToObject(serializer); + + // Some fields are based on the latest version in the json + var latestVersion = packageData["versions"].ToObject().Last; + + package.VersionId = latestVersion["id"].ToString(); + package.Modified = latestVersion["modified"].ToString(); + package.Size = latestVersion["size"].ToString(); + + Packages.Add(package); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs.meta new file mode 100644 index 00000000..0590efe4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 88d58ad5e0eea6345b5c83f30ee8ebd5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesAdditionalDataResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs new file mode 100644 index 00000000..d9fb47c1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs @@ -0,0 +1,59 @@ +using AssetStoreTools.Api.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Api.Responses +{ + internal class PackagesDataResponse : AssetStoreResponse + { + public List Packages { get; set; } + + public PackagesDataResponse() : base() { } + public PackagesDataResponse(Exception e) : base(e) { } + + public PackagesDataResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + ParseMainData(json); + Success = true; + } + catch (Exception e) + { + Success = false; + Exception = e; + } + } + + private void ParseMainData(string json) + { + var packageDict = JsonConvert.DeserializeObject(json); + if (!packageDict.ContainsKey("packages")) + throw new Exception("Response did not not contain the list of packages"); + + Packages = new List(); + var serializer = new JsonSerializer() + { + ContractResolver = Package.AssetStorePackageResolver.Instance + }; + + foreach (var packageToken in packageDict["packages"]) + { + var property = (JProperty)packageToken; + var packageData = property.Value.ToObject(serializer); + + // Package Id is the key of the package object + packageData.PackageId = property.Name; + + // Package Icon Url is returned without the https: prefix + if (!string.IsNullOrEmpty(packageData.IconUrl)) + packageData.IconUrl = $"https:{packageData.IconUrl}"; + + Packages.Add(packageData); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs.meta new file mode 100644 index 00000000..f780da1d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 705ec748e689148479f54666993cd79d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/PackagesDataResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs new file mode 100644 index 00000000..a0479a03 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs @@ -0,0 +1,12 @@ +using AssetStoreTools.Api.Models; +using System; + +namespace AssetStoreTools.Api.Responses +{ + internal class RefreshedPackageDataResponse : AssetStoreResponse + { + public Package Package { get; set; } + public RefreshedPackageDataResponse() { } + public RefreshedPackageDataResponse(Exception e) : base(e) { } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs.meta new file mode 100644 index 00000000..06075058 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 20f710024d5ed514db02672f12ac361c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/RefreshedPackageDataResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs new file mode 100644 index 00000000..3fa21600 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs @@ -0,0 +1,28 @@ +using System; + +namespace AssetStoreTools.Api.Responses +{ + internal class PackageUploadResponse : AssetStoreResponse + { + public UploadStatus Status { get; set; } + + public PackageUploadResponse() : base() { } + public PackageUploadResponse(Exception e) : base(e) { } + + public PackageUploadResponse(string json) + { + try + { + ValidateAssetStoreResponse(json); + Status = UploadStatus.Success; + Success = true; + } + catch (Exception e) + { + Success = false; + Status = UploadStatus.Fail; + Exception = e; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs.meta new file mode 100644 index 00000000..8b619704 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8f1758cfa8119cf49a61b010a04352e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/Responses/UploadResponse.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs b/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs new file mode 100644 index 00000000..eb5e54cb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs @@ -0,0 +1,25 @@ +using AssetStoreTools.Api.Responses; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class SessionAuthentication : AuthenticationBase + { + public SessionAuthentication(string sessionId) + { + AuthenticationContent = GetAuthenticationContent( + new KeyValuePair("reuse_session", sessionId) + ); + } + + public override async Task Authenticate(IAssetStoreClient client, CancellationToken cancellationToken) + { + var result = await client.Post(LoginUrl, AuthenticationContent, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + + return ParseResponse(result); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs.meta new file mode 100644 index 00000000..ca64f186 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 02e970f660088cc4b89003608d59cd06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/SessionAuthentication.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs b/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs new file mode 100644 index 00000000..17c765f2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs @@ -0,0 +1,99 @@ +using AssetStoreTools.Api.Responses; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Api +{ + internal class UnityPackageUploadSettings + { + public string VersionId { get; set; } + public string UnityPackagePath { get; set; } + public string RootGuid { get; set; } + public string RootPath { get; set; } + public string ProjectPath { get; set; } + } + + internal class UnityPackageUploader : PackageUploaderBase + { + private UnityPackageUploadSettings _settings; + private Uri _uploadUri; + + public UnityPackageUploader(UnityPackageUploadSettings settings) + { + _settings = settings; + } + + protected override void ValidateSettings() + { + if (string.IsNullOrEmpty(_settings.VersionId)) + throw new Exception("Version Id is unset"); + + if (string.IsNullOrEmpty(_settings.UnityPackagePath) + || !File.Exists(_settings.UnityPackagePath)) + throw new Exception("Package file could not be found"); + + if (!_settings.UnityPackagePath.EndsWith(".unitypackage")) + throw new Exception("Provided package file is not .unitypackage"); + } + + public override async Task Upload(IAssetStoreClient client, IProgress progress = null, CancellationToken cancellationToken = default) + { + try + { + ValidateSettings(); + + var endpoint = Constants.Api.UploadUnityPackageUrl(_settings.VersionId); + var query = new Dictionary() + { + { "root_guid", _settings.RootGuid }, + { "root_path", _settings.RootPath }, + { "project_path", _settings.ProjectPath } + }; + + _uploadUri = ApiUtility.CreateUri(endpoint, query, true); + } + catch (Exception e) + { + return new PackageUploadResponse() { Success = false, Status = UploadStatus.Fail, Exception = e }; + } + + return await Task.Run(() => UploadTask(client, progress, cancellationToken)); + } + + private PackageUploadResponse UploadTask(IAssetStoreClient client, IProgress progress, CancellationToken cancellationToken) + { + try + { + using (FileStream requestFileStream = new FileStream(_settings.UnityPackagePath, FileMode.Open, FileAccess.Read)) + { + var content = new StreamContent(requestFileStream, UploadChunkSizeBytes); + + var response = client.Put(_uploadUri, content, cancellationToken); + WaitForUploadCompletion(response, requestFileStream, progress, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + EnsureSuccessResponse(response.Result); + + var responseStr = response.Result.Content.ReadAsStringAsync().Result; + return new PackageUploadResponse(responseStr); + } + } + catch (OperationCanceledException e) + { + return new PackageUploadResponse() { Success = false, Cancelled = true, Status = UploadStatus.Cancelled, Exception = e }; + } + catch (TimeoutException e) + { + return new PackageUploadResponse() { Success = true, Status = UploadStatus.ResponseTimeout, Exception = e }; + } + catch (Exception e) + { + return new PackageUploadResponse() { Success = false, Exception = e, Status = UploadStatus.Fail }; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs.meta new file mode 100644 index 00000000..cdc262ae --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 95bd0284375397f41a2065e07d4ba526 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/UnityPackageUploader.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs b/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs new file mode 100644 index 00000000..cc3adf44 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs @@ -0,0 +1,11 @@ +namespace AssetStoreTools.Api +{ + internal enum UploadStatus + { + Default = 0, + Success = 1, + Fail = 2, + Cancelled = 3, + ResponseTimeout = 4 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs.meta new file mode 100644 index 00000000..83a03101 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0a121831a941cb64a8a9d21ca6fda9c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Api/UploadStatus.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs b/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs new file mode 100644 index 00000000..81fbd086 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("AssetStoreTools.Tests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] +[assembly: InternalsVisibleTo("ab-builder")] +[assembly: InternalsVisibleTo("Inspector-Editor")] diff --git a/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs.meta b/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs.meta new file mode 100644 index 00000000..e3d24b45 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ccfd7faf75ab3c74a98015e772288d86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/AssemblyInfo.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs b/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs new file mode 100644 index 00000000..373ac329 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs @@ -0,0 +1,82 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.UI; +using AssetStoreTools.Uploader; +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.UI; +using System; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools +{ + internal static class AssetStoreTools + { + [MenuItem("Tools/Asset Store/Uploader", false, 0)] + public static void ShowAssetStoreToolsUploader() + { + Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll"); + var wnd = EditorWindow.GetWindow(inspectorType); + wnd.Show(); + } + + [MenuItem("Tools/Asset Store/Validator", false, 1)] + public static void ShowAssetStoreToolsValidator() + { + Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll"); + var wnd = EditorWindow.GetWindow(typeof(UploaderWindow), inspectorType); + wnd.Show(); + } + + public static void ShowAssetStoreToolsValidator(ValidationSettings settings, ValidationResult result) + { + ShowAssetStoreToolsValidator(); + EditorWindow.GetWindow().Load(settings, result); + } + + [MenuItem("Tools/Asset Store/Preview Generator", false, 2)] + public static void ShowAssetStoreToolsPreviewGenerator() + { + Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll"); + var wnd = EditorWindow.GetWindow(inspectorType); + wnd.Show(); + } + + public static void ShowAssetStoreToolsPreviewGenerator(PreviewGenerationSettings settings) + { + ShowAssetStoreToolsPreviewGenerator(); + EditorWindow.GetWindow().Load(settings); + } + + [MenuItem("Tools/Asset Store/Publisher Portal", false, 20)] + public static void OpenPublisherPortal() + { + Application.OpenURL("https://publisher.unity.com/"); + } + + [MenuItem("Tools/Asset Store/Submission Guidelines", false, 21)] + public static void OpenSubmissionGuidelines() + { + Application.OpenURL("https://assetstore.unity.com/publishing/submission-guidelines/"); + } + + [MenuItem("Tools/Asset Store/Provide Feedback", false, 22)] + public static void OpenFeedback() + { + Application.OpenURL("https://forum.unity.com/threads/new-asset-store-tools-version-coming-july-20th-2022.1310939/"); + } + + [MenuItem("Tools/Asset Store/Check for Updates", false, 45)] + public static void OpenUpdateChecker() + { + var wnd = EditorWindow.GetWindowWithRect(new Rect(Screen.width / 2, Screen.height / 2, 400, 150), true); + wnd.Show(); + } + + [MenuItem("Tools/Asset Store/Settings", false, 50)] + public static void OpenSettings() + { + ASToolsPreferencesProvider.OpenSettings(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs.meta b/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs.meta new file mode 100644 index 00000000..1d99f813 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6060eef206afc844caaa1732538e8890 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/AssetStoreTools.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs b/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs new file mode 100644 index 00000000..43f3c117 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs @@ -0,0 +1,23 @@ +ο»Ώusing UnityEditor; +using UnityEngine; + +namespace AssetStoreTools +{ + internal abstract class AssetStoreToolsWindow : EditorWindow + { + protected abstract string WindowTitle { get; } + + private void DefaultInit() + { + titleContent = new GUIContent(WindowTitle); + Init(); + } + + protected abstract void Init(); + + private void OnEnable() + { + DefaultInit(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs.meta new file mode 100644 index 00000000..2dc3a121 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c1057a05baaa45942808573065c02a03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/AssetStoreToolsWindow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Constants.cs b/Packages/com.unity.asset-store-tools/Editor/Constants.cs new file mode 100644 index 00000000..d2c777a7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Constants.cs @@ -0,0 +1,178 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; + +namespace AssetStoreTools +{ + internal class Constants + { +#if UNITY_EDITOR_OSX + public static readonly string UnityPath = System.IO.Path.Combine(EditorApplication.applicationPath, "Contents", "MacOS", "Unity"); +#else + public static readonly string UnityPath = EditorApplication.applicationPath; +#endif + public static readonly string RootProjectPath = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length); + + private static bool GetArgument(string argumentName, out string argumentValue) + { + argumentValue = string.Empty; + var args = Environment.GetCommandLineArgs(); + + for (int i = 0; i < args.Length; i++) + { + if (!args[i].Equals(argumentName, StringComparison.OrdinalIgnoreCase)) + continue; + + if (i + 1 >= args.Length) + return false; + + argumentValue = args[i + 1]; + break; + } + + return !string.IsNullOrEmpty(argumentValue); + } + + public class Api + { + public static readonly string ApiVersion = $"V{PackageInfo.FindForAssetPath("Packages/com.unity.asset-store-tools").version}"; + public const string AssetStoreToolsLatestVersionUrl = "https://api.assetstore.unity3d.com/package/latest-version/115"; + + private const string AssetStoreBaseUrlDefault = "https://kharma.unity3d.com"; + private const string AssetStoreBaseUrlOverrideArgument = "-assetStoreUrl"; + public static readonly string AssetStoreBaseUrl = !GetArgument(AssetStoreBaseUrlOverrideArgument, out var overriddenUrl) + ? AssetStoreBaseUrlDefault + : overriddenUrl; + + public static readonly string AuthenticateUrl = $"{AssetStoreBaseUrl}/login"; + public static readonly string GetPackagesUrl = $"{AssetStoreBaseUrl}/api/asset-store-tools/metadata/0.json"; + public static readonly string GetPackagesAdditionalDataUrl = $"{AssetStoreBaseUrl}/api/management/packages.json"; + public static readonly string GetCategoriesUrl = $"{AssetStoreBaseUrl}/api/management/categories.json"; + + public static string GetPackageUploadedVersionsUrl(string packageId, string versionId) => + $"{AssetStoreBaseUrl}/api/content/preview/{packageId}/{versionId}.json"; + public static string UploadUnityPackageUrl(string versionId) => + $"{AssetStoreBaseUrl}/api/asset-store-tools/package/{versionId}/unitypackage.json"; + + public static IDictionary DefaultAssetStoreQuery() + { + var dict = new Dictionary() + { + { "unityversion", Application.unityVersion }, + { "toolversion", ApiVersion } + }; + return dict; + } + } + + public class Updater + { + public const string AssetStoreToolsUrl = "https://assetstore.unity.com/packages/tools/utilities/asset-store-publishing-tools-115"; + } + + public class Cache + { + public const string SessionTokenKey = "kharma.sessionid"; + public const string TempCachePath = "Temp/AssetStoreToolsCache"; + public const string PersistentCachePath = "Library/AssetStoreToolsCache"; + + public const string PackageDataFileName = "PackageMetadata.json"; + public const string CategoryDataFile = "Categories.json"; + public const string ValidationResultFile = "ValidationStateData.asset"; + + public static string PackageThumbnailFileName(string packageId) => $"{packageId}.png"; + public static string WorkflowStateDataFileName(string packageId) => $"{packageId}-workflowStateData.asset"; + } + + public class Uploader + { + public const string MinRequiredUnitySupportVersion = "2021.3"; + public const long MaxPackageSizeBytes = 6576668672; // 6 GB + 128MB of headroom + public const string AccountRegistrationUrl = "https://publisher.unity.com/access"; + public const string AccountForgottenPasswordUrl = "https://id.unity.com/password/new"; + + public class Analytics + { + public const string VendorKey = "unity.assetStoreTools"; + public const int MaxEventsPerHour = 20; + public const int MaxNumberOfElements = 1000; + + public class AuthenticationAnalytics + { + public const string EventName = "assetStoreToolsLogin"; + public const int EventVersion = 1; + } + + public class PackageUploadAnalytics + { + public const string EventName = "assetStoreTools"; + public const int EventVersion = 3; + } + } + } + + public class Validator + { + public const string SubmissionGuidelinesUrl = "https://assetstore.unity.com/publishing/submission-guidelines#Overview"; + public const string SupportTicketUrl = "https://support.unity.com/hc/en-us/requests/new?ticket_form_id=65905"; + + public class Tests + { + public const string TestDefinitionsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Tests"; + public const string TestMethodsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods"; + + public static readonly string GenericTestMethodsPath = $"{TestMethodsPath}/Generic"; + public static readonly string UnityPackageTestMethodsPath = $"{TestMethodsPath}/UnityPackage"; + } + } + + public class Previews + { + public const string PreviewDatabaseFile = "PreviewDatabase.json"; + + public static readonly string DefaultOutputPath = $"{Cache.TempCachePath}/AssetPreviews"; + public const FileNameFormat DefaultFileNameFormat = FileNameFormat.Guid; + + public class Native + { + public static readonly string DefaultOutputPath = $"{Previews.DefaultOutputPath}/Native"; + public const PreviewFormat DefaultFormat = PreviewFormat.PNG; + public const bool DefaultWaitForPreviews = true; + public const bool DefaultChunkedPreviewLoading = true; + public const int DefaultChunkSize = 100; + } + + public class Custom + { + public static readonly string DefaultOutputPath = $"{Previews.DefaultOutputPath}/Custom"; + public const PreviewFormat DefaultFormat = PreviewFormat.JPG; + public const int DefaultWidth = 300; + public const int DefaultHeight = 300; + public const int DefaultDepth = 32; + + public const int DefaultNativeWidth = 900; + public const int DefaultNativeHeight = 900; + + public static readonly Color DefaultAudioSampleColor = new Color(1f, 0.55f, 0); + public static readonly Color DefaultAudioBackgroundColor = new Color(0.32f, 0.32f, 0.32f); + } + } + + public class WindowStyles + { + public const string UploaderStylesPath = "Packages/com.unity.asset-store-tools/Editor/Uploader/Styles"; + public const string ValidatorStylesPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Styles"; + public const string ValidatorIconsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Icons"; + public const string PreviewGeneratorStylesPath = "Packages/com.unity.asset-store-tools/Editor/Previews/Styles"; + public const string UpdaterStylesPath = "Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater"; + } + + public class Debug + { + public const string DebugModeKey = "ASTDebugMode"; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Constants.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Constants.cs.meta new file mode 100644 index 00000000..9fa06571 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Constants.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a4ee1f78505bda748ae24b3dfd2606ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Constants.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter.meta new file mode 100644 index 00000000..4e1143b8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f5ca981958937a43997a9f365759edf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions.meta new file mode 100644 index 00000000..ac18e6c5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2072d354c04b19c48b22593536b3ebcf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs new file mode 100644 index 00000000..0201a8ea --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace AssetStoreTools.Exporter +{ + internal interface IPackageExporter + { + PackageExporterSettings Settings { get; } + + Task Export(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs.meta new file mode 100644 index 00000000..2285d4b7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 41bc3a111ed1fd64c8b9acef211d9e51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPackageExporter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs new file mode 100644 index 00000000..ba503d8d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs @@ -0,0 +1,7 @@ +ο»Ώnamespace AssetStoreTools.Exporter +{ + internal interface IPreviewInjector + { + void Inject(string temporaryPackagePath); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs.meta new file mode 100644 index 00000000..7f4182ed --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: dcff58dc716351f43b2709cfacdfebba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/IPreviewInjector.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs new file mode 100644 index 00000000..885a188b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs @@ -0,0 +1,134 @@ +ο»Ώusing AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; + +namespace AssetStoreTools.Exporter +{ + internal abstract class PackageExporterBase : IPackageExporter + { + public PackageExporterSettings Settings { get; private set; } + + public const string ProgressBarTitle = "Exporting Package"; + public const string ProgressBarStepSavingAssets = "Saving Assets..."; + public const string ProgressBarStepGatheringFiles = "Gathering files..."; + public const string ProgressBarStepGeneratingPreviews = "Generating previews..."; + public const string ProgressBarStepCompressingPackage = "Compressing package..."; + + private static readonly string[] PluginFolderExtensions = { "androidlib", "bundle", "plugin", "framework", "xcframework" }; + + public PackageExporterBase(PackageExporterSettings settings) + { + Settings = settings; + } + + public async Task Export() + { + try + { + ValidateSettings(); + } + catch (Exception e) + { + return new PackageExporterResult() { Success = false, Exception = e }; + } + + return await ExportImpl(); + } + + protected virtual void ValidateSettings() + { + if (Settings == null) + throw new ArgumentException("Settings cannot be null"); + + if (string.IsNullOrEmpty(Settings.OutputFilename)) + throw new ArgumentException("Output path cannot be null"); + + if (Settings.OutputFilename.EndsWith("/") || Settings.OutputFilename.EndsWith("\\")) + throw new ArgumentException("Output path must be a valid filename and not end with a directory separator character"); + } + + protected abstract Task ExportImpl(); + + protected string[] GetAssetPaths(string rootPath) + { + // To-do: slight optimization is possible in the future by having a list of excluded folders/file extensions + List paths = new List(); + + // Add files within given directory + var filePaths = Directory.GetFiles(rootPath).Select(p => p.Replace('\\', '/')).ToArray(); + paths.AddRange(filePaths); + + // Add directories within given directory + var directoryPaths = Directory.GetDirectories(rootPath).Select(p => p.Replace('\\', '/')).ToArray(); + foreach (var nestedDirectory in directoryPaths) + paths.AddRange(GetAssetPaths(nestedDirectory)); + + // Add the given directory itself if it is not empty + if (filePaths.Length > 0 || directoryPaths.Length > 0) + paths.Add(rootPath); + + return paths.ToArray(); + } + + protected string GetAssetGuid(string assetPath, bool generateIfPlugin, bool scrapeFromMeta) + { + if (!FileUtility.ShouldHaveMeta(assetPath)) + return string.Empty; + + // Skip ProjectVersion.txt file specifically as it may introduce + // project compatibility issues when imported + if (string.Compare(assetPath, "ProjectSettings/ProjectVersion.txt", StringComparison.OrdinalIgnoreCase) == 0) + return string.Empty; + + // Attempt retrieving guid from the Asset Database first + var guid = AssetDatabase.AssetPathToGUID(assetPath); + if (guid != string.Empty) + return guid; + + // Some special folders (e.g. SomeName.framework) do not have meta files inside them. + // Their contents should be exported with any arbitrary GUID so that Unity Importer could pick them up + if (generateIfPlugin && PathBelongsToPlugin(assetPath)) + return GUID.Generate().ToString(); + + // Files in hidden folders (e.g. Samples~) are not part of the Asset Database, + // therefore GUIDs need to be scraped from the .meta file. + // Note: only do this for non-native exporter since the native exporter + // will not be able to retrieve the asset path from a hidden folder + if (scrapeFromMeta) + { + var metaPath = $"{assetPath}.meta"; + + if (!File.Exists(metaPath)) + return string.Empty; + + using (StreamReader reader = new StreamReader(metaPath)) + { + string line; + while ((line = reader.ReadLine()) != string.Empty) + { + if (!line.StartsWith("guid:")) + continue; + var metaGuid = line.Substring("guid:".Length).Trim(); + return metaGuid; + } + } + } + + return string.Empty; + } + + private bool PathBelongsToPlugin(string assetPath) + { + return PluginFolderExtensions.Any(extension => assetPath.ToLower().Contains($".{extension}/")); + } + + protected virtual void PostExportCleanup() + { + EditorUtility.ClearProgressBar(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs.meta new file mode 100644 index 00000000..da3072cc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: aab20a0b596e60b40b1f7f7e0f54858e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs new file mode 100644 index 00000000..6197ba56 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs @@ -0,0 +1,7 @@ +ο»Ώnamespace AssetStoreTools.Exporter +{ + internal abstract class PackageExporterSettings + { + public string OutputFilename; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs.meta new file mode 100644 index 00000000..d6041f44 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 82c350daaabdc784e95e09cdc8511e23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/Abstractions/PackageExporterSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs new file mode 100644 index 00000000..82a10ac1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Previews.Generators; + +namespace AssetStoreTools.Exporter +{ + internal class DefaultExporterSettings : PackageExporterSettings + { + public string[] ExportPaths; + public string[] Dependencies; + public IPreviewGenerator PreviewGenerator; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs.meta new file mode 100644 index 00000000..4f784d27 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 92cbd0e60b4bb9049bcf1e9fd92ccae6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultExporterSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs new file mode 100644 index 00000000..c8d6c428 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs @@ -0,0 +1,304 @@ +ο»Ώusing AssetStoreTools.Previews.Data; +using AssetStoreTools.Utility; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using CacheConstants = AssetStoreTools.Constants.Cache; + +namespace AssetStoreTools.Exporter +{ + internal class DefaultPackageExporter : PackageExporterBase + { + private const string TemporaryExportPathName = "CustomExport"; + + private DefaultExporterSettings _defaultExportSettings; + + public DefaultPackageExporter(DefaultExporterSettings settings) : base(settings) + { + _defaultExportSettings = settings; + } + + protected override void ValidateSettings() + { + base.ValidateSettings(); + + if (_defaultExportSettings.ExportPaths == null || _defaultExportSettings.ExportPaths.Length == 0) + throw new ArgumentException("Export paths array cannot be empty"); + } + + protected override async Task ExportImpl() + { + return await this.Export(); + } + + private new async Task Export() + { + ASDebug.Log("Using custom package exporter"); + + // Save assets before exporting + EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepSavingAssets, 0.1f); + AssetDatabase.SaveAssets(); + + try + { + // Create a temporary export path + PostExportCleanup(); + var temporaryExportPath = GetTemporaryExportPath(); + if (!Directory.Exists(temporaryExportPath)) + Directory.CreateDirectory(temporaryExportPath); + + // Construct an unzipped package structure + CreateTempPackageStructure(temporaryExportPath); + + var previewGenerationResult = await GeneratePreviews(); + InjectPreviews(previewGenerationResult, temporaryExportPath); + + // Build a .unitypackage file from the temporary folder + CreateUnityPackage(temporaryExportPath, _defaultExportSettings.OutputFilename); + + EditorUtility.RevealInFinder(_defaultExportSettings.OutputFilename); + + ASDebug.Log($"Package file has been created at {_defaultExportSettings.OutputFilename}"); + return new PackageExporterResult() { Success = true, ExportedPath = _defaultExportSettings.OutputFilename, PreviewGenerationResult = previewGenerationResult }; + } + catch (Exception e) + { + return new PackageExporterResult() { Success = false, Exception = e }; + } + finally + { + PostExportCleanup(); + } + } + + private string GetTemporaryExportPath() + { + return $"{CacheConstants.TempCachePath}/{TemporaryExportPathName}"; + } + + private void CreateTempPackageStructure(string tempOutputPath) + { + EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepGatheringFiles, 0.4f); + var pathGuidPairs = GetPathGuidPairs(_defaultExportSettings.ExportPaths); + + foreach (var pair in pathGuidPairs) + { + var originalAssetPath = pair.Key; + var outputAssetPath = $"{tempOutputPath}/{pair.Value}"; + + if (Directory.Exists(outputAssetPath)) + { + var path1 = File.ReadAllText($"{outputAssetPath}/pathname"); + var path2 = originalAssetPath; + throw new InvalidOperationException($"Multiple assets with guid {pair.Value} have been detected " + + $"when exporting the package. Please resolve the guid conflicts and try again:\n{path1}\n{path2}"); + } + + Directory.CreateDirectory(outputAssetPath); + + // Every exported asset has a pathname file + using (StreamWriter writer = new StreamWriter($"{outputAssetPath}/pathname")) + writer.Write(originalAssetPath); + + // Only files (not folders) have an asset file + if (File.Exists(originalAssetPath)) + File.Copy(originalAssetPath, $"{outputAssetPath}/asset"); + + // Most files and folders have an asset.meta file (but ProjectSettings folder assets do not) + if (File.Exists($"{originalAssetPath}.meta")) + File.Copy($"{originalAssetPath}.meta", $"{outputAssetPath}/asset.meta"); + + // To-do: handle previews in hidden folders as they are not part of the AssetDatabase + var previewObject = AssetDatabase.LoadAssetAtPath(originalAssetPath); + if (previewObject == null) + continue; + } + + if (_defaultExportSettings.Dependencies == null || _defaultExportSettings.Dependencies.Length == 0) + return; + + var exportDependenciesDict = new JObject(); + var allRegistryPackages = PackageUtility.GetAllRegistryPackages(); + + foreach (var exportDependency in _defaultExportSettings.Dependencies) + { + var registryPackage = allRegistryPackages.FirstOrDefault(x => x.name == exportDependency); + if (registryPackage == null) + { + // Package is either not from a registry source or does not exist in the project + UnityEngine.Debug.LogWarning($"Found an unsupported Package Manager dependency: {exportDependency}.\n" + + "This dependency is not supported in the project's manifest.json and will be skipped."); + continue; + } + + exportDependenciesDict[registryPackage.name] = registryPackage.version; + } + + if (exportDependenciesDict.Count == 0) + return; + + var exportManifestJson = new JObject(); + exportManifestJson["dependencies"] = exportDependenciesDict; + + var tempManifestDirectoryPath = $"{tempOutputPath}/packagemanagermanifest"; + Directory.CreateDirectory(tempManifestDirectoryPath); + var tempManifestFilePath = $"{tempManifestDirectoryPath}/asset"; + + File.WriteAllText(tempManifestFilePath, exportManifestJson.ToString()); + } + + private Dictionary GetPathGuidPairs(string[] exportPaths) + { + var pathGuidPairs = new Dictionary(); + + foreach (var exportPath in exportPaths) + { + var assetPaths = GetAssetPaths(exportPath); + + foreach (var assetPath in assetPaths) + { + var guid = GetAssetGuid(assetPath, true, true); + if (string.IsNullOrEmpty(guid)) + continue; + + pathGuidPairs.Add(assetPath, guid); + } + } + + return pathGuidPairs; + } + + private async Task GeneratePreviews() + { + if (_defaultExportSettings.PreviewGenerator == null) + return null; + + void ReportProgress(float progress) + { + EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepGeneratingPreviews, progress); + } + + _defaultExportSettings.PreviewGenerator.OnProgressChanged += ReportProgress; + var result = await _defaultExportSettings.PreviewGenerator.Generate(); + _defaultExportSettings.PreviewGenerator.OnProgressChanged -= ReportProgress; + EditorUtility.ClearProgressBar(); + + if (!result.Success) + { + UnityEngine.Debug.LogWarning($"An error was encountered while generating previews. Exported package may be missing previews.\n{result.Exception}"); + } + + return result; + } + + private void InjectPreviews(PreviewGenerationResult result, string temporaryExportPath) + { + if (result == null || !result.Success) + return; + + var injector = new PreviewInjector(result); + injector.Inject(temporaryExportPath); + } + + private void CreateUnityPackage(string pathToArchive, string outputPath) + { + if (Directory.GetDirectories(pathToArchive).Length == 0) + throw new InvalidOperationException("Unable to export package. The specified path is empty"); + + EditorUtility.DisplayProgressBar(ProgressBarTitle, ProgressBarStepCompressingPackage, 0.8f); + + // Archiving process working path will be set to the + // temporary package path so adjust the output path accordingly + if (!Path.IsPathRooted(outputPath)) + outputPath = $"{Application.dataPath.Substring(0, Application.dataPath.Length - "/Assets".Length)}/{outputPath}"; + +#if UNITY_EDITOR_WIN + CreateUnityPackageUniversal(pathToArchive, outputPath); +#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX + CreateUnityPackageOsxLinux(pathToArchive, outputPath); +#endif + } + + private void CreateUnityPackageUniversal(string pathToArchive, string outputPath) + { + var _7zPath = EditorApplication.applicationContentsPath; +#if UNITY_EDITOR_WIN + _7zPath = Path.Combine(_7zPath, "Tools", "7z.exe"); +#elif UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX + _7zPath = Path.Combine(_7zPath, "Tools", "7za"); +#endif + if (!File.Exists(_7zPath)) + throw new FileNotFoundException("Archiving utility was not found in your Unity installation directory"); + + var argumentsTar = $"a -r -ttar -y -bd archtemp.tar ."; + var result = StartProcess(_7zPath, argumentsTar, pathToArchive); + if (result != 0) + throw new Exception("Failed to compress the package"); + + // Create a GZIP archive + var argumentsGzip = $"a -tgzip -bd -y \"{outputPath}\" archtemp.tar"; + result = StartProcess(_7zPath, argumentsGzip, pathToArchive); + if (result != 0) + throw new Exception("Failed to compress the package"); + } + +#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX + private void CreateUnityPackageOsxLinux(string pathToArchive, string outputPath) + { + var tarPath = "/usr/bin/tar"; + + if (!File.Exists(tarPath)) + { + // Fallback to the universal export method + ASDebug.LogWarning("'/usr/bin/tar' executable not found. Falling back to 7za"); + CreateUnityPackageUniversal(pathToArchive, outputPath); + return; + } + + // Create a TAR archive + var arguments = $"-czpf \"{outputPath}\" ."; + var result = StartProcess(tarPath, arguments, pathToArchive); + if (result != 0) + throw new Exception("Failed to compress the package"); + } +#endif + + private int StartProcess(string processPath, string arguments, string workingDirectory) + { + var info = new ProcessStartInfo() + { + FileName = processPath, + Arguments = arguments, + WorkingDirectory = workingDirectory, + CreateNoWindow = true, + UseShellExecute = false + }; + +#if UNITY_EDITOR_OSX + // Prevent OSX-specific archive pollution + info.EnvironmentVariables.Add("COPYFILE_DISABLE", "1"); +#endif + + using (Process process = Process.Start(info)) + { + process.WaitForExit(); + return process.ExitCode; + } + } + + protected override void PostExportCleanup() + { + base.PostExportCleanup(); + + var tempExportPath = GetTemporaryExportPath(); + if (Directory.Exists(tempExportPath)) + Directory.Delete(tempExportPath, true); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs.meta new file mode 100644 index 00000000..76233204 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 32f50122a1b2bc2428cf8fba321e2414 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/DefaultPackageExporter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs new file mode 100644 index 00000000..52a7cadc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs @@ -0,0 +1,8 @@ +namespace AssetStoreTools.Exporter +{ + internal class LegacyExporterSettings : PackageExporterSettings + { + public string[] ExportPaths; + public bool IncludeDependencies; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs.meta new file mode 100644 index 00000000..e87e08c9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c7dea1cfe45989e4eab6fc5fd18c1e10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyExporterSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs new file mode 100644 index 00000000..17200439 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs @@ -0,0 +1,109 @@ +ο»Ώusing AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Exporter +{ + internal class LegacyPackageExporter : PackageExporterBase + { + private const string ExportMethodWithoutDependencies = "UnityEditor.PackageUtility.ExportPackage"; + private const string ExportMethodWithDependencies = "UnityEditor.PackageUtility.ExportPackageAndPackageManagerManifest"; + + private LegacyExporterSettings _legacyExportSettings; + + public LegacyPackageExporter(LegacyExporterSettings settings) : base(settings) + { + _legacyExportSettings = settings; + } + + protected override void ValidateSettings() + { + base.ValidateSettings(); + + if (_legacyExportSettings.ExportPaths == null || _legacyExportSettings.ExportPaths.Length == 0) + throw new ArgumentException("Export paths array cannot be empty"); + } + + protected override async Task ExportImpl() + { + return await this.Export(); + } + + private async new Task Export() + { + ASDebug.Log("Using native package exporter"); + + try + { + var guids = GetGuids(_legacyExportSettings.ExportPaths, out bool onlyFolders); + + if (guids.Length == 0 || onlyFolders) + throw new ArgumentException("Package Exporting failed: provided export paths are empty or only contain empty folders"); + + string exportMethod = ExportMethodWithoutDependencies; + if (_legacyExportSettings.IncludeDependencies) + exportMethod = ExportMethodWithDependencies; + + var split = exportMethod.Split('.'); + var assembly = Assembly.Load(split[0]); // UnityEditor + var typeName = $"{split[0]}.{split[1]}"; // UnityEditor.PackageUtility + var methodName = split[2]; // ExportPackage or ExportPackageAndPackageManagerManifest + + var type = assembly.GetType(typeName); + var method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, + null, new Type[] { typeof(string[]), typeof(string) }, null); + + ASDebug.Log("Invoking native export method"); + + method?.Invoke(null, new object[] { guids, _legacyExportSettings.OutputFilename }); + + // The internal exporter methods are asynchronous, therefore + // we need to wait for exporting to finish before returning + await Task.Run(() => + { + while (!File.Exists(_legacyExportSettings.OutputFilename)) + Thread.Sleep(100); + }); + + ASDebug.Log($"Package file has been created at {_legacyExportSettings.OutputFilename}"); + return new PackageExporterResult() { Success = true, ExportedPath = _legacyExportSettings.OutputFilename }; + } + catch (Exception e) + { + return new PackageExporterResult() { Success = false, Exception = e }; + } + finally + { + PostExportCleanup(); + } + } + + private string[] GetGuids(string[] exportPaths, out bool onlyFolders) + { + var guids = new List(); + onlyFolders = true; + + foreach (var exportPath in exportPaths) + { + var assetPaths = GetAssetPaths(exportPath); + + foreach (var assetPath in assetPaths) + { + var guid = GetAssetGuid(assetPath, false, false); + if (string.IsNullOrEmpty(guid)) + continue; + + guids.Add(guid); + if (onlyFolders == true && (File.Exists(assetPath))) + onlyFolders = false; + } + } + + return guids.ToArray(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs.meta new file mode 100644 index 00000000..61f20571 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3200380dff2de104aa79620e4b41dc70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/LegacyPackageExporter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs new file mode 100644 index 00000000..a0ae7a5d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs @@ -0,0 +1,13 @@ +ο»Ώusing AssetStoreTools.Previews.Data; +using System; + +namespace AssetStoreTools.Exporter +{ + internal class PackageExporterResult + { + public bool Success; + public string ExportedPath; + public PreviewGenerationResult PreviewGenerationResult; + public Exception Exception; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs.meta new file mode 100644 index 00000000..549deb00 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e685b1c322eab4540919d4fc970e812d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/PackageExporterResult.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs b/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs new file mode 100644 index 00000000..69e06da3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs @@ -0,0 +1,41 @@ +using AssetStoreTools.Previews.Data; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace AssetStoreTools.Exporter +{ + internal class PreviewInjector : IPreviewInjector + { + private PreviewGenerationResult _result; + + public PreviewInjector(PreviewGenerationResult result) + { + _result = result; + } + + public void Inject(string temporaryPackagePath) + { + if (_result == null || !_result.Success) + return; + + var previews = _result.Previews.Where(x => x.Type == _result.GenerationType && x.Exists()); + InjectFilesIntoGuidFolders(previews, temporaryPackagePath); + } + + private void InjectFilesIntoGuidFolders(IEnumerable previews, string temporaryPackagePath) + { + foreach (var assetFolder in Directory.EnumerateDirectories(temporaryPackagePath)) + { + var guid = assetFolder.Replace("\\", "/").Split('/').Last(); + var generatedPreview = previews.FirstOrDefault(x => x.Guid.Equals(guid)); + + if (generatedPreview == null) + continue; + + // Note: Unity Importer and Asset Store only operate with .png extensions + File.Copy(generatedPreview.Path, $"{assetFolder}/preview.png", true); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs.meta new file mode 100644 index 00000000..1f7fe2e9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 772db784128e32d4792bb680258c71df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Exporter/PreviewInjector.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews.meta b/Packages/com.unity.asset-store-tools/Editor/Previews.meta new file mode 100644 index 00000000..747d5eb9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 13e8cd63112e52d43a7e65949f0143a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts.meta new file mode 100644 index 00000000..f95e49f0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cbe1aebea6551424997b361fab69f266 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data.meta new file mode 100644 index 00000000..89f1356f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ae99e2e3b5a83d1469110306c96f4c58 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs new file mode 100644 index 00000000..27058752 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +namespace AssetStoreTools.Previews.Data +{ + internal class CustomPreviewGenerationSettings : PreviewGenerationSettings + { + public override GenerationType GenerationType => GenerationType.Custom; + + public int Width; + public int Height; + public int Depth; + + public int NativeWidth; + public int NativeHeight; + + public Color AudioSampleColor; + public Color AudioBackgroundColor; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs.meta new file mode 100644 index 00000000..027edf9a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2ccb1292c1c4ba94cb6f4022ecfdfa50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/CustomPreviewGenerationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs new file mode 100644 index 00000000..cb841a86 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs @@ -0,0 +1,9 @@ +namespace AssetStoreTools.Previews.Data +{ + internal enum FileNameFormat + { + Guid = 0, + FullAssetPath = 1, + AssetName = 2, + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs.meta new file mode 100644 index 00000000..48065984 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 38a1babecfeaf524f98e8d67882acf48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/FileNameFormat.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs new file mode 100644 index 00000000..fef979f7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs @@ -0,0 +1,9 @@ +namespace AssetStoreTools.Previews.Data +{ + internal enum GenerationType + { + Unknown = 0, + Native = 1, + Custom = 2 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs.meta new file mode 100644 index 00000000..310ce823 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 66697a5d16404d948ba3191ddfc60bd9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/GenerationType.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs new file mode 100644 index 00000000..fff204ee --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs @@ -0,0 +1,10 @@ +namespace AssetStoreTools.Previews.Data +{ + internal class NativePreviewGenerationSettings : PreviewGenerationSettings + { + public override GenerationType GenerationType => GenerationType.Native; + public bool WaitForPreviews; + public bool ChunkedPreviewLoading; + public int ChunkSize; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs.meta new file mode 100644 index 00000000..a6119eaa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5b2ef019acae6fe43b5565858e15433a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/NativePreviewGenerationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs new file mode 100644 index 00000000..cabc56c1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.Data +{ + internal class PreviewDatabase + { + public List Previews; + + public PreviewDatabase() + { + Previews = new List(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs.meta new file mode 100644 index 00000000..43055403 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cf8cef28a68324742a7e4b47efc87563 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewDatabase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs new file mode 100644 index 00000000..e68f29a4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs @@ -0,0 +1,8 @@ +namespace AssetStoreTools.Previews.Data +{ + internal enum PreviewFormat + { + JPG = 0, + PNG = 1 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs.meta new file mode 100644 index 00000000..2ffac1dc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0500e4459ebfe8448a13194af49f89fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewFormat.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs new file mode 100644 index 00000000..6fb77911 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs @@ -0,0 +1,14 @@ +ο»Ώusing System; +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.Data +{ + internal class PreviewGenerationResult + { + public GenerationType GenerationType; + public bool Success; + public IEnumerable GeneratedPreviews; + public IEnumerable Previews; + public Exception Exception; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs.meta new file mode 100644 index 00000000..22f1136d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e040f2cdf0177824dacb158b23a63374 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationResult.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs new file mode 100644 index 00000000..920ac139 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs @@ -0,0 +1,12 @@ +namespace AssetStoreTools.Previews.Data +{ + internal abstract class PreviewGenerationSettings + { + public abstract GenerationType GenerationType { get; } + public string[] InputPaths; + public string OutputPath; + public PreviewFormat Format; + public FileNameFormat PreviewFileNamingFormat; + public bool OverwriteExisting; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs.meta new file mode 100644 index 00000000..30ef418e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7e578ae6616505a4795da8f632d63229 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewGenerationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs new file mode 100644 index 00000000..a7ba227e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs @@ -0,0 +1,17 @@ +using System.IO; + +namespace AssetStoreTools.Previews.Data +{ + internal class PreviewMetadata + { + public GenerationType Type; + public string Guid; + public string Name; + public string Path; + + public bool Exists() + { + return File.Exists(Path); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs.meta new file mode 100644 index 00000000..437956a7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4ff6be4e277d8314e921baff52ea25bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Data/PreviewMetadata.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators.meta new file mode 100644 index 00000000..7019d5cb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed651159a2004574789e97726da5090c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom.meta new file mode 100644 index 00000000..cac3d999 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f675855c3d971694785806c0c7a463be +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs new file mode 100644 index 00000000..f46e4062 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom +{ + internal class AudioChannel + { + private int _yMin; + private int _yMax; + + private int _yBaseline; + private int _yAmplitude; + + private List _samples; + + public AudioChannel(int minY, int maxY, List samples) + { + _yMin = minY; + _yMax = maxY; + + _yBaseline = (_yMin + _yMax) / 2; + _yAmplitude = _yMax - _yBaseline; + + _samples = samples; + } + + public IEnumerable GetCoordinateData(int desiredWidth) + { + var coordinates = new List(); + var step = Mathf.RoundToInt((float)_samples.Count / desiredWidth); + + for (int i = 0; i < desiredWidth; i++) + { + var startIndex = i * step; + var endIndex = (i + 1) * step; + var sampleChunk = CreateChunk(startIndex, endIndex); + + if (sampleChunk.Count() == 0) + break; + + DownsampleMax(sampleChunk, out var aboveBaseline, out var belowBaseline); + + var yAboveBaseline = SampleToCoordinate(aboveBaseline); + var yBelowBaseline = SampleToCoordinate(belowBaseline); + + coordinates.Add(new AudioChannelCoordinate(i, _yBaseline, yAboveBaseline, yBelowBaseline)); + } + + // If there weren't enough samples to complete the desired width - fill out the rest with zeroes + for (int i = coordinates.Count; i < desiredWidth; i++) + coordinates.Add(new AudioChannelCoordinate(i, _yBaseline, 0, 0)); + + return coordinates; + } + + private IEnumerable CreateChunk(int startIndex, int endIndex) + { + var chunk = new List(); + for (int i = startIndex; i < endIndex; i++) + { + if (i >= _samples.Count) + break; + + chunk.Add(_samples[i]); + } + + return chunk; + } + + private void DownsampleMax(IEnumerable samples, out float valueAboveBaseline, out float valueBelowBaseline) + { + valueAboveBaseline = 0; + valueBelowBaseline = 0; + + foreach (var sample in samples) + { + if (sample > 0 && sample > valueAboveBaseline) + { + valueAboveBaseline = sample; + continue; + } + + if (sample < 0 && sample < valueBelowBaseline) + { + valueBelowBaseline = sample; + continue; + } + } + } + + private int SampleToCoordinate(float sample) + { + return _yBaseline + (int)(sample * _yAmplitude); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs.meta new file mode 100644 index 00000000..dbbceb38 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 82fab55b08a1be94cb2e18f3feae91ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannel.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs new file mode 100644 index 00000000..1030eed2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs @@ -0,0 +1,18 @@ +namespace AssetStoreTools.Previews.Generators.Custom +{ + internal struct AudioChannelCoordinate + { + public int X { get; private set; } + public int YBaseline { get; private set; } + public int YAboveBaseline { get; private set; } + public int YBelowBaseline { get; private set; } + + public AudioChannelCoordinate(int x, int yBaseline, int yAboveBaseline, int yBelowBaseline) + { + X = x; + YBaseline = yBaseline; + YAboveBaseline = yAboveBaseline; + YBelowBaseline = yBelowBaseline; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs.meta new file mode 100644 index 00000000..5c41aae9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b54462f6af82a2644944d6e4bde23c9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/AudioChannelCoordinate.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters.meta new file mode 100644 index 00000000..91cfc9f9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c07070deed666d54cb72a89a5fcd7ef7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs new file mode 100644 index 00000000..ec7cd578 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters +{ + internal interface ISceneScreenshotter + { + SceneScreenshotterSettings Settings { get; } + + string Screenshot(string outputPath); + string Screenshot(GameObject target, string outputPath); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs.meta new file mode 100644 index 00000000..103f3a0c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 045ac265a792af243918af0849ee2ac8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/ISceneScreenshotter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs new file mode 100644 index 00000000..a4462089 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters +{ + internal class MaterialScreenshotter : SceneScreenshotterBase + { + public MaterialScreenshotter(SceneScreenshotterSettings settings) : base(settings) { } + + public override void PositionCamera(GameObject target) + { + var renderers = target.GetComponentsInChildren(); + if (renderers == null || renderers.Length == 0) + return; + + var bounds = GetGlobalBounds(renderers); + + var materialSphereRadius = bounds.extents.y * 1.1f; + + var angle = Camera.fieldOfView / 2; + var sinAngle = Mathf.Sin(angle * Mathf.Deg2Rad); + var distance = materialSphereRadius / sinAngle; + + Camera.transform.position = new Vector3(bounds.center.x, bounds.center.y + distance, bounds.center.z); + Camera.transform.LookAt(bounds.center); + Camera.transform.RotateAround(bounds.center, Vector3.left, 60); + Camera.transform.RotateAround(bounds.center, Vector3.up, -45); + + Camera.nearClipPlane = 0.01f; + Camera.farClipPlane = 10000; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs.meta new file mode 100644 index 00000000..fc8ef16f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c2bd7b01b0cebeb43a6fbc53377f0ea6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MaterialScreenshotter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs new file mode 100644 index 00000000..6ce59053 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters +{ + internal class MeshScreenshotter : SceneScreenshotterBase + { + public MeshScreenshotter(SceneScreenshotterSettings settings) : base(settings) { } + + public override void PositionCamera(GameObject target) + { + var renderers = target.GetComponentsInChildren(); + if (renderers == null || renderers.Length == 0) + return; + + var bounds = GetGlobalBounds(renderers); + + var encapsulatingSphereDiameter = (bounds.max - bounds.min).magnitude; + var encapsulatingSphereRadius = encapsulatingSphereDiameter / 2; + + var angle = Camera.fieldOfView / 2; + var sinAngle = Mathf.Sin(angle * Mathf.Deg2Rad); + var distance = encapsulatingSphereRadius / sinAngle; + + Camera.transform.position = new Vector3(bounds.center.x, bounds.center.y + distance, bounds.center.z); + Camera.transform.LookAt(bounds.center); + Camera.transform.RotateAround(bounds.center, Vector3.left, 65); + Camera.transform.RotateAround(bounds.center, Vector3.up, 235); + + Camera.nearClipPlane = 0.01f; + Camera.farClipPlane = 10000; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs.meta new file mode 100644 index 00000000..7802999f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f0339d22d91b7c94ebc18b1de6f1e287 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/MeshScreenshotter.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs new file mode 100644 index 00000000..fb289f42 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs @@ -0,0 +1,124 @@ +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters +{ + internal abstract class SceneScreenshotterBase : ISceneScreenshotter + { + public SceneScreenshotterSettings Settings { get; } + + protected Camera Camera => GetCamera(); + private Camera _camera; + + public SceneScreenshotterBase(SceneScreenshotterSettings settings) + { + Settings = settings; + } + + private Camera GetCamera() + { + if (_camera == null) + { +#if UNITY_2022_3_OR_NEWER + _camera = GameObject.FindFirstObjectByType(FindObjectsInactive.Include); +#else + _camera = GameObject.FindObjectOfType(); +#endif + } + + return _camera; + } + + public virtual void ValidateSettings() + { + if (Settings.Width <= 0) + throw new ArgumentException("Width should be larger than 0"); + + if (Settings.Height <= 0) + throw new ArgumentException("Height should be larger than 0"); + + if (Settings.Depth <= 0) + throw new ArgumentException("Depth should be larger than 0"); + + if (Settings.NativeWidth <= 0) + throw new ArgumentException("Native width should be larger than 0"); + + if (Settings.NativeHeight <= 0) + throw new ArgumentException("Native height should be larger than 0"); + } + + public abstract void PositionCamera(GameObject target); + + public string Screenshot(string outputPath) + { + ValidateSettings(); + + var texture = GraphicsUtility.GetTextureFromCamera(Camera, Settings.NativeWidth, Settings.NativeHeight, Settings.Depth); + + if (Settings.Width < Settings.NativeWidth || Settings.Height < Settings.NativeHeight) + texture = GraphicsUtility.ResizeTexture(texture, Settings.Width, Settings.Height); + + var extension = PreviewConvertUtility.ConvertExtension(Settings.Format); + var writtenPath = $"{outputPath}.{extension}"; + var bytes = PreviewConvertUtility.ConvertTexture(texture, Settings.Format); + File.WriteAllBytes(writtenPath, bytes); + + return writtenPath; + } + + public string Screenshot(GameObject target, string outputPath) + { + PositionCamera(target); + PositionLighting(target); + return Screenshot(outputPath); + } + + private void PositionLighting(GameObject target) + { +#if UNITY_2022_3_OR_NEWER + var light = GameObject.FindFirstObjectByType(FindObjectsInactive.Include); +#else + var light = GameObject.FindObjectOfType(); +#endif + light.transform.position = Camera.transform.position; + light.transform.LookAt(target.transform); + light.transform.RotateAround(target.transform.position, Vector3.forward, 60f); + } + + protected Bounds GetGlobalBounds(IEnumerable renderers) + { + var center = Vector3.zero; + + foreach (var renderer in renderers) + { + center += renderer.bounds.center; + } + center /= renderers.Count(); + + var globalBounds = new Bounds(center, Vector3.zero); + + foreach (var renderer in renderers) + { + globalBounds.Encapsulate(renderer.bounds); + } + + return globalBounds; + } + + protected Bounds GetNormalizedBounds(Bounds bounds) + { + var largestExtent = Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z); + var normalizedBounds = new Bounds() + { + center = bounds.center, + extents = new Vector3(largestExtent, largestExtent, largestExtent) + }; + + return normalizedBounds; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs.meta new file mode 100644 index 00000000..bf6bbf07 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ce77aefdce8a37f498d17d73da53d0a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs new file mode 100644 index 00000000..82e0ec1d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs @@ -0,0 +1,16 @@ +using AssetStoreTools.Previews.Data; + +namespace AssetStoreTools.Previews.Generators.Custom.Screenshotters +{ + internal class SceneScreenshotterSettings + { + public int Width; + public int Height; + public int Depth; + + public int NativeWidth; + public int NativeHeight; + + public PreviewFormat Format; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs.meta new file mode 100644 index 00000000..04d76d7d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: aa34806e243bad949892d06dd47295e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/Screenshotters/SceneScreenshotterSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators.meta new file mode 100644 index 00000000..e13d7264 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4bb2dd0960418d4a8d4efd34b92a418 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs new file mode 100644 index 00000000..36a6b215 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs @@ -0,0 +1,15 @@ +using AssetStoreTools.Previews.Data; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class AudioTypeGeneratorSettings : TypeGeneratorSettings + { + public int Width; + public int Height; + + public Color SampleColor; + public Color BackgroundColor; + public PreviewFormat Format; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs.meta new file mode 100644 index 00000000..fbf89c94 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5b7ab1b072d95be4daf221ee23af1c80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypeGeneratorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs new file mode 100644 index 00000000..a0f15453 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs @@ -0,0 +1,207 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class AudioTypePreviewGenerator : TypePreviewGeneratorBase + { + private AudioTypeGeneratorSettings _settings; + private Texture2D _texture; + + public override event Action OnAssetProcessed; + + public AudioTypePreviewGenerator(AudioTypeGeneratorSettings settings) : base(settings) + { + _settings = settings; + } + + public override void ValidateSettings() + { + base.ValidateSettings(); + + if (_settings.Width <= 0) + throw new ArgumentException("Width must be larger than 0"); + + if (_settings.Height <= 0) + throw new ArgumentException("Height must be larger than 0"); + } + + protected override IEnumerable CollectAssets() + { + var assets = new List(); + var materialGuids = AssetDatabase.FindAssets("t:audioclip", Settings.InputPaths); + foreach (var guid in materialGuids) + { + var audioClip = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid)); + + // Skip nested audio clips + if (!AssetDatabase.IsMainAsset(audioClip)) + continue; + + // Skip materials with an error shader + if (!IsLoadTypeSupported(audioClip)) + { + Debug.LogWarning($"Audio clip '{audioClip}' is using a load type which cannot retrieve sample data. Preview will not be generated."); + continue; + } + + assets.Add(audioClip); + } + + return assets; + } + + private bool IsLoadTypeSupported(AudioClip audioClip) + { + if (audioClip.loadType == AudioClipLoadType.DecompressOnLoad) + return true; + + return false; + } + + protected override async Task> GenerateImpl(IEnumerable assets) + { + var generatedPreviews = new List(); + var audioClips = assets.ToList(); + for (int i = 0; i < audioClips.Count; i++) + { + var audioClip = audioClips[i] as AudioClip; + if (audioClip != null) + { + var texture = GenerateAudioClipTexture(audioClip); + + var outputPath = GenerateOutputPathWithExtension(audioClip, _settings.PreviewFileNamingFormat, _settings.Format); + var bytes = PreviewConvertUtility.ConvertTexture(texture, _settings.Format); + File.WriteAllBytes(outputPath, bytes); + generatedPreviews.Add(ObjectToMetadata(audioClip, outputPath)); + } + + OnAssetProcessed?.Invoke(i, audioClips.Count); + await Task.Yield(); + } + + return generatedPreviews; + } + + private Texture2D GenerateAudioClipTexture(AudioClip audioClip) + { + if (!audioClip.LoadAudioData()) + throw new Exception("Could not load audio data"); + + try + { + if (_texture == null) + _texture = new Texture2D(_settings.Width, _settings.Height); + else +#if UNITY_2021_3_OR_NEWER || UNITY_2022_1_OR_NEWER || UNITY_2021_2_OR_NEWER + _texture.Reinitialize(_settings.Width, _settings.Height); +#else + _texture.Resize(_settings.Width, _settings.Height); +#endif + + FillTextureBackground(); + FillTextureForeground(audioClip); + + _texture.Apply(); + return _texture; + } + finally + { + audioClip.UnloadAudioData(); + } + } + + private void FillTextureBackground() + { + for (int i = 0; i < _texture.width; i++) + { + for (int j = 0; j < _texture.height; j++) + { + _texture.SetPixel(i, j, _settings.BackgroundColor); + } + } + } + + private void FillTextureForeground(AudioClip audioClip) + { + var channels = CreateChannels(audioClip); + + for (int i = 0; i < channels.Count; i++) + { + DrawChannel(channels[i]); + } + } + + private List CreateChannels(AudioClip audioClip) + { + var channelSamples = GetChannelSamples(audioClip); + var sectionSize = _texture.height / audioClip.channels; + + var channels = new List(); + + for (int i = 0; i < audioClip.channels; i++) + { + var channelMaxY = (_texture.height - 1) - i * sectionSize; + var channelMinY = _texture.height - (i + 1) * sectionSize; + var channel = new AudioChannel(channelMinY, channelMaxY, channelSamples[i]); + channels.Add(channel); + } + + return channels; + } + + private List> GetChannelSamples(AudioClip audioClip) + { + var channelSamples = new List>(); + var allSamples = new float[audioClip.samples * audioClip.channels]; + + if (!audioClip.GetData(allSamples, 0)) + throw new Exception("Could not retrieve audio samples"); + + for (int i = 0; i < audioClip.channels; i++) + { + var samples = new List(); + var sampleIndex = i; + while (sampleIndex < allSamples.Length) + { + samples.Add(allSamples[sampleIndex]); + sampleIndex += audioClip.channels; + } + + channelSamples.Add(samples); + } + + return channelSamples; + } + + private void DrawChannel(AudioChannel channel) + { + var sectionData = channel.GetCoordinateData(_texture.width); + + foreach (var data in sectionData) + { + DrawVerticalColumn(data.X, data.YBaseline, data.YAboveBaseline, data.YBelowBaseline, _settings.SampleColor); + } + } + + private void DrawVerticalColumn(int x, int yBaseline, int y1, int y2, Color color) + { + _texture.SetPixel(x, yBaseline, color); + + var startIndex = y1 < y2 ? y1 : y2; + var endIndex = y1 < y2 ? y2 : y1; + + for (int i = startIndex; i < endIndex; i++) + { + _texture.SetPixel(x, i, color); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs.meta new file mode 100644 index 00000000..11499cf5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9ddf69bb2dca51a42aff247b3a471bb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/AudioTypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs new file mode 100644 index 00000000..bdd5056b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs @@ -0,0 +1,16 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal interface ITypePreviewGenerator + { + TypeGeneratorSettings Settings { get; } + + event Action OnAssetProcessed; + + Task> Generate(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs.meta new file mode 100644 index 00000000..8069f542 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7d9cd368dc73a23478390ee1332cb0be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ITypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs new file mode 100644 index 00000000..13b44ec5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs @@ -0,0 +1,85 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class MaterialTypePreviewGenerator : TypePreviewGeneratorFromScene + { + public override event Action OnAssetProcessed; + + public MaterialTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { } + + protected override IEnumerable CollectAssets() + { + var assets = new List(); + var materialGuids = AssetDatabase.FindAssets("t:material", Settings.InputPaths); + foreach (var guid in materialGuids) + { + var mat = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid)); + + // Skip nested materials + if (!AssetDatabase.IsMainAsset(mat)) + continue; + + // Skip materials with an error shader + if (IsShaderInvalid(mat.shader)) + { + Debug.LogWarning($"Material '{mat}' is using an erroring shader. Preview will not be generated."); + continue; + } + + assets.Add(mat); + } + + return assets; + } + + protected override async Task> GeneratePreviewsInScene(IEnumerable assets) + { + var generatedPreviews = new List(); + var materials = assets.ToList(); + var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); + + var hasMeshRenderer = sphere.TryGetComponent(out var meshRenderer); + if (!hasMeshRenderer) + throw new Exception($"Could not find a MeshRenderer for {sphere}"); + + for (int i = 0; i < materials.Count; i++) + { + ThrowIfSceneChanged(); + + var material = materials[i] as Material; + + if (material != null) + { + meshRenderer.sharedMaterial = material; + var previewPath = Settings.Screenshotter.Screenshot(sphere, GenerateOutputPathWithoutExtension(material, Settings.PreviewFileNamingFormat)); + if (!string.IsNullOrEmpty(previewPath)) + generatedPreviews.Add(ObjectToMetadata(material, previewPath)); + } + + OnAssetProcessed?.Invoke(i, materials.Count); + await Task.Yield(); + } + + UnityEngine.Object.DestroyImmediate(sphere); + return generatedPreviews; + } + + private bool IsShaderInvalid(Shader shader) + { + if (ShaderUtil.ShaderHasError(shader)) + return true; + + if (!shader.isSupported) + return true; + + return false; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs.meta new file mode 100644 index 00000000..b4edb16a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a4e121bae63a199458e53a523dd18c8c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/MaterialTypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs new file mode 100644 index 00000000..7d97607a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs @@ -0,0 +1,86 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class ModelTypePreviewGenerator : TypePreviewGeneratorFromScene + { + public override event Action OnAssetProcessed; + + public ModelTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { } + + protected override IEnumerable CollectAssets() + { + var models = new List(); + var modelGuids = AssetDatabase.FindAssets("t:model", Settings.InputPaths); + + foreach (var guid in modelGuids) + { + var model = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid)); + + // Skip nested models + if (!AssetDatabase.IsMainAsset(model)) + continue; + + // Skip models without renderers + if (model.GetComponentsInChildren().Length == 0) + continue; + + models.Add(model); + } + + return models; + } + + protected override async Task> GeneratePreviewsInScene(IEnumerable assets) + { + var generatedPreviews = new List(); + var models = assets.ToList(); + var referenceShader = GetDefaultObjectShader(); + + for (int i = 0; i < models.Count; i++) + { + ThrowIfSceneChanged(); + + var model = models[i] as GameObject; + + if (model != null) + { + var go = UnityEngine.Object.Instantiate(model, Vector3.zero, Quaternion.Euler(0, 0, 0)); + ReplaceShaders(go, referenceShader); + + var previewPath = Settings.Screenshotter.Screenshot(go, GenerateOutputPathWithoutExtension(model, Settings.PreviewFileNamingFormat)); + if (!string.IsNullOrEmpty(previewPath)) + generatedPreviews.Add(ObjectToMetadata(model, previewPath)); + + UnityEngine.Object.DestroyImmediate(go); + } + + OnAssetProcessed?.Invoke(i, models.Count); + await Task.Yield(); + } + + return generatedPreviews; + } + + private void ReplaceShaders(GameObject go, Shader shader) + { + var meshRenderers = go.GetComponentsInChildren(); + foreach (var mr in meshRenderers) + { + var materialArray = mr.sharedMaterials; + for (int i = 0; i < materialArray.Length; i++) + { + materialArray[i] = new Material(shader) { color = new Color(0.7f, 0.7f, 0.7f) }; + } + + mr.sharedMaterials = materialArray; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs.meta new file mode 100644 index 00000000..dacc7e3d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fca8a1fa8a211874cb84d3d811a0158c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/ModelTypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs new file mode 100644 index 00000000..f0eeb6b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs @@ -0,0 +1,113 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class PrefabTypePreviewGenerator : TypePreviewGeneratorFromScene + { + public override event Action OnAssetProcessed; + + public PrefabTypePreviewGenerator(TypePreviewGeneratorFromSceneSettings settings) : base(settings) { } + + protected override IEnumerable CollectAssets() + { + var prefabs = new List(); + var prefabGuids = AssetDatabase.FindAssets("t:prefab", Settings.InputPaths); + + foreach (var guid in prefabGuids) + { + var prefab = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid)); + + // Skip nested prefabs + if (!AssetDatabase.IsMainAsset(prefab)) + continue; + + // Skip prefabs without renderers + if (prefab.GetComponentsInChildren().Length == 0) + continue; + + prefabs.Add(prefab); + } + + return prefabs; + } + + protected override async Task> GeneratePreviewsInScene(IEnumerable assets) + { + var generatedPreviews = new List(); + var prefabs = assets.ToList(); + var objectReferenceShader = GetDefaultObjectShader(); + var particleReferenceShader = GetDefaultParticleShader(); + + for (int i = 0; i < prefabs.Count; i++) + { + ThrowIfSceneChanged(); + + var prefab = prefabs[i] as GameObject; + if (prefab != null) + { + var go = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.Euler(0, 0, 0)); + + ReplaceMissingShaders(go, objectReferenceShader, particleReferenceShader); + + HandleParticleSystems(go); + + var previewPath = Settings.Screenshotter.Screenshot(go, GenerateOutputPathWithoutExtension(prefab, Settings.PreviewFileNamingFormat)); + if (!string.IsNullOrEmpty(previewPath)) + generatedPreviews.Add(ObjectToMetadata(prefab, previewPath)); + + UnityEngine.Object.DestroyImmediate(go); + } + + OnAssetProcessed?.Invoke(i, prefabs.Count); + await Task.Yield(); + } + + return generatedPreviews; + } + + private void ReplaceMissingShaders(GameObject go, Shader objectShader, Shader particleShader) + { + var meshRenderers = go.GetComponentsInChildren(); + foreach (var mr in meshRenderers) + { + var shaderToUse = mr is ParticleSystemRenderer ? particleShader : objectShader; + + var materialArray = mr.sharedMaterials; + for (int i = 0; i < materialArray.Length; i++) + { + if (materialArray[i] == null) + { + materialArray[i] = new Material(shaderToUse); + } + else if (!materialArray[i].shader.isSupported) + { + materialArray[i].shader = shaderToUse; + } + } + + mr.sharedMaterials = materialArray; + } + } + + private void HandleParticleSystems(GameObject go) + { + var particleSystems = go.GetComponentsInChildren(); + if (particleSystems.Length == 0) + return; + + foreach (var ps in particleSystems) + { + ps.Stop(); + ps.Clear(); + ps.randomSeed = 1; + ps.Simulate(10, false, true, false); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs.meta new file mode 100644 index 00000000..ce814043 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 24b15b10bc361c84581f46cb6dd644cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/PrefabTypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs new file mode 100644 index 00000000..666b32dd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Previews.Data; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class TextureTypeGeneratorSettings : TypeGeneratorSettings + { + public int MaxWidth; + public int MaxHeight; + public PreviewFormat Format; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs.meta new file mode 100644 index 00000000..09acc0d5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 058d746982619b04eb5e200363003899 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypeGeneratorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs new file mode 100644 index 00000000..24e1102f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs @@ -0,0 +1,116 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class TextureTypePreviewGenerator : TypePreviewGeneratorBase + { + private TextureTypeGeneratorSettings _settings; + + public override event Action OnAssetProcessed; + + public TextureTypePreviewGenerator(TextureTypeGeneratorSettings settings) : base(settings) + { + _settings = settings; + } + + public override void ValidateSettings() + { + base.ValidateSettings(); + + if (_settings.MaxWidth <= 0) + throw new ArgumentException("Max width should be larger than 0"); + + if (_settings.MaxHeight <= 0) + throw new ArgumentException("Max height should be larger than 0"); + } + + protected override IEnumerable CollectAssets() + { + var textures = new List(); + var textureGuids = AssetDatabase.FindAssets("t:texture", Settings.InputPaths); + + foreach (var guid in textureGuids) + { + var texture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid)); + + // Skip nested textures + if (!AssetDatabase.IsMainAsset(texture)) + continue; + + textures.Add(texture); + } + + return textures; + } + + protected override async Task> GenerateImpl(IEnumerable assets) + { + var generatedPreviews = new List(); + var textures = assets.ToList(); + + for (int i = 0; i < textures.Count; i++) + { + var texture = textures[i] as Texture2D; + + if (texture != null) + { + Texture2D resizedTexture; + CalculateTextureSize(texture, out var resizeWidth, out var resizeHeight); + + var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter; + if (importer != null && importer.textureType == TextureImporterType.NormalMap) + resizedTexture = GraphicsUtility.ResizeTextureNormalMap(texture, resizeWidth, resizeHeight); + else + resizedTexture = GraphicsUtility.ResizeTexture(texture, resizeWidth, resizeHeight); + + var previewPath = GenerateOutputPathWithExtension(texture, _settings.PreviewFileNamingFormat, _settings.Format); + + // Some textures may be transparent and need to be encoded as PNG to look correctly + var targetFormat = texture.alphaIsTransparency ? PreviewFormat.PNG : _settings.Format; + var bytes = PreviewConvertUtility.ConvertTexture(resizedTexture, targetFormat); + + File.WriteAllBytes(previewPath, bytes); + generatedPreviews.Add(ObjectToMetadata(texture, previewPath)); + } + + OnAssetProcessed?.Invoke(i, textures.Count); + await Task.Yield(); + } + + return generatedPreviews; + } + + private void CalculateTextureSize(Texture2D texture, out int width, out int height) + { + if (texture.width <= _settings.MaxWidth && texture.height <= _settings.MaxHeight) + { + width = texture.width; + height = texture.height; + return; + } + + var widthLongerThanHeight = texture.width > texture.height; + + if (widthLongerThanHeight) + { + var ratio = (float)texture.width / texture.height; + width = _settings.MaxWidth; + height = Mathf.RoundToInt(width / ratio); + } + else + { + var ratio = (float)texture.height / texture.width; + height = _settings.MaxHeight; + width = Mathf.RoundToInt(height / ratio); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs.meta new file mode 100644 index 00000000..90d58b7a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b04f55867ee575c489803356220feb31 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TextureTypePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs new file mode 100644 index 00000000..1aaaa42d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs @@ -0,0 +1,12 @@ +using AssetStoreTools.Previews.Data; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal abstract class TypeGeneratorSettings + { + public string[] InputPaths; + public string[] IgnoredGuids; + public string OutputPath; + public FileNameFormat PreviewFileNamingFormat; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs.meta new file mode 100644 index 00000000..90f895de --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a224a4b41a8c7cf4cb53dd77d6f2518b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypeGeneratorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs new file mode 100644 index 00000000..a49d9686 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs @@ -0,0 +1,126 @@ +ο»Ώusing AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal abstract class TypePreviewGeneratorBase : ITypePreviewGenerator + { + public TypeGeneratorSettings Settings { get; } + + public abstract event Action OnAssetProcessed; + + public TypePreviewGeneratorBase(TypeGeneratorSettings settings) + { + Settings = settings; + } + + public virtual void ValidateSettings() + { + if (Settings.InputPaths == null || Settings.InputPaths.Length == 0) + throw new ArgumentException("Input path cannot be null"); + + foreach (var path in Settings.InputPaths) + { + var inputPath = path.EndsWith("/") ? path.Remove(path.Length - 1) : path; + if (!AssetDatabase.IsValidFolder(inputPath)) + throw new ArgumentException($"Input path '{inputPath}' is not a valid ADB folder"); + } + + if (string.IsNullOrEmpty(Settings.OutputPath)) + throw new ArgumentException("Output path cannot be null"); + } + + public async Task> Generate() + { + var generatedPreviews = new List(); + ValidateSettings(); + + var assets = CollectAssets(); + assets = FilterIgnoredAssets(assets); + + if (assets.Count() == 0) + return generatedPreviews; + + return await GenerateImpl(assets); + } + + protected abstract IEnumerable CollectAssets(); + + private IEnumerable FilterIgnoredAssets(IEnumerable assets) + { + if (Settings.IgnoredGuids == null || Settings.IgnoredGuids.Length == 0) + return assets; + + var filteredAssets = new List(); + foreach (var asset in assets) + { + if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _)) + continue; + + if (Settings.IgnoredGuids.Any(x => x == guid)) + continue; + + filteredAssets.Add(asset); + } + + return filteredAssets; + } + + protected abstract Task> GenerateImpl(IEnumerable assets); + + protected PreviewMetadata ObjectToMetadata(UnityEngine.Object obj, string previewPath) + { + if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out var guid, out long _)) + throw new Exception($"Could not retrieve guid for object {obj}"); + + return new PreviewMetadata() + { + Type = GenerationType.Custom, + Guid = guid, + Name = obj.name, + Path = previewPath + }; + } + + protected string GenerateOutputPathWithoutExtension(UnityEngine.Object asset, FileNameFormat fileNameFormat) + { + PrepareOutputFolder(Settings.OutputPath, false); + var directoryPath = Settings.OutputPath; + var fileName = PreviewConvertUtility.ConvertFilename(asset, fileNameFormat); + var fullPath = $"{directoryPath}/{fileName}"; + + return fullPath; + } + + protected string GenerateOutputPathWithExtension(UnityEngine.Object asset, FileNameFormat fileNameFormat, PreviewFormat previewFormat) + { + var partialOutputPath = GenerateOutputPathWithoutExtension(asset, fileNameFormat); + var extension = PreviewConvertUtility.ConvertExtension(previewFormat); + + return $"{partialOutputPath}.{extension}"; + } + + private void PrepareOutputFolder(string outputPath, bool cleanup) + { + var dir = new DirectoryInfo(outputPath); + + if (!dir.Exists) + { + dir.Create(); + return; + } + + if (!cleanup) + return; + + dir.Delete(true); + dir.Create(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs.meta new file mode 100644 index 00000000..8b3faa83 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c6fb2d639232bce4698338a252f47f3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs new file mode 100644 index 00000000..f9fe453e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs @@ -0,0 +1,111 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal abstract class TypePreviewGeneratorFromScene : TypePreviewGeneratorBase + { + protected new TypePreviewGeneratorFromSceneSettings Settings; + + private CancellationTokenSource _cancellationTokenSource; + + public TypePreviewGeneratorFromScene(TypePreviewGeneratorFromSceneSettings settings) : base(settings) + { + Settings = settings; + } + + public override void ValidateSettings() + { + base.ValidateSettings(); + + if (Settings.Screenshotter == null) + throw new ArgumentException("Screenshotter cannot be null"); + } + + protected sealed override async Task> GenerateImpl(IEnumerable assets) + { + var originalScenePath = EditorSceneManager.GetActiveScene().path; + await PreviewSceneUtility.OpenPreviewSceneForCurrentPipeline(); + + try + { + _cancellationTokenSource = new CancellationTokenSource(); + EditorSceneManager.sceneOpened += SceneOpenedDuringGeneration; + return await GeneratePreviewsInScene(assets); + } + finally + { + EditorSceneManager.sceneOpened -= SceneOpenedDuringGeneration; + _cancellationTokenSource.Dispose(); + if (!string.IsNullOrEmpty(originalScenePath)) + EditorSceneManager.OpenScene(originalScenePath); + } + } + + protected abstract Task> GeneratePreviewsInScene(IEnumerable assets); + + private void SceneOpenedDuringGeneration(Scene _, OpenSceneMode __) + { + if (!_cancellationTokenSource.IsCancellationRequested) + _cancellationTokenSource.Cancel(); + } + + protected void ThrowIfSceneChanged() + { + if (_cancellationTokenSource.Token.IsCancellationRequested) + throw new Exception("Preview generation was aborted due to a change of the scene"); + } + + protected Shader GetDefaultObjectShader() + { + switch (RenderPipelineUtility.GetCurrentPipeline()) + { + case RenderPipeline.BiRP: + return Shader.Find("Standard"); + case RenderPipeline.URP: + return Shader.Find("Universal Render Pipeline/Lit"); + case RenderPipeline.HDRP: + return Shader.Find("HDRP/Lit"); + default: + throw new NotImplementedException("Undefined Render Pipeline"); + } + } + + protected Shader GetDefaultParticleShader() + { + switch (RenderPipelineUtility.GetCurrentPipeline()) + { + case RenderPipeline.BiRP: + return Shader.Find("Particles/Standard Unlit"); + case RenderPipeline.URP: + return Shader.Find("Universal Render Pipeline/Particles/Unlit"); + case RenderPipeline.HDRP: + return Shader.Find("HDRP/Unlit"); + default: + throw new NotImplementedException("Undefined Render Pipeline"); + } + } + + protected Shader GetDefaultTextureShader() + { + switch (RenderPipelineUtility.GetCurrentPipeline()) + { + case RenderPipeline.BiRP: + return Shader.Find("Unlit/Texture"); + case RenderPipeline.URP: + return Shader.Find("Universal Render Pipeline/Unlit"); + case RenderPipeline.HDRP: + return Shader.Find("HDRP/Unlit"); + default: + throw new NotImplementedException("Undefined Render Pipeline"); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs.meta new file mode 100644 index 00000000..263c5440 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 1bf0eb8d7ef65f340be785dae96e4b73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromScene.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs new file mode 100644 index 00000000..36a2e6e0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs @@ -0,0 +1,9 @@ +using AssetStoreTools.Previews.Generators.Custom.Screenshotters; + +namespace AssetStoreTools.Previews.Generators.Custom.TypeGenerators +{ + internal class TypePreviewGeneratorFromSceneSettings : TypeGeneratorSettings + { + public ISceneScreenshotter Screenshotter; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs.meta new file mode 100644 index 00000000..d51befd5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a6b871798f99ad44d9fca46789239ec1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/Custom/TypeGenerators/TypePreviewGeneratorFromSceneSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs new file mode 100644 index 00000000..7a1ffebc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs @@ -0,0 +1,213 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Generators; +using AssetStoreTools.Previews.Generators.Custom.Screenshotters; +using AssetStoreTools.Previews.Generators.Custom.TypeGenerators; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; + +namespace AssetStoreTools.Previews +{ + internal class CustomPreviewGenerator : PreviewGeneratorBase + { + private CustomPreviewGenerationSettings _customSettings; + + public override event Action OnProgressChanged; + + public CustomPreviewGenerator(CustomPreviewGenerationSettings settings) + : base(settings) + { + _customSettings = settings; + } + + protected override void Validate() + { + base.Validate(); + + if (_customSettings.Width <= 0) + throw new ArgumentException("Width should be larger than 0"); + + if (_customSettings.Height <= 0) + throw new ArgumentException("Height should be larger than 0"); + + if (_customSettings.Depth <= 0) + throw new ArgumentException("Depth should be larger than 0"); + + if (_customSettings.NativeWidth <= 0) + throw new ArgumentException("Native width should be larger than 0"); + + if (_customSettings.NativeHeight <= 0) + throw new ArgumentException("Native height should be larger than 0"); + } + + protected override async Task GenerateImpl() + { + var result = new PreviewGenerationResult() + { + GenerationType = _customSettings.GenerationType + }; + + OnProgressChanged?.Invoke(0f); + + var generatedPreviews = new List(); + var existingPreviews = GetExistingPreviews(); + var generators = CreateGenerators(existingPreviews); + + var currentGenerator = 0; + Action generatorProgressCallback = null; + generatorProgressCallback = (currentAsset, totalAssets) => ReportProgress(currentGenerator, generators.Count(), currentAsset, totalAssets); + + try + { + foreach (var generator in generators) + { + generator.OnAssetProcessed += generatorProgressCallback; + var typeGeneratorPreviews = await generator.Generate(); + generatedPreviews.AddRange(typeGeneratorPreviews); + currentGenerator++; + } + + AssetDatabase.Refresh(); + + var allPreviews = new List(); + allPreviews.AddRange(generatedPreviews); + allPreviews.AddRange(existingPreviews); + + result.Success = true; + result.GeneratedPreviews = generatedPreviews; + result.Previews = allPreviews; + } + catch (Exception e) + { + result.Success = false; + result.Exception = e; + } + finally + { + foreach (var generator in generators) + generator.OnAssetProcessed -= generatorProgressCallback; + } + + return result; + } + + private IEnumerable GetExistingPreviews() + { + var existingPreviews = new List(); + + if (Settings.OverwriteExisting || !CachingService.GetCachedMetadata(out var database)) + return existingPreviews; + + var inputGuids = AssetDatabase.FindAssets("", _customSettings.InputPaths); + existingPreviews = database.Previews.Where(x => x.Type == GenerationType.Custom && x.Exists() && inputGuids.Any(y => y.Equals(x.Guid))).ToList(); + return existingPreviews; + } + + private IEnumerable CreateGenerators(IEnumerable existingPreviews) + { + var ignoredGuids = existingPreviews.Select(x => x.Guid).ToArray(); + + var generators = new ITypePreviewGenerator[] + { + CreateAudioPreviewGenerator(ignoredGuids), + CreateMaterialPreviewGenerator(ignoredGuids), + CreateModelPreviewGenerator(ignoredGuids), + CreatePrefabPreviewGenerator(ignoredGuids), + CreateTexturePreviewGenerator(ignoredGuids) + }; + + return generators; + } + + private ITypePreviewGenerator CreateAudioPreviewGenerator(string[] ignoredGuids) + { + var settings = new AudioTypeGeneratorSettings() + { + Width = _customSettings.Width, + Height = _customSettings.Height, + InputPaths = _customSettings.InputPaths, + OutputPath = _customSettings.OutputPath, + PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat, + Format = _customSettings.Format, + SampleColor = _customSettings.AudioSampleColor, + BackgroundColor = _customSettings.AudioBackgroundColor, + IgnoredGuids = ignoredGuids + }; + + return new AudioTypePreviewGenerator(settings); + } + + private ITypePreviewGenerator CreateMaterialPreviewGenerator(string[] ignoredGuids) + { + var settings = CreateSceneGeneratorSettings(new MaterialScreenshotter(CreateScreenshotterSettings()), ignoredGuids); + return new MaterialTypePreviewGenerator(settings); + } + + private ITypePreviewGenerator CreateModelPreviewGenerator(string[] ignoredGuids) + { + var settings = CreateSceneGeneratorSettings(new MeshScreenshotter(CreateScreenshotterSettings()), ignoredGuids); + return new ModelTypePreviewGenerator(settings); + } + + private ITypePreviewGenerator CreatePrefabPreviewGenerator(string[] ignoredGuids) + { + var settings = CreateSceneGeneratorSettings(new MeshScreenshotter(CreateScreenshotterSettings()), ignoredGuids); + return new PrefabTypePreviewGenerator(settings); + } + + private ITypePreviewGenerator CreateTexturePreviewGenerator(string[] ignoredGuids) + { + var settings = new TextureTypeGeneratorSettings() + { + MaxWidth = _customSettings.Width, + MaxHeight = _customSettings.Height, + InputPaths = _customSettings.InputPaths, + OutputPath = _customSettings.OutputPath, + Format = _customSettings.Format, + PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat, + IgnoredGuids = ignoredGuids + }; + + return new TextureTypePreviewGenerator(settings); + } + + private TypePreviewGeneratorFromSceneSettings CreateSceneGeneratorSettings(ISceneScreenshotter screenshotter, string[] ignoredGuids) + { + var settings = new TypePreviewGeneratorFromSceneSettings() + { + InputPaths = _customSettings.InputPaths, + OutputPath = _customSettings.OutputPath, + PreviewFileNamingFormat = _customSettings.PreviewFileNamingFormat, + Screenshotter = screenshotter, + IgnoredGuids = ignoredGuids + }; + + return settings; + } + + private SceneScreenshotterSettings CreateScreenshotterSettings() + { + var settings = new SceneScreenshotterSettings() + { + Width = _customSettings.Width, + Height = _customSettings.Height, + Depth = _customSettings.Depth, + Format = _customSettings.Format, + NativeWidth = _customSettings.NativeWidth, + NativeHeight = _customSettings.NativeHeight, + }; + + return settings; + } + + private void ReportProgress(int currentGenerator, int totalGenerators, int currentGeneratorAsset, int totalCurrentGeneratorAssets) + { + var completedGeneratorProgress = (float)currentGenerator / totalGenerators; + var currentGeneratorProgress = ((float)currentGeneratorAsset / totalCurrentGeneratorAssets) / totalGenerators; + var progressToReport = completedGeneratorProgress + currentGeneratorProgress; + OnProgressChanged?.Invoke(progressToReport); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs.meta new file mode 100644 index 00000000..4b18db3b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e5906f8cb3e4eec489a2f7a82844bb3f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/CustomPreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs new file mode 100644 index 00000000..b548bafb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs @@ -0,0 +1,15 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Threading.Tasks; + +namespace AssetStoreTools.Previews.Generators +{ + internal interface IPreviewGenerator + { + PreviewGenerationSettings Settings { get; } + + event Action OnProgressChanged; + + Task Generate(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs.meta new file mode 100644 index 00000000..c7178a8d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ebddaccb94ca6e34aa36b535d0a47249 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/IPreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs new file mode 100644 index 00000000..760e2d14 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs @@ -0,0 +1,362 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using UnityEngine.Tilemaps; + +namespace AssetStoreTools.Previews.Generators +{ + internal class NativePreviewGenerator : PreviewGeneratorBase + { + private const double InitialPreviewLoadingTimeoutSeconds = 10; + + private NativePreviewGenerationSettings _nativeSettings; + + private RenderTexture _renderTexture; + + private int _generatedPreviewsCount; + private int _totalPreviewsCount; + + public override event Action OnProgressChanged; + + public NativePreviewGenerator(NativePreviewGenerationSettings settings) + : base(settings) + { + _nativeSettings = settings; + } + + protected override void Validate() + { + base.Validate(); + + if (_nativeSettings.ChunkSize <= 0) + throw new ArgumentException("Chunk size must be larger than 0"); + } + + protected override async Task GenerateImpl() + { + var result = new PreviewGenerationResult() + { + GenerationType = _nativeSettings.GenerationType + }; + + OnProgressChanged?.Invoke(0f); + + try + { + var objects = GetObjectsRequiringPreviews(_nativeSettings.InputPaths); + var filteredObjects = new List(); + var reusedPreviews = new List(); + FilterObjects(objects, filteredObjects, reusedPreviews); + + _generatedPreviewsCount = 0; + _totalPreviewsCount = objects.Count; + + Directory.CreateDirectory(_nativeSettings.OutputPath); + + var generatedPreviews = new List(); + if (!_nativeSettings.WaitForPreviews) + { + WritePreviewsWithoutWaiting(filteredObjects, out generatedPreviews); + } + else + { + if (_nativeSettings.ChunkedPreviewLoading) + { + await WaitAndWritePreviewsChunked(filteredObjects, generatedPreviews); + } + else + { + await WaitAndWritePreviews(filteredObjects, generatedPreviews); + } + } + + var allPreviews = new List(); + allPreviews.AddRange(generatedPreviews); + allPreviews.AddRange(reusedPreviews); + + result.Success = true; + result.GeneratedPreviews = generatedPreviews; + result.Previews = allPreviews; + } + catch (Exception e) + { + result.Success = false; + result.Exception = e; + } + + return result; + } + + private List GetObjectsRequiringPreviews(string[] inputPaths) + { + var objects = new List(); + var guids = AssetDatabase.FindAssets("", inputPaths); + + foreach (var guid in guids) + { + if (objects.Any(x => x.Guid == guid)) + continue; + + var assetPath = AssetDatabase.GUIDToAssetPath(guid); + var obj = AssetDatabase.LoadAssetAtPath(assetPath); + if (!ShouldHavePreview(obj)) + continue; + + objects.Add(new PreviewMetadata() { Type = GenerationType.Native, Guid = guid }); + } + + return objects; + } + + private void FilterObjects(List objects, List filteredObjects, List reusedPreviews) + { + if (Settings.OverwriteExisting || !CachingService.GetCachedMetadata(out var database)) + { + filteredObjects.AddRange(objects); + return; + } + + foreach (var obj in objects) + { + var matchingEntry = database.Previews.FirstOrDefault(x => + x.Guid == obj.Guid + && x.Type == GenerationType.Native + && x.Exists()); + + if (matchingEntry == null) + { + filteredObjects.Add(obj); + } + else + { + reusedPreviews.Add(matchingEntry); + } + } + } + + private bool ShouldHavePreview(UnityEngine.Object asset) + { + if (asset == null) + return false; + + if (!AssetDatabase.IsMainAsset(asset)) + return false; + + switch (asset) + { + case AudioClip _: + case Material _: + case Mesh _: + case TerrainLayer _: + case Texture _: + case Tile _: + return true; + case GameObject go: + var renderers = go.GetComponentsInChildren(); + return renderers != null && renderers.Length > 0; + default: + return false; + } + } + + private PreviewMetadata WritePreviewToDisk(PreviewMetadata metadata, Texture2D texture) + { + var asset = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(metadata.Guid)); + var width = Mathf.Min(texture.width, 128); + var height = Mathf.Min(texture.height, 128); + var readableTexture = GraphicsUtility.ResizeTexture(texture, width, height); + var fileName = PreviewConvertUtility.ConvertFilenameWithExtension(asset, _nativeSettings.PreviewFileNamingFormat, _nativeSettings.Format); + var filePath = $"{_nativeSettings.OutputPath}/{fileName}"; + var bytes = PreviewConvertUtility.ConvertTexture(readableTexture, _nativeSettings.Format); + + File.WriteAllBytes(filePath, bytes); + + metadata.Type = GenerationType.Native; + metadata.Name = asset.name; + metadata.Path = filePath; + + return metadata; + } + + private void WritePreviewsWithoutWaiting(List objects, out List generatedPreviews) + { + generatedPreviews = new List(); + + foreach (var obj in objects) + { + var texture = GetAssetPreviewFromGuid(obj.Guid); + if (texture == null) + continue; + + var generatedPreview = WritePreviewToDisk(obj, texture); + generatedPreviews.Add(generatedPreview); + } + } + + private Texture2D GetAssetPreviewFromGuid(string guid) + { + var method = typeof(AssetPreview).GetMethod("GetAssetPreviewFromGUID", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(string) }, null); + var args = new object[] { guid }; + + return method?.Invoke(null, args) as Texture2D; + } + + private async Task WaitAndWritePreviewsChunked(List objects, List generatedPreviews) + { + var chunks = objects.Count / _nativeSettings.ChunkSize; + var remainder = objects.Count % _nativeSettings.ChunkSize; + if (remainder != 0) + chunks += 1; + + for (int i = 0; i < chunks; i++) + { + var chunkObjects = new List(); + + for (int j = 0; j < _nativeSettings.ChunkSize; j++) + { + var index = i * _nativeSettings.ChunkSize + j; + if (index == objects.Count) + break; + + chunkObjects.Add(objects[index]); + } + + var generatedPreviewsChunk = new List(); + await WaitAndWritePreviews(chunkObjects, generatedPreviewsChunk); + generatedPreviews.AddRange(generatedPreviewsChunk); + } + } + + private async Task WaitAndWritePreviews(List objects, List generatedPreviews) + { + var initialObjectCount = objects.Count(); + if (initialObjectCount == 0) + return; + + await WaitAndWritePreviewIteration(objects, generatedPreviews); + var remainingObjectCount = objects.Count; + + // First iteration may take longer to start loading objects + var firstIterationStartTime = EditorApplication.timeSinceStartup; + while (true) + { + if (remainingObjectCount < initialObjectCount) + break; + + if (EditorApplication.timeSinceStartup - firstIterationStartTime > InitialPreviewLoadingTimeoutSeconds) + throw new Exception("Preview loading timed out."); + + await WaitAndWritePreviewIteration(objects, generatedPreviews); + remainingObjectCount = objects.Count; + } + + if (remainingObjectCount == 0) + return; + + while (true) + { + await WaitForEndOfFrame(1); + await WaitAndWritePreviewIteration(objects, generatedPreviews); + + // If no more previews are being loaded, try one more time before quitting + if (objects.Count == remainingObjectCount) + { + await WaitForEndOfFrame(1); + await WaitAndWritePreviewIteration(objects, generatedPreviews); + + if (objects.Count == remainingObjectCount) + { + var missingObjects = string.Join("\n", objects.Select(x => AssetDatabase.GUIDToAssetPath(x.Guid))); + Debug.LogWarning($"Unity Editor failed to fetch previews for {objects.Count} objects:\n{missingObjects}"); + break; + } + } + + remainingObjectCount = objects.Count; + + // Exit when all previews are loaded + if (remainingObjectCount == 0) + break; + } + } + + private async Task WaitAndWritePreviewIteration(List objects, List generatedPreviews) + { + var cacheSize = Mathf.Max(_nativeSettings.ChunkSize * 2, objects.Count() + _nativeSettings.ChunkSize); + AssetPreview.SetPreviewTextureCacheSize(cacheSize); + + // Initial queueing + foreach (var obj in objects) + { + var asset = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(obj.Guid)); + AssetPreview.GetAssetPreview(asset); + } + + await WaitForEndOfFrame(); + + // Waiting (NOTE: works inconsistently across Unity streams) + foreach (var obj in objects) + { + var asset = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(obj.Guid)); + if (AssetPreview.IsLoadingAssetPreview(asset.GetInstanceID())) + { + await WaitForEndOfFrame(); + } + } + + // Writing + for (int i = 0; i < objects.Count; i++) + { + var obj = objects[i]; + + var asset = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(obj.Guid)); + var texture = AssetPreview.GetAssetPreview(asset); + if (texture == null) + continue; + + WritePreviewToDisk(obj, texture); + generatedPreviews.Add(obj); + _generatedPreviewsCount++; + OnProgressChanged?.Invoke((float)_generatedPreviewsCount / _totalPreviewsCount); + } + + // Removing written objects from the list + for (int i = objects.Count - 1; i >= 0; i--) + { + if (objects[i].Exists()) + objects.RemoveAt(i); + } + } + + private async Task WaitForEndOfFrame(double atLeastSeconds) + { + var startTime = EditorApplication.timeSinceStartup; + while (EditorApplication.timeSinceStartup - startTime <= atLeastSeconds) + { + await WaitForEndOfFrame(); + } + } + + private async Task WaitForEndOfFrame() + { + var isNextFrame = false; + EditorApplication.CallbackFunction callback = null; + callback = () => + { + EditorApplication.update -= callback; + isNextFrame = true; + }; + + EditorApplication.update += callback; + while (!isNextFrame) + await Task.Yield(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs.meta new file mode 100644 index 00000000..0d6454db --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: dd6eeb2f97a2ed34db51ab5ac0b3ffa1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/NativePreviewGenerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs new file mode 100644 index 00000000..02d779d3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs @@ -0,0 +1,45 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Services; +using System; +using System.Threading.Tasks; + +namespace AssetStoreTools.Previews.Generators +{ + internal abstract class PreviewGeneratorBase : IPreviewGenerator + { + public PreviewGenerationSettings Settings { get; } + protected ICachingService CachingService; + + public abstract event Action OnProgressChanged; + + public PreviewGeneratorBase(PreviewGenerationSettings settings) + { + Settings = settings; + CachingService = PreviewServiceProvider.Instance.GetService(); + } + + public async Task Generate() + { + Validate(); + + var result = await GenerateImpl(); + if (result.Success) + { + CachingService.CacheMetadata(result.GeneratedPreviews); + } + + return result; + } + + protected virtual void Validate() + { + if (Settings.InputPaths == null || Settings.InputPaths.Length == 0) + throw new ArgumentException("Input paths cannot be null"); + + if (string.IsNullOrEmpty(Settings.OutputPath)) + throw new ArgumentException("Output path cannot be null"); + } + + protected abstract Task GenerateImpl(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs.meta new file mode 100644 index 00000000..36e64a20 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cedf01448e0edcc4fb55f19f2e92b740 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Generators/PreviewGeneratorBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services.meta new file mode 100644 index 00000000..55ebe0c7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aa18c820f185bfc4d8cd59e3418e2c4e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching.meta new file mode 100644 index 00000000..449835ad --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eb61a60f2ff91a448a7808ef2a25f871 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs new file mode 100644 index 00000000..10bb448e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs @@ -0,0 +1,87 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Utility; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace AssetStoreTools.Previews.Services +{ + internal class CachingService : ICachingService + { + public void CacheMetadata(IEnumerable previews) + { + var updatedDatabase = UpdatePreviewDatabase(previews); + + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = PreviewDatabaseContractResolver.Instance, + Converters = new List() { new StringEnumConverter() }, + Formatting = Formatting.Indented + }; + + CacheUtil.CreateFileInTempCache(Constants.Previews.PreviewDatabaseFile, JsonConvert.SerializeObject(updatedDatabase, serializerSettings), true); + } + + public bool GetCachedMetadata(out PreviewDatabase previewDatabase) + { + previewDatabase = null; + if (!CacheUtil.GetFileFromTempCache(Constants.Previews.PreviewDatabaseFile, out string filePath)) + return false; + + try + { + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = PreviewDatabaseContractResolver.Instance, + Converters = new List() { new StringEnumConverter() } + }; + + previewDatabase = JsonConvert.DeserializeObject(File.ReadAllText(filePath, Encoding.UTF8), serializerSettings); + return true; + } + catch + { + return false; + } + } + + private PreviewDatabase UpdatePreviewDatabase(IEnumerable previews) + { + PreviewDatabase database; + if (!GetCachedMetadata(out database)) + database = new PreviewDatabase(); + + // Delete missing previews + for (int i = database.Previews.Count - 1; i >= 0; i--) + { + if (database.Previews[i].Exists()) + continue; + + database.Previews.RemoveAt(i); + } + + // Append new previews & Replace existing previews + foreach (var preview in previews) + { + var matchingPreviews = database.Previews.Where(x => x.Guid == preview.Guid).ToList(); + foreach (var matchingPreview in matchingPreviews) + { + // Delete previously generated preview of the same type + if (matchingPreview.Type == preview.Type) + database.Previews.Remove(matchingPreview); + // Delete previously generated preview of a different type if the path matches + else if (matchingPreview.Path.Equals(preview.Path)) + database.Previews.Remove(matchingPreview); + } + + database.Previews.Add(preview); + } + + database.Previews = database.Previews.OrderBy(x => x.Guid).ThenBy(x => x.Type).ToList(); + return database; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs.meta new file mode 100644 index 00000000..ef9417ed --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e0b6cf909c8798b4590744959571a21f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/CachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs new file mode 100644 index 00000000..67130008 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Previews.Data; +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.Services +{ + internal interface ICachingService : IPreviewService + { + void CacheMetadata(IEnumerable previews); + bool GetCachedMetadata(out PreviewDatabase previewDatabase); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs.meta new file mode 100644 index 00000000..50b3339d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: eeaeae010299dcd489adb00dbf51b274 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/Caching/ICachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs new file mode 100644 index 00000000..0bc56aeb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs @@ -0,0 +1,4 @@ +namespace AssetStoreTools.Previews.Services +{ + public interface IPreviewService { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs.meta new file mode 100644 index 00000000..28043dcb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8c2761fe05638644d8e3a265865beef8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/IPreviewService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs new file mode 100644 index 00000000..7b2754be --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs @@ -0,0 +1,17 @@ +using AssetStoreTools.Utility; + +namespace AssetStoreTools.Previews.Services +{ + internal class PreviewServiceProvider : ServiceProvider + { + public static PreviewServiceProvider Instance => _instance ?? (_instance = new PreviewServiceProvider()); + private static PreviewServiceProvider _instance; + + private PreviewServiceProvider() { } + + protected override void RegisterServices() + { + Register(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs.meta new file mode 100644 index 00000000..0f5345ee --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a19bf5a4e3e441047bbc1b894e2a1149 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Services/PreviewServiceProvider.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI.meta new file mode 100644 index 00000000..67d04e3c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4738f3648c8368244a968bc840c1152b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data.meta new file mode 100644 index 00000000..b302df52 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23a2f4eadd444194a91ff4ce509e4798 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs new file mode 100644 index 00000000..1b2fee97 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs @@ -0,0 +1,56 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.IO; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal class AssetPreview : IAssetPreview + { + private PreviewMetadata _metadata; + + private UnityEngine.Object _cachedAsset; + private string _cachedAssetPath; + private Texture2D _cachedTexture; + + public UnityEngine.Object Asset => _cachedAsset ?? (_cachedAsset = AssetDatabase.LoadAssetAtPath(AssetPath)); + public string AssetPath => _cachedAssetPath ?? (_cachedAssetPath = AssetDatabase.GUIDToAssetPath(_metadata.Guid)); + + public AssetPreview(PreviewMetadata metadata) + { + _metadata = metadata; + } + + public string GetAssetPath() + { + var assetPath = AssetDatabase.GUIDToAssetPath(_metadata.Guid); + return assetPath; + } + + public async Task LoadImage(Action onSuccess) + { + if (_cachedTexture == null) + { + if (!_metadata.Exists()) + return; + + await Task.Yield(); + + try + { + _cachedTexture = new Texture2D(1, 1); + _cachedTexture.LoadImage(File.ReadAllBytes(_metadata.Path)); + } + catch (Exception e) + { + Debug.LogException(e); + return; + } + } + + onSuccess?.Invoke(_cachedTexture); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs.meta new file mode 100644 index 00000000..9764acf5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 739cf05c689204f4089fd0a6bddb8c3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreview.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs new file mode 100644 index 00000000..40db2b62 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs @@ -0,0 +1,46 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal class AssetPreviewCollection : IAssetPreviewCollection + { + private GenerationType _generationType; + private List _images; + + public event Action OnCollectionChanged; + + public AssetPreviewCollection() + { + _images = new List(); + } + + public GenerationType GetGenerationType() + { + return _generationType; + } + + public IEnumerable GetPreviews() + { + return _images; + } + + public void Refresh(GenerationType generationType, IEnumerable previews) + { + _images.Clear(); + + _generationType = generationType; + + foreach (var entry in previews) + { + if (!entry.Exists()) + continue; + + _images.Add(new AssetPreview(entry)); + } + + OnCollectionChanged?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs.meta new file mode 100644 index 00000000..319746ac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9b1a0db8710933048b49dcca463fb8fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/AssetPreviewCollection.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs new file mode 100644 index 00000000..f7fc7508 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading.Tasks; +using UnityEngine; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal interface IAssetPreview + { + UnityEngine.Object Asset { get; } + string GetAssetPath(); + Task LoadImage(Action onSuccess); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs.meta new file mode 100644 index 00000000..3bf6b869 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0f9373dfc16d0fa4794dac29b75204ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreview.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs new file mode 100644 index 00000000..6e614c68 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs @@ -0,0 +1,15 @@ +using AssetStoreTools.Previews.Data; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal interface IAssetPreviewCollection + { + event Action OnCollectionChanged; + + GenerationType GetGenerationType(); + IEnumerable GetPreviews(); + void Refresh(GenerationType generationType, IEnumerable previews); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs.meta new file mode 100644 index 00000000..60da0185 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fc9d9abd80c070f44ac49d5ce23d2fc0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IAssetPreviewCollection.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs new file mode 100644 index 00000000..51f626c9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs @@ -0,0 +1,27 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Generators; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal interface IPreviewGeneratorSettings + { + event Action OnGenerationTypeChanged; + event Action OnGenerationPathsChanged; + + void LoadSettings(PreviewGenerationSettings settings); + + GenerationType GetGenerationType(); + void SetGenerationType(GenerationType type); + List GetAvailableGenerationTypes(); + + List GetGenerationPaths(); + void AddGenerationPath(string path); + void RemoveGenerationPath(string path); + void ClearGenerationPaths(); + bool IsGenerationPathValid(string path, out string error); + + IPreviewGenerator CreateGenerator(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs.meta new file mode 100644 index 00000000..e3ecce75 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 55c9fcde15f06754588fd02fb8b99a60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/IPreviewGeneratorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs new file mode 100644 index 00000000..86962e41 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs @@ -0,0 +1,212 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Generators; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Previews.UI.Data +{ + internal class PreviewGeneratorSettings : IPreviewGeneratorSettings + { + private readonly GenerationType[] _availableGenerationTypes = new GenerationType[] + { + GenerationType.Native, + GenerationType.Custom + }; + + private List _inputPaths; + private GenerationType _generationType; + + public event Action OnGenerationTypeChanged; + public event Action OnGenerationPathsChanged; + + public PreviewGeneratorSettings() + { + _inputPaths = new List(); + _generationType = GenerationType.Native; + } + + public void LoadSettings(PreviewGenerationSettings settings) + { + if (settings == null) + return; + + _inputPaths = settings.InputPaths.ToList(); + OnGenerationPathsChanged?.Invoke(); + + switch (settings) + { + case NativePreviewGenerationSettings _: + _generationType = GenerationType.Native; + break; + case CustomPreviewGenerationSettings _: + _generationType = GenerationType.Custom; + break; + default: + return; + } + + OnGenerationTypeChanged?.Invoke(); + } + + public GenerationType GetGenerationType() + { + return _generationType; + } + + public void SetGenerationType(GenerationType type) + { + _generationType = type; + OnGenerationTypeChanged?.Invoke(); + } + + public List GetAvailableGenerationTypes() + { + return _availableGenerationTypes.ToList(); + } + + public List GetGenerationPaths() + { + return _inputPaths; + } + + public void AddGenerationPath(string path) + { + if (string.IsNullOrEmpty(path)) + return; + + if (_inputPaths.Contains(path)) + return; + + // Prevent redundancy for new paths + var existingPath = _inputPaths.FirstOrDefault(x => path.StartsWith(x + "/")); + if (existingPath != null) + { + Debug.LogWarning($"Path '{path}' is already included with existing path: '{existingPath}'"); + return; + } + + // Prevent redundancy for already added paths + var redundantPaths = _inputPaths.Where(x => x.StartsWith(path + "/")).ToArray(); + foreach (var redundantPath in redundantPaths) + { + Debug.LogWarning($"Existing validation path '{redundantPath}' has been made redundant by the inclusion of new validation path: '{path}'"); + _inputPaths.Remove(redundantPath); + } + + _inputPaths.Add(path); + + OnGenerationPathsChanged?.Invoke(); + } + + public void RemoveGenerationPath(string path) + { + if (!_inputPaths.Contains(path)) + return; + + _inputPaths.Remove(path); + + OnGenerationPathsChanged?.Invoke(); + } + + public void ClearGenerationPaths() + { + if (_inputPaths.Count == 0) + return; + + _inputPaths.Clear(); + + OnGenerationPathsChanged?.Invoke(); + } + + public bool IsGenerationPathValid(string path, out string error) + { + error = string.Empty; + + if (string.IsNullOrEmpty(path)) + { + error = "Path cannot be empty"; + return false; + } + + var isAssetsPath = path.StartsWith("Assets/") + || path.Equals("Assets"); + var isPackagePath = PackageUtility.GetPackageByManifestPath($"{path}/package.json", out _); + + if (!isAssetsPath && !isPackagePath) + { + error = "Selected path must be within the Assets folder or point to a root path of a package"; + return false; + } + + if (!Directory.Exists(path)) + { + error = "Path does not exist"; + return false; + } + + if (path.Split('/').Any(x => x.StartsWith(".") || x.EndsWith("~"))) + { + error = $"Path '{path}' cannot be selected as it is a hidden folder and not part of the Asset Database"; + return false; + } + + return true; + } + + public IPreviewGenerator CreateGenerator() + { + switch (_generationType) + { + case GenerationType.Native: + return CreateNativeGenerator(); + case GenerationType.Custom: + return CreateCustomGenerator(); + default: + throw new NotImplementedException("Undefined generator type"); + } + } + + private IPreviewGenerator CreateNativeGenerator() + { + var settings = new NativePreviewGenerationSettings() + { + InputPaths = _inputPaths.ToArray(), + OutputPath = Constants.Previews.Native.DefaultOutputPath, + PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat, + Format = Constants.Previews.Native.DefaultFormat, + WaitForPreviews = Constants.Previews.Native.DefaultWaitForPreviews, + ChunkedPreviewLoading = Constants.Previews.Native.DefaultChunkedPreviewLoading, + ChunkSize = Constants.Previews.Native.DefaultChunkSize, + OverwriteExisting = true + }; + + return new NativePreviewGenerator(settings); + } + + private IPreviewGenerator CreateCustomGenerator() + { + var settings = new CustomPreviewGenerationSettings() + { + InputPaths = _inputPaths.ToArray(), + OutputPath = Constants.Previews.Custom.DefaultOutputPath, + Width = Constants.Previews.Custom.DefaultWidth, + Height = Constants.Previews.Custom.DefaultHeight, + Depth = Constants.Previews.Custom.DefaultDepth, + NativeWidth = Constants.Previews.Custom.DefaultNativeWidth, + NativeHeight = Constants.Previews.Custom.DefaultNativeHeight, + PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat, + Format = Constants.Previews.Custom.DefaultFormat, + AudioSampleColor = Constants.Previews.Custom.DefaultAudioSampleColor, + AudioBackgroundColor = Constants.Previews.Custom.DefaultAudioBackgroundColor, + OverwriteExisting = true + }; + + var generator = new CustomPreviewGenerator(settings); + return generator; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs.meta new file mode 100644 index 00000000..b57c82ab --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9e6f754b1179d8d4cb40f62692619a63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Data/PreviewGeneratorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements.meta new file mode 100644 index 00000000..d81acd59 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 700ec0107b011824892281e880281bb1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs new file mode 100644 index 00000000..aee6fa8a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs @@ -0,0 +1,83 @@ +using AssetStoreTools.Previews.UI.Data; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class AssetPreviewElement : VisualElement + { + // Data + private IAssetPreview _assetPreview; + + // UI + private Image _image; + private Label _label; + + public AssetPreviewElement() + { + AddToClassList("preview-list-image"); + + Create(); + + RegisterCallback(OnImageClicked); + } + + private void Create() + { + CreateFiller(); + CreateImage(); + CreateLabel(); + } + + private void CreateImage() + { + _image = new Image(); + Add(_image); + } + + private void CreateFiller() + { + var filler = new VisualElement() { name = "Filler" }; + Add(filler); + } + + private void CreateLabel() + { + _label = new Label(); + Add(_label); + } + + private void SetImage(Texture2D texture) + { + _image.style.width = texture.width < 128 ? texture.width : 128; + _image.style.height = texture.height < 128 ? texture.height : 128; + _image.style.backgroundImage = texture; + } + + private void OnImageClicked(MouseDownEvent _) + { + EditorGUIUtility.PingObject(_assetPreview.Asset); + } + + public void SetSource(IAssetPreview assetPreview) + { + _assetPreview = assetPreview; + _assetPreview.LoadImage(SetImage); + + var assetPath = _assetPreview.GetAssetPath(); + + if (string.IsNullOrEmpty(assetPath)) + { + _label.text = "[Missing]"; + tooltip = "This asset has been deleted"; + return; + } + + var assetNameWithExtension = assetPath.Split('/').Last(); + _label.text = assetNameWithExtension; + tooltip = assetPath; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs.meta new file mode 100644 index 00000000..fec756c2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 28891b8cff841a44eb508494d62c190c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/AssetPreviewElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs new file mode 100644 index 00000000..a1bf53a0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class GridListElement : VisualElement + { + public int ElementWidth; + public int ElementHeight; + private int _visibilityHeadroom => ElementHeight; + + public IList ItemSource; + public Func MakeItem; + public Action BindItem; + + private ScrollView _scrollView; + + public GridListElement() + { + style.flexGrow = 1; + + Create(); + + _scrollView.contentViewport.RegisterCallback(OnGeometryChanged); + _scrollView.verticalScroller.valueChanged += OnVerticalScroll; +#if UNITY_2021_1_OR_NEWER + _scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden; +#else + _scrollView.showHorizontal = false; +#endif + } + + private void Create() + { + _scrollView = new ScrollView(); + Add(_scrollView); + } + + private void OnGeometryChanged(GeometryChangedEvent evt) + { + Redraw(); + } + + private void OnVerticalScroll(float value) + { + Redraw(); + } + + public void Redraw() + { + if (ElementWidth == 0 + || ElementHeight == 0 + || ItemSource == null + || MakeItem == null + || BindItem == null) + return; + + _scrollView.Clear(); + + var rowCapacity = Mathf.FloorToInt(_scrollView.contentContainer.worldBound.width / ElementWidth); + if (rowCapacity == 0) + rowCapacity = 1; + + var totalRequiredRows = ItemSource.Count / rowCapacity; + if (ItemSource.Count % rowCapacity != 0) + totalRequiredRows++; + + _scrollView.contentContainer.style.height = totalRequiredRows * ElementHeight; + + var visibleRows = new List(); + for (int i = 0; i < totalRequiredRows; i++) + { + var visible = IsRowVisible(i); + if (!visible) + continue; + + var rowElement = CreateRow(i); + + for (int j = 0; j < rowCapacity; j++) + { + var elementIndex = i * rowCapacity + j; + if (elementIndex >= ItemSource.Count) + { + rowElement.Add(CreateFillerElement()); + continue; + } + + var element = MakeItem?.Invoke(); + BindItem?.Invoke(element, elementIndex); + + rowElement.Add(element); + } + + _scrollView.Add(rowElement); + } + } + + private bool IsRowVisible(int rowIndex) + { + var contentStartY = _scrollView.contentContainer.worldBound.yMin; + var visibleContentMinY = _scrollView.contentViewport.worldBound.yMin - _visibilityHeadroom; + var visibleContentMaxY = _scrollView.contentViewport.worldBound.yMax + _visibilityHeadroom; + if (_scrollView.contentViewport.worldBound.height == 0) + visibleContentMaxY = this.worldBound.yMax; + + var rowMinY = (rowIndex * ElementHeight) + contentStartY; + var rowMaxY = (rowIndex * ElementHeight) + ElementHeight + contentStartY; + + var fullyVisible = rowMinY >= visibleContentMinY && rowMaxY <= visibleContentMaxY; + var partiallyAbove = rowMinY < visibleContentMinY && rowMaxY > visibleContentMinY; + var partiallyBelow = rowMaxY > visibleContentMaxY && rowMinY < visibleContentMaxY; + + return fullyVisible || partiallyAbove || partiallyBelow; + } + + private VisualElement CreateRow(int rowIndex) + { + var rowElement = new VisualElement() { name = $"Row {rowIndex}" }; + rowElement.style.flexDirection = FlexDirection.Row; + rowElement.style.position = Position.Absolute; + rowElement.style.top = ElementHeight * rowIndex; + rowElement.style.width = _scrollView.contentViewport.worldBound.width; + rowElement.style.justifyContent = Justify.SpaceAround; + + return rowElement; + } + + private VisualElement CreateFillerElement() + { + var element = new VisualElement(); + element.style.width = ElementWidth; + element.style.height = ElementHeight; + + return element; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs.meta new file mode 100644 index 00000000..a439c553 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 81d9f779e8c2a464cbdc1e39a4864803 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/GridListElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs new file mode 100644 index 00000000..28a35b18 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs @@ -0,0 +1,116 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.UI.Data; +using System.Linq; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.SceneManagement; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class PreviewCollectionElement : VisualElement + { + // Data + private IAssetPreviewCollection _collection; + + // UI + private Label _previewCountLabel; + private GridListElement _gridListElement; + + public PreviewCollectionElement(IAssetPreviewCollection collection) + { + AddToClassList("preview-list"); + + _collection = collection; + _collection.OnCollectionChanged += RefreshList; + + Create(); + RefreshList(); + + SubscribeToSceneChanges(); + } + + private void Create() + { + CreateLabel(); + CreateGridListElement(); + } + + private void CreateLabel() + { + _previewCountLabel = new Label(); + _previewCountLabel.style.display = DisplayStyle.None; + Add(_previewCountLabel); + } + + private void CreateGridListElement() + { + _gridListElement = new GridListElement(); + _gridListElement.MakeItem = CreatePreview; + _gridListElement.BindItem = BindPreview; + _gridListElement.ElementWidth = 140 + 10; // Accounting for margin style + _gridListElement.ElementHeight = 160 + 10; // Accounting for margin style + Add(_gridListElement); + } + + private VisualElement CreatePreview() + { + var preview = new AssetPreviewElement(); + return preview; + } + + private void BindPreview(VisualElement element, int index) + { + var previewElement = (AssetPreviewElement)element; + var preview = _collection.GetPreviews().ToList()[index]; + previewElement.SetSource(preview); + } + + private void RefreshList() + { + var type = _collection.GetGenerationType(); + var items = _collection.GetPreviews().ToList(); + _previewCountLabel.text = $"Displaying {items.Count} {ConvertGenerationTypeName(type)} previews"; + _previewCountLabel.style.display = DisplayStyle.Flex; + _previewCountLabel.style.alignSelf = Align.Center; + _previewCountLabel.style.marginBottom = 10; + _previewCountLabel.style.unityFontStyleAndWeight = FontStyle.Bold; + + _gridListElement.ItemSource = items; + _gridListElement.Redraw(); + } + + private string ConvertGenerationTypeName(GenerationType type) + { + switch (type) + { + case GenerationType.Custom: + return "high resolution"; + default: + return type.ToString().ToLower(); + } + } + + private void SubscribeToSceneChanges() + { + var windowToSubscribeTo = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + UnityAction sceneChanged = null; + sceneChanged = new UnityAction((_, __) => RefreshObjects(windowToSubscribeTo)); + EditorSceneManager.activeSceneChangedInEditMode += sceneChanged; + + void RefreshObjects(PreviewGeneratorWindow subscribedWindow) + { + // Remove callback if preview generator window instance changed + var activeWindow = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + if (subscribedWindow == null || subscribedWindow != activeWindow) + { + EditorSceneManager.activeSceneChangedInEditMode -= sceneChanged; + return; + } + + RefreshList(); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs.meta new file mode 100644 index 00000000..fc6e1c13 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 842a11e046ca5284d9de9f4a05b1fa26 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewCollectionElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs new file mode 100644 index 00000000..3d2f9a86 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs @@ -0,0 +1,50 @@ +using AssetStoreTools.Previews.UI.Data; +using System; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class PreviewGenerateButtonElement : VisualElement + { + // Data + private IPreviewGeneratorSettings _settings; + + // UI + private Button _generateButton; + + public event Action OnGenerate; + + public PreviewGenerateButtonElement(IPreviewGeneratorSettings settings) + { + _settings = settings; + _settings.OnGenerationPathsChanged += GenerationPathsChanged; + + Create(); + Deserialize(); + } + + private void Create() + { + _generateButton = new Button(Validate) { text = "Generate" }; + _generateButton.AddToClassList("preview-generate-button"); + + Add(_generateButton); + } + + private void Validate() + { + OnGenerate?.Invoke(); + } + + private void GenerationPathsChanged() + { + var inputPathsPresent = _settings.GetGenerationPaths().Count > 0; + _generateButton.SetEnabled(inputPathsPresent); + } + + private void Deserialize() + { + GenerationPathsChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs.meta new file mode 100644 index 00000000..57303acd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 1c8fbb0b13ba7d3479c0867c440821e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGenerateButtonElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs new file mode 100644 index 00000000..cf724404 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs @@ -0,0 +1,122 @@ +using AssetStoreTools.Previews.UI.Data; +using AssetStoreTools.Utility; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class PreviewGeneratorPathsElement : VisualElement + { + // Data + private IPreviewGeneratorSettings _settings; + + // UI + private ScrollView _pathBoxScrollView; + + public PreviewGeneratorPathsElement(IPreviewGeneratorSettings settings) + { + AddToClassList("preview-paths"); + + _settings = settings; + _settings.OnGenerationPathsChanged += InputPathsChanged; + + Create(); + Deserialize(); + } + + private void Create() + { + var pathSelectionRow = new VisualElement(); + pathSelectionRow.AddToClassList("preview-settings-selection-row"); + + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("preview-settings-selection-label-help-row"); + labelHelpRow.style.alignSelf = Align.FlexStart; + + Label pathLabel = new Label { text = "Input paths" }; + Image pathLabelTooltip = new Image + { + tooltip = "Select the folder (or multiple folders) to generate asset previews for." + }; + + labelHelpRow.Add(pathLabel); + labelHelpRow.Add(pathLabelTooltip); + + var fullPathBox = new VisualElement() { name = "PreviewPaths" }; + fullPathBox.AddToClassList("preview-paths-box"); + + _pathBoxScrollView = new ScrollView { name = "PreviewPathsScrollView" }; + _pathBoxScrollView.AddToClassList("preview-paths-scroll-view"); + + VisualElement scrollViewBottomRow = new VisualElement(); + scrollViewBottomRow.AddToClassList("preview-paths-scroll-view-bottom-row"); + + var addExtraPathsButton = new Button(BrowsePath) { text = "Add a path" }; + addExtraPathsButton.AddToClassList("preview-paths-add-button"); + scrollViewBottomRow.Add(addExtraPathsButton); + + fullPathBox.Add(_pathBoxScrollView); + fullPathBox.Add(scrollViewBottomRow); + + pathSelectionRow.Add(labelHelpRow); + pathSelectionRow.Add(fullPathBox); + + Add(pathSelectionRow); + } + + private VisualElement CreateSinglePathElement(string path) + { + var validationPath = new VisualElement(); + validationPath.AddToClassList("preview-paths-path-row"); + + var folderPathLabel = new Label(path); + folderPathLabel.AddToClassList("preview-paths-path-row-input-field"); + + var removeButton = new Button(() => + { + _settings.RemoveGenerationPath(path); + }); + removeButton.text = "X"; + removeButton.AddToClassList("preview-paths-path-row-remove-button"); + + validationPath.Add(folderPathLabel); + validationPath.Add(removeButton); + + return validationPath; + } + + private void BrowsePath() + { + string absolutePath = EditorUtility.OpenFolderPanel("Select a directory", "Assets", ""); + + if (string.IsNullOrEmpty(absolutePath)) + return; + + var relativePath = FileUtility.AbsolutePathToRelativePath(absolutePath, ASToolsPreferences.Instance.EnableSymlinkSupport); + + if (!_settings.IsGenerationPathValid(relativePath, out var error)) + { + EditorUtility.DisplayDialog("Invalid path", error, "OK"); + return; + } + + _settings.AddGenerationPath(relativePath); + } + + private void InputPathsChanged() + { + var inputPaths = _settings.GetGenerationPaths(); + + _pathBoxScrollView.Clear(); + foreach (var path in inputPaths) + { + _pathBoxScrollView.Add(CreateSinglePathElement(path)); + } + } + + private void Deserialize() + { + InputPathsChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs.meta new file mode 100644 index 00000000..efdee4a2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cd3e3f7fbfc5f1e46835438be2756746 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorPathsElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs new file mode 100644 index 00000000..d5268f5e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs @@ -0,0 +1,99 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.UI.Data; +using AssetStoreTools.Validator.UI.Elements; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class PreviewGeneratorSettingsElement : VisualElement + { + // Data + private IPreviewGeneratorSettings _settings; + + // UI + private PreviewGeneratorPathsElement _previewPathsElement; + private ToolbarMenu _generationTypeMenu; + + public PreviewGeneratorSettingsElement(IPreviewGeneratorSettings settings) + { + AddToClassList("preview-settings"); + + _settings = settings; + _settings.OnGenerationTypeChanged += GenerationTypeChanged; + + Create(); + Deserialize(); + } + + private void Create() + { + CreateGenerationType(); + CreateInputPathsElement(); + } + + private void CreateInputPathsElement() + { + _previewPathsElement = new PreviewGeneratorPathsElement(_settings); + Add(_previewPathsElement); + } + + private void CreateGenerationType() + { + var typeSelectionBox = new VisualElement(); + typeSelectionBox.AddToClassList("preview-settings-selection-row"); + + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("preview-settings-selection-label-help-row"); + + Label generationTypeLabel = new Label { text = "Generation type" }; + Image categoryLabelTooltip = new Image + { + tooltip = "Choose the generation type for your previews.\n\n" + + "- Native: retrieve previews from the Asset Database which are generated by Unity Editor internally\n" + + "- High Resolution (experimental): generate previews using a custom implementation. Resulting previews are of higher resolution " + + "than those generated by Unity Editor. Note that they may look slightly different from native previews" + }; + + labelHelpRow.Add(generationTypeLabel); + labelHelpRow.Add(categoryLabelTooltip); + + _generationTypeMenu = new ToolbarMenu { name = "GenerationTypeMenu" }; + _generationTypeMenu.AddToClassList("preview-settings-selection-dropdown"); + + typeSelectionBox.Add(labelHelpRow); + typeSelectionBox.Add(_generationTypeMenu); + + // Append available categories + var types = _settings.GetAvailableGenerationTypes(); + foreach (var t in types) + { + _generationTypeMenu.menu.AppendAction(ConvertGenerationTypeName(t), _ => _settings.SetGenerationType(t)); + } + + Add(typeSelectionBox); + } + + private string ConvertGenerationTypeName(GenerationType type) + { + switch (type) + { + case GenerationType.Custom: + return "High Resolution (experimental)"; + default: + return type.ToString(); + } + } + + private void GenerationTypeChanged() + { + var t = _settings.GetGenerationType(); + _generationTypeMenu.text = ConvertGenerationTypeName(t); + } + + private void Deserialize() + { + GenerationTypeChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs.meta new file mode 100644 index 00000000..acda521f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6f38de8a438b8c94a81fe5f2cc45c110 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewGeneratorSettingsElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs new file mode 100644 index 00000000..1306f05b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs @@ -0,0 +1,87 @@ +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Elements +{ + internal class PreviewWindowDescriptionElement : VisualElement + { + private const string DescriptionFoldoutText = "Generate and inspect asset preview images to be displayed in your package listing page on the Asset Store."; + private const string DescriptionFoldoutContentText = "Images generated in this window will be reused when exporting a package. Any missing images generated during the package export process will also appear here.\n\n" + + "Preview images are displayed on the Asset Store under the 'Package Content' section of the package listing. " + + "They are also displayed in the package importer window that appears during the package import process. " + + "Note that these images will not replace the images used for the assets in the Project window after the package gets imported."; + + private VisualElement _descriptionSimpleContainer; + private Button _showMoreButton; + + private VisualElement _descriptionFullContainer; + private Button _showLessButton; + + public PreviewWindowDescriptionElement() + { + AddToClassList("asset-preview-description"); + Create(); + } + + private void Create() + { + CreateSimpleDescription(); + CreateFullDescription(); + } + + private void CreateSimpleDescription() + { + _descriptionSimpleContainer = new VisualElement(); + _descriptionSimpleContainer.AddToClassList("asset-preview-description-simple-container"); + + var simpleDescription = new Label(DescriptionFoldoutText); + simpleDescription.AddToClassList("asset-preview-description-simple-label"); + + _showMoreButton = new Button(ToggleFullDescription) { text = "Show more..." }; + _showMoreButton.AddToClassList("asset-preview-description-hyperlink-button"); + _showMoreButton.AddToClassList("asset-preview-description-show-button"); + + _descriptionSimpleContainer.Add(simpleDescription); + _descriptionSimpleContainer.Add(_showMoreButton); + + Add(_descriptionSimpleContainer); + } + + private void CreateFullDescription() + { + _descriptionFullContainer = new VisualElement(); + _descriptionFullContainer.AddToClassList("asset-preview-description-full-container"); + + var validatorDescription = new Label() + { + text = DescriptionFoldoutContentText + }; + validatorDescription.AddToClassList("asset-preview-description-full-label"); + + _showLessButton = new Button(ToggleFullDescription) { text = "Show less..." }; + _showLessButton.AddToClassList("asset-preview-description-hide-button"); + _showLessButton.AddToClassList("asset-preview-description-hyperlink-button"); + + _descriptionFullContainer.Add(validatorDescription); + _descriptionFullContainer.Add(_showLessButton); + + _descriptionFullContainer.style.display = DisplayStyle.None; + Add(_descriptionFullContainer); + } + + private void ToggleFullDescription() + { + var displayFullDescription = _descriptionFullContainer.style.display == DisplayStyle.None; + + if (displayFullDescription) + { + _showMoreButton.style.display = DisplayStyle.None; + _descriptionFullContainer.style.display = DisplayStyle.Flex; + } + else + { + _showMoreButton.style.display = DisplayStyle.Flex; + _descriptionFullContainer.style.display = DisplayStyle.None; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs.meta new file mode 100644 index 00000000..5f0631e9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2cab289a87b0ba74f89cb458ff6d44f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Elements/PreviewWindowDescriptionElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs new file mode 100644 index 00000000..3a2d36f8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs @@ -0,0 +1,51 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Services; +using AssetStoreTools.Previews.UI.Views; +using AssetStoreTools.Utility; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI +{ + internal class PreviewGeneratorWindow : AssetStoreToolsWindow + { + protected override string WindowTitle => "Preview Generator"; + + private ICachingService _cachingService; + + private PreviewListView _previewListView; + + protected override void Init() + { + minSize = new Vector2(350, 350); + + this.SetAntiAliasing(4); + + VisualElement root = rootVisualElement; + + // Getting a reference to the USS Document and adding stylesheet to the root + root.styleSheets.Add(StyleSelector.PreviewGeneratorWindow.PreviewGeneratorWindowStyle); + root.styleSheets.Add(StyleSelector.PreviewGeneratorWindow.PreviewGeneratorWindowTheme); + + GetServices(); + ConstructWindow(); + } + + private void GetServices() + { + _cachingService = PreviewServiceProvider.Instance.GetService(); + } + + private void ConstructWindow() + { + _previewListView = new PreviewListView(_cachingService); + rootVisualElement.Add(_previewListView); + } + + public void Load(PreviewGenerationSettings settings) + { + _previewListView.LoadSettings(settings); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs.meta new file mode 100644 index 00000000..04e42023 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4cad15de2de8cdc46b48a4b05eac5d78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/PreviewGeneratorWindow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views.meta new file mode 100644 index 00000000..598279e5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5e154861b0e2af64b93f6c831e6c0dc2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs new file mode 100644 index 00000000..36f52642 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs @@ -0,0 +1,142 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Services; +using AssetStoreTools.Previews.UI.Data; +using AssetStoreTools.Previews.UI.Elements; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Previews.UI.Views +{ + internal class PreviewListView : VisualElement + { + //Data + private PreviewDatabase _previewDatabase; + private IPreviewGeneratorSettings _previewGeneratorSettings; + private IAssetPreviewCollection _previewCollection; + + private ICachingService _cachingService; + + // UI + private PreviewWindowDescriptionElement _descriptionElement; + private PreviewGeneratorSettingsElement _settingsElement; + private PreviewGenerateButtonElement _generateButtonElement; + private PreviewCollectionElement _previewCollectionElement; + + public PreviewListView(ICachingService cachingService) + { + _cachingService = cachingService; + + _previewGeneratorSettings = new PreviewGeneratorSettings(); + _previewCollection = new AssetPreviewCollection(); + + _previewGeneratorSettings.OnGenerationTypeChanged += RefreshPreviewList; + _previewGeneratorSettings.OnGenerationPathsChanged += RefreshPreviewList; + + Create(); + RefreshPreviewList(); + } + + private void Create() + { + CreateDescription(); + CreateSettings(); + CreateGenerateButton(); + CreatePreviewList(); + } + + private void CreateDescription() + { + _descriptionElement = new PreviewWindowDescriptionElement(); + Add(_descriptionElement); + } + + private void CreateSettings() + { + _settingsElement = new PreviewGeneratorSettingsElement(_previewGeneratorSettings); + Add(_settingsElement); + } + + private void CreateGenerateButton() + { + _generateButtonElement = new PreviewGenerateButtonElement(_previewGeneratorSettings); + _generateButtonElement.OnGenerate += GeneratePreviews; + Add(_generateButtonElement); + } + + private void CreatePreviewList() + { + _previewCollectionElement = new PreviewCollectionElement(_previewCollection); + Add(_previewCollectionElement); + } + + private async void GeneratePreviews() + { + try + { + _settingsElement.SetEnabled(false); + _generateButtonElement.SetEnabled(false); + _previewCollectionElement.SetEnabled(false); + + var generator = _previewGeneratorSettings.CreateGenerator(); + generator.OnProgressChanged += DisplayProgress; + var result = await generator.Generate(); + generator.OnProgressChanged -= DisplayProgress; + + if (!result.Success) + { + EditorUtility.DisplayDialog("Error", result.Exception.Message, "OK"); + Debug.LogException(result.Exception); + return; + } + + RefreshPreviewList(); + } + finally + { + _settingsElement.SetEnabled(true); + _generateButtonElement.SetEnabled(true); + _previewCollectionElement.SetEnabled(true); + EditorUtility.ClearProgressBar(); + } + } + + private void DisplayProgress(float progress) + { + EditorUtility.DisplayProgressBar("Generating", "Generating previews...", progress); + } + + public void LoadSettings(PreviewGenerationSettings settings) + { + _previewGeneratorSettings.LoadSettings(settings); + } + + private void RefreshPreviewList() + { + if (!_cachingService.GetCachedMetadata(out _previewDatabase)) + _previewDatabase = new PreviewDatabase(); + + var paths = _previewGeneratorSettings.GetGenerationPaths(); + var guids = AssetDatabase.FindAssets("", paths.ToArray()); + var displayedPreviews = new List(); + + foreach (var entry in _previewDatabase.Previews) + { + if (!entry.Exists()) + continue; + + if (entry.Type != _previewGeneratorSettings.GetGenerationType()) + continue; + + if (!guids.Any(x => x == entry.Guid)) + continue; + + displayedPreviews.Add(entry); + } + + _previewCollection.Refresh(_previewGeneratorSettings.GetGenerationType(), displayedPreviews); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs.meta new file mode 100644 index 00000000..5c2a7161 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 94d417240bb510d469acb8a11f15b277 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/UI/Views/PreviewListView.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility.meta new file mode 100644 index 00000000..92fdd4fe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 99cf24252c136f246bfa4b02a69fe992 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs new file mode 100644 index 00000000..1a304f0a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs @@ -0,0 +1,96 @@ +using UnityEngine; + +namespace AssetStoreTools.Previews.Utility +{ + internal static class GraphicsUtility + { + public static Texture2D GetTextureFromCamera(Camera camera, int desiredWidth, int desiredHeight, int desiredDepth) + { + var texture = new Texture2D(desiredWidth, desiredHeight); + var originalRenderTexture = RenderTexture.active; + var renderTexture = RenderTexture.GetTemporary(desiredWidth, desiredHeight, desiredDepth); + var cameraInitiallyEnabled = camera.enabled; + + try + { + if (cameraInitiallyEnabled) + camera.enabled = false; + + camera.targetTexture = renderTexture; + camera.Render(); + + RenderTexture.active = renderTexture; + texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); + texture.Apply(); + } + finally + { + camera.targetTexture = null; + RenderTexture.active = originalRenderTexture; + RenderTexture.ReleaseTemporary(renderTexture); + camera.enabled = cameraInitiallyEnabled; + } + + return texture; + } + + public static Texture2D ResizeTexture(Texture2D source, int desiredWidth, int desiredHeight) + { + var texture = new Texture2D(desiredWidth, desiredHeight); + var originalRenderTexture = RenderTexture.active; + var renderTexture = RenderTexture.GetTemporary(desiredWidth, desiredHeight, 32); + + try + { + RenderTexture.active = renderTexture; + Graphics.Blit(source, renderTexture); + + texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); + texture.Apply(); + } + finally + { + RenderTexture.active = originalRenderTexture; + RenderTexture.ReleaseTemporary(renderTexture); + } + + return texture; + } + + public static Texture2D ResizeTextureNormalMap(Texture2D source, int desiredWidth, int desiredHeight) + { + var texture = new Texture2D(desiredWidth, desiredHeight); + var originalRenderTexture = RenderTexture.active; + var renderTexture = RenderTexture.GetTemporary(desiredWidth, desiredHeight, 32, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); + + try + { + RenderTexture.active = renderTexture; + Graphics.Blit(source, renderTexture); + + texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); + + for (int i = 0; i < texture.width; i++) + { + for (int j = 0; j < texture.height; j++) + { + var color = texture.GetPixel(i, j); + color.b = color.r; + color.r = color.a; + color.a = 1; + texture.SetPixel(i, j, color); + } + } + + texture.Apply(); + } + finally + { + RenderTexture.active = originalRenderTexture; + RenderTexture.ReleaseTemporary(renderTexture); + } + + return texture; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs.meta new file mode 100644 index 00000000..9acc1c26 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f0a4fc8f266b4dd41a59693dd581e232 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/GraphicsUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs new file mode 100644 index 00000000..ab93f979 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs @@ -0,0 +1,72 @@ +using AssetStoreTools.Previews.Data; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Previews.Utility +{ + internal static class PreviewConvertUtility + { + public static string ConvertFilename(Object asset, FileNameFormat format) + { + string fileName = string.Empty; + + switch (format) + { + case FileNameFormat.Guid: + AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _); + fileName = guid; + break; + case FileNameFormat.FullAssetPath: + var assetPath = AssetDatabase.GetAssetPath(asset); + + if (assetPath.StartsWith("Assets/")) + fileName = assetPath.Substring("Assets/".Length); + else if (assetPath.StartsWith("Packages/")) + fileName = assetPath.Substring("Packages/".Length); + + fileName = fileName.Replace("/", "_"); + break; + case FileNameFormat.AssetName: + fileName = asset.name; + break; + default: + throw new System.Exception("Undefined format"); + } + + return fileName; + } + + public static string ConvertExtension(PreviewFormat format) + { + switch (format) + { + case PreviewFormat.JPG: + return "jpg"; + case PreviewFormat.PNG: + return "png"; + default: + throw new System.Exception("Undefined format"); + } + } + + public static string ConvertFilenameWithExtension(Object asset, FileNameFormat nameFormat, PreviewFormat imageFormat) + { + var filename = ConvertFilename(asset, nameFormat); + var extension = ConvertExtension(imageFormat); + return $"{filename}.{extension}"; + } + + public static byte[] ConvertTexture(Texture2D texture, PreviewFormat format) + { + switch (format) + { + case PreviewFormat.JPG: + return texture.EncodeToJPG(); + case PreviewFormat.PNG: + return texture.EncodeToPNG(); + default: + throw new System.Exception("Undefined format"); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs.meta new file mode 100644 index 00000000..e9b337dd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 700eaf82299628d44853599774664bea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewConvertUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs new file mode 100644 index 00000000..8ca2b3a1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs @@ -0,0 +1,196 @@ +using System; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +#if AST_URP_AVAILABLE +using UnityEngine.Rendering.Universal; +#endif +#if AST_HDRP_AVAILABLE +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; +#endif + +namespace AssetStoreTools.Previews.Utility +{ + internal static class PreviewSceneUtility + { + private const string PreviewSceneName = "Preview Generation In Progress"; + private static readonly Color BackgroundColor = new Color(82f / 255, 82f / 255, 82f / 255); + private static readonly Color BackgroundColorHDRP = new Color(38f / 255, 38f / 255, 38f / 255); + + public static async Task OpenPreviewSceneForCurrentPipeline() + { + // Wait for an Editor frame to avoid recursive player loop internal errors + await WaitForEditorUpdate(); + + switch (RenderPipelineUtility.GetCurrentPipeline()) + { + case RenderPipeline.BiRP: + await OpenPreviewSceneBiRP(); + break; +#if AST_URP_AVAILABLE + case RenderPipeline.URP: + await OpenPreviewSceneURP(); + break; +#endif +#if AST_HDRP_AVAILABLE + case RenderPipeline.HDRP: + await OpenPreviewSceneHDRP(); + break; +#endif + default: + throw new NotImplementedException("Undefined Render Pipeline"); + } + } + + private static async Task WaitForEditorUpdate() + { + var updateCalled = false; + var delayCalled = false; + + void Update() + { + EditorApplication.update -= Update; + updateCalled = true; + } + + EditorApplication.update += Update; + while (!updateCalled) + await Task.Delay(10); + + void DelayCall() + { + EditorApplication.delayCall -= DelayCall; + delayCalled = true; + } + + EditorApplication.delayCall += DelayCall; + while (!delayCalled) + await Task.Delay(10); + } + + public static async Task OpenPreviewSceneBiRP() + { + OpenNewScene(); + + CreateSceneCamera(); + CreateSceneLighting(); + + await WaitForLighting(); + } + + private static void OpenNewScene() + { + EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); + var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + scene.name = PreviewSceneName; + } + + private static Camera CreateSceneCamera() + { + var cameraGO = new GameObject() { name = "Camera" }; + var camera = cameraGO.AddComponent(); + camera.enabled = false; + camera.tag = "MainCamera"; + + camera.nearClipPlane = 0.01f; + camera.farClipPlane = 100000; + camera.clearFlags = CameraClearFlags.SolidColor; + camera.backgroundColor = BackgroundColor; + + return camera; + } + + private static Light CreateSceneLighting() + { + var lightGO = new GameObject() { name = "Lights" }; + lightGO.transform.rotation = Quaternion.Euler(45, 225, 0); + var light = lightGO.AddComponent(); + light.intensity = 0.75f; + light.type = LightType.Directional; + light.shadows = LightShadows.None; + + return light; + } + + private static async Task WaitForLighting() + { + while (!DynamicGI.isConverged) + await Task.Delay(100); + + await Task.Yield(); + } + +#if AST_URP_AVAILABLE + public static async Task OpenPreviewSceneURP() + { + OpenNewScene(); + + var camera = CreateSceneCamera(); + camera.gameObject.AddComponent(); + + var lighting = CreateSceneLighting(); + lighting.intensity = 0.5f; + lighting.gameObject.AddComponent(); + + await WaitForLighting(); + } +#endif + +#if AST_HDRP_AVAILABLE + public static async Task OpenPreviewSceneHDRP() + { + OpenNewScene(); + + var camera = CreateSceneCamera(); + var cameraData = camera.gameObject.AddComponent(); + cameraData.clearColorMode = HDAdditionalCameraData.ClearColorMode.Color; + cameraData.backgroundColorHDR = BackgroundColorHDRP; + + var light = CreateSceneLighting(); + var lightData = light.gameObject.AddComponent(); + lightData.SetIntensity(5000, LightUnit.Lux); + + CreateHDRPVolumeProfile(); + + await WaitForLighting(); + } + + private static Volume CreateHDRPVolumeProfile() + { + var volumeGO = new GameObject() { name = "Volume" }; + var volume = volumeGO.gameObject.AddComponent(); + + var profile = VolumeProfile.CreateInstance(); + volume.profile = profile; + volume.isGlobal = true; + + var exposure = profile.Add(); + exposure.active = true; + + exposure.mode.overrideState = true; + exposure.mode.value = ExposureMode.Fixed; + + exposure.fixedExposure.overrideState = true; + exposure.fixedExposure.value = 11; + + var fog = profile.Add(); + fog.active = true; + + fog.enabled.overrideState = true; + fog.enabled.value = false; + +#if AST_HDRP_AVAILABLE_V12 + var volumetricClouds = profile.Add(); + volumetricClouds.active = true; + + volumetricClouds.enable.overrideState = true; + volumetricClouds.enable.value = false; +#endif + + return volume; + } +#endif + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs.meta new file mode 100644 index 00000000..c11d3fbe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 63fa5650920e7914dae6fe76badac249 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/PreviewSceneUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs new file mode 100644 index 00000000..028f96db --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs @@ -0,0 +1,10 @@ +namespace AssetStoreTools.Previews.Utility +{ + internal enum RenderPipeline + { + Unknown = 0, + BiRP = 1, + URP = 2, + HDRP = 3 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs.meta new file mode 100644 index 00000000..cbc59290 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c43c7ce2b9090ab49bb8944bc6bdb3c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipeline.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs new file mode 100644 index 00000000..c8e79d52 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs @@ -0,0 +1,32 @@ +ο»Ώusing UnityEngine.Rendering; +#if AST_URP_AVAILABLE +using UnityEngine.Rendering.Universal; +#endif +#if AST_HDRP_AVAILABLE +using UnityEngine.Rendering.HighDefinition; +#endif + +namespace AssetStoreTools.Previews.Utility +{ + internal static class RenderPipelineUtility + { + public static RenderPipeline GetCurrentPipeline() + { + var currentPipelineAsset = GraphicsSettings.currentRenderPipeline; + if (currentPipelineAsset == null) + return RenderPipeline.BiRP; + +#if AST_URP_AVAILABLE + if (currentPipelineAsset is UniversalRenderPipelineAsset) + return RenderPipeline.URP; +#endif + +#if AST_HDRP_AVAILABLE + if (currentPipelineAsset is HDRenderPipelineAsset) + return RenderPipeline.HDRP; +#endif + + return RenderPipeline.Unknown; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs.meta new file mode 100644 index 00000000..96956b5a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5e42bdf53cd8b51429b10a6742ec5272 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Scripts/Utility/RenderPipelineUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles.meta new file mode 100644 index 00000000..50a00183 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 70d30555bce30014a9143c3d003105bf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss new file mode 100644 index 00000000..c363a3d6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss @@ -0,0 +1,210 @@ +/* Asset Preview Description */ + +.asset-preview-description { + flex-direction: column; + flex-shrink: 0; + + margin: 10px 5px 2px 5px; + padding: 2px 4px; +} + +.asset-preview-description-simple-container { + flex-direction: column; + flex-wrap: wrap; +} + +.asset-preview-description-simple-label { + white-space: normal; +} + +.asset-preview-description-hyperlink-button { + margin: 0; + padding: 0; + + align-self: flex-start; + cursor: link; +} + +.asset-preview-description-show-button { + margin-top: 12px; +} + +.asset-preview-description-hide-button { + margin-top: 12px; +} + +.asset-preview-description-full-container { + margin-top: 12px; +} + +.asset-preview-description-full-label { + white-space: normal; +} + +/* Asset Preview Settings */ + +.preview-settings { + flex-direction: column; + flex-shrink: 0; + + margin: 0px 5px 2px 5px; + padding: 2px 4px; +} + +.preview-settings-selection-row { + flex-direction: row; + flex-grow: 1; + + margin-top: 10px; + padding: 0 3px 0 2px; +} + +.preview-settings-selection-label-help-row { + flex-direction: row; + flex-shrink: 1; + flex-grow: 0; + + align-self: center; + align-items: center; + justify-content: flex-start; + + width: 120px; +} + +.preview-settings-selection-label-help-row > Label { + -unity-font-style: bold; +} + +.preview-settings-selection-label-help-row > Image { + height: 16px; + width: 16px; +} + +.preview-settings-selection-dropdown { + flex-grow: 1; + flex-shrink: 1; + + align-self: stretch; + + margin-right: 0; + margin-left: 3px; + padding: 1px 4px; +} + +/* Preview Paths */ + +.preview-paths { + flex-direction: column; + flex-grow: 1; + flex-shrink: 0; + + margin-bottom: 10px; + padding: 0; +} + +.preview-paths-box { + flex-grow: 1; + flex-direction: column; +} + +.preview-paths-scroll-view { + flex-grow: 1; + height: 100px; + margin-left: 3px; +} + +.preview-paths-scroll-view > .unity-scroll-view__content-viewport +{ + margin-left: 1px; +} + +.preview-paths-scroll-view > * > .unity-scroll-view__content-container +{ + padding: 0 0 0 0; +} + +.preview-paths-scroll-view > * > .unity-scroll-view__vertical-scroller +{ + margin: -1px 0; +} + +.preview-paths-scroll-view-bottom-row { + flex-direction: row-reverse; + margin: -1px 0 0 3px; +} + +.preview-paths-add-button { + margin: 3px 0 0 0; + align-self: center; +} + +.preview-paths-path-row { + flex-direction: row; + flex-grow: 1; + + margin-top: 2px; + padding: 0 5px 0 2px; +} + +.preview-paths-path-row-input-field { + flex-grow: 1; + flex-shrink: 1; + + padding-left: 5px; + + white-space: normal; + -unity-text-align: middle-left; +} + +.preview-paths-path-row-remove-button { + width: 20px; + height: 20px; + margin-left: 2px; + margin-right: 1px; + padding: 1px 0 0 0; +} + +/* Generate Button */ + +.preview-generate-button { + align-self: stretch; + + height: 25px; + margin-left: 2px; +} + +/* Asset Preview List Element */ + +.preview-list { + margin-top: 10px; + flex-grow: 1; +} + +.preview-list-image { + width: 140px; + height: 160px; + margin: 5px; + padding: 5px; + justify-content: space-between; +} + +.preview-list-image:hover{ + background-color: #444444; +} + +.preview-list-image > Image { + flex-shrink: 0; + max-width: 100%; + max-height: 100%; + -unity-background-scale-mode: scale-to-fit; + align-self: center; +} + +.preview-list-image > Label { + align-self: center; + overflow: hidden; + text-overflow: ellipsis; + margin-top: 2px; + padding: 0; + -unity-text-align: middle-center; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss.meta new file mode 100644 index 00000000..14dfd5de --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 095b74bd60b187c418dcc4cd47aa696d +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Styles/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss new file mode 100644 index 00000000..6dff0ddc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss @@ -0,0 +1,67 @@ +.primary-colors { + /* Light - lighter */ + background-color: rgb(220, 220, 220); + /* Light - middle */ + background-color: rgb(200, 200, 200); + /* Light - darker */ + background-color: rgb(180, 180, 180); + + /* Dark - lighter */ + background-color: rgb(78, 78, 78); + /* Dark - middle */ + background-color: rgb(68, 68, 68); + /* Dark - darker */ + background-color: rgb(58, 58, 58); + + /* Border color - light */ + border-color: rgb(200, 200, 200); + /* Border color - dark */ + border-color: rgb(33, 33, 33); +} + +/* Asset Preview Description */ + +.asset-preview-description-hyperlink-button { + color: rgb(68, 113, 229); + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.asset-preview-description-hyperlink-button:hover { + color: rgb(68, 133, 229); +} + +.asset-preview-description-hyperlink-button:active { + color: rgb(68, 93, 229); +} + +/* Asset Preview Settings */ + +.preview-settings-selection-label-help-row > Image { + --unity-image: resource("d__Help@2x"); +} + +.preview-settings-selection-dropdown { + color: rgb(238, 238, 238); + background-color: rgb(88, 88, 88); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(36, 36, 36); +} + +/* Preview Paths */ + +.preview-paths-scroll-view { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(58, 58, 58); +} + +.preview-paths-scroll-view > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.preview-paths-path-row-input-field:hover { + background-color: rgb(78, 78, 78); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss.meta new file mode 100644 index 00000000..8295d423 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 1c04ee69303d45644bb3971a4e8ce952 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss new file mode 100644 index 00000000..b98e1cd4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss @@ -0,0 +1,67 @@ +.primary-colors { + /* Light - lighter */ + background-color: rgb(220, 220, 220); + /* Light - middle */ + background-color: rgb(200, 200, 200); + /* Light - darker */ + background-color: rgb(180, 180, 180); + + /* Dark - lighter */ + background-color: rgb(50, 50, 50); + /* Dark - middle */ + background-color: rgb(28, 28, 28); + /* Dark - darker */ + background-color: rgb(0, 0, 0); + + /* Border color - light */ + border-color: rgb(200, 200, 200); + /* Border color - dark */ + border-color: rgb(33, 33, 33); +} + +/* Asset Preview Description */ + +.asset-preview-description-hyperlink-button { + color: rgb(68, 113, 229); + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.asset-preview-description-hyperlink-button:hover { + color: rgb(68, 133, 229); +} + +.asset-preview-description-hyperlink-button:active { + color: rgb(68, 93, 229); +} + +/* Asset Preview Settings */ + +.preview-settings-selection-label-help-row > Image { + --unity-image: resource("_Help@2x"); +} + +.preview-settings-selection-dropdown { + color: rgb(9, 9, 9); + background-color: rgb(228, 228, 228); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(178, 178, 178); +} + +/* Preview Paths */ + +.preview-paths-scroll-view { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(180, 180, 180); +} + +.preview-paths-scroll-view > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.preview-paths-path-row-input-field:hover { + background-color: rgb(200, 200, 200); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss.meta new file mode 100644 index 00000000..f522d082 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 38ae9e6ef965cae43902ba22967938ee +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Previews/Styles/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef b/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef new file mode 100644 index 00000000..b0ba405b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef @@ -0,0 +1,36 @@ +{ + "name": "asset-store-tools-editor", + "rootNamespace": "", + "references": [ + "Unity.RenderPipelines.Universal.Runtime", + "Unity.RenderPipelines.Core.Runtime", + "Unity.RenderPipelines.HighDefinition.Runtime" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.render-pipelines.universal", + "expression": "1.0.0", + "define": "AST_URP_AVAILABLE" + }, + { + "name": "com.unity.render-pipelines.high-definition", + "expression": "1.0.0", + "define": "AST_HDRP_AVAILABLE" + }, + { + "name": "com.unity.render-pipelines.high-definition", + "expression": "12.0.0", + "define": "AST_HDRP_AVAILABLE_V12" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef.meta b/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef.meta new file mode 100644 index 00000000..5e135086 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: c183be512f4485d40a3437fabd6c81cf +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Unity.AssetStoreTools.Editor.asmdef + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader.meta new file mode 100644 index 00000000..b4b86614 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9722d52df16aab742b26fe301782c74c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons.meta new file mode 100644 index 00000000..7026063d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab9d0e254817f4f4589a6a378d77babc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-dark.png b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f54f1a23228b4a5640825aee9ba25ccdc9aa5509 GIT binary patch literal 337 zcmV-X0j~auP)yr?k zO-rI1&>Ozw+QP}}WryCTG>oXY^4AV&3 z!QgoAO@>Z`NklCE2Zjf{gG~B@U4QS}`4czm~6Rg&l93aum zu2xUdTdlN0{IzJ?0>Ut~ce`CWO;Z3LEs|Q(w5%wK@5Q|BcLYh2IKwa;;dW$5E48w_ zu6wSkigBUKfLU#lzsj zUK5<)2(a31r-6yhglfV_);%~AfSWL-+n5L=$@9ELRdX{DlP#za1|MA4tqsFSV83{t zCz__23CT}m^L_sV#{*W2(Y_H*qAhCKH)URd(ht1KCfcxnJ@1Zy$>>iYDMj+0Fls2& hx$pZ7&m-c0BtNsViP-ATJE{Nx002ovPDHLkV1kx_uMGeI literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png.meta new file mode 100644 index 00000000..769b5ba0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png.meta @@ -0,0 +1,130 @@ +fileFormatVersion: 2 +guid: 7c0661b9a6385a3488c075711f368cf4 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/account-light.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/open-in-browser.png b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/open-in-browser.png new file mode 100644 index 0000000000000000000000000000000000000000..245875b4df64816f61a939405c6b33a38d121bab GIT binary patch literal 878 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
+}br+wE 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%0Ajkl|$X1m`*2UvL4|z1#txFuHfs{VDwo=E<%>W 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 I?>_qf0QQ_UdH?_b literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png.meta new file mode 100644 index 00000000..7676a317 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png.meta @@ -0,0 +1,135 @@ +fileFormatVersion: 2 +guid: 003e2710f9b29d94c87632022a3c7c48 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 18 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-dark.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png new file mode 100644 index 0000000000000000000000000000000000000000..621e906e33598c8bfdbe38dd5f6761ef5a98e07f GIT binary patch literal 33281 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 literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png.meta new file mode 100644 index 00000000..71625547 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png.meta @@ -0,0 +1,142 @@ +fileFormatVersion: 2 +guid: 8e0749dce5b14cc46b73b0303375c162 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + cookieLightType: 1 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Icons/publisher-portal-light.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts.meta new file mode 100644 index 00000000..63c6efc3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15b24ad8f9d236249910fb8eef1e30ea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data.meta new file mode 100644 index 00000000..1382bf8a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 930cfc857321b1048bf9607d4c8f89d3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions.meta new file mode 100644 index 00000000..73728d0f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 771776e4d51c47945b3449d4de948c00 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs new file mode 100644 index 00000000..84033b51 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs @@ -0,0 +1,34 @@ +using System; +using UnityEngine; +using PackageModel = AssetStoreTools.Api.Models.Package; + +namespace AssetStoreTools.Uploader.Data +{ + internal interface IPackage + { + string PackageId { get; } + string VersionId { get; } + string Name { get; } + string Status { get; } + string Category { get; } + bool IsCompleteProject { get; } + string RootGuid { get; } + string RootPath { get; } + string ProjectPath { get; } + string Modified { get; } + string Size { get; } + bool IsDraft { get; } + Texture2D Icon { get; } + + event Action OnUpdate; + event Action OnIconUpdate; + + string FormattedSize(); + string FormattedModified(); + + void UpdateData(PackageModel source); + void UpdateIcon(Texture2D texture); + + PackageModel ToModel(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs.meta new file mode 100644 index 00000000..190b689d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b92f2ed98d0b31a479aa2bfd95528fbd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackage.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs new file mode 100644 index 00000000..d82520f8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Uploader.Data +{ + internal interface IPackageContent + { + event Action OnActiveWorkflowChanged; + + IWorkflow GetActiveWorkflow(); + List GetAvailableWorkflows(); + void SetActiveWorkflow(IWorkflow workflow); + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs.meta new file mode 100644 index 00000000..61420459 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 45ce41158c3174149b7056a30ac901db +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageContent.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs new file mode 100644 index 00000000..c35936b2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Uploader.Data +{ + internal interface IPackageGroup + { + string Name { get; } + List Packages { get; } + + event Action> OnPackagesSorted; + event Action> OnPackagesFiltered; + + void Sort(PackageSorting sortingType); + void Filter(string filter); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs.meta new file mode 100644 index 00000000..4a358083 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f683845071b8891498156d95a1a5c2dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IPackageGroup.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs new file mode 100644 index 00000000..c6e9b813 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs @@ -0,0 +1,36 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Exporter; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Data +{ + internal interface IWorkflow + { + string Name { get; } + string DisplayName { get; } + string PackageName { get; } + string PackageExtension { get; } + bool IsPathSet { get; } + + event Action OnChanged; + event Action OnUploadStateChanged; + + bool GenerateHighQualityPreviews { get; set; } + ValidationSettings LastValidationSettings { get; } + ValidationResult LastValidationResult { get; } + + IEnumerable GetAllPaths(); + ValidationResult Validate(); + Task ExportPackage(string outputPath); + Task ValidatePackageUploadedVersions(); + + Task UploadPackage(string exportedPackagePath); + void AbortUpload(); + void ResetUploadStatus(); + Task RefreshPackage(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs.meta new file mode 100644 index 00000000..c8381f3e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7a2f796eadafa774bae89cf3939611dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs new file mode 100644 index 00000000..6987b911 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs @@ -0,0 +1,18 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Uploader.Services.Analytics.Data; +using System; +using System.Threading.Tasks; +using UnityEngine.Analytics; + +namespace AssetStoreTools.Uploader.Data +{ + internal interface IWorkflowServices + { + Task GetPackageUploadedVersions(IPackage package, int timeoutMs); + Task UploadPackage(IPackageUploader uploader, IProgress progress); + void StopUploading(IPackageUploader uploader); + AnalyticsResult SendAnalytic(IAssetStoreAnalytic data); + Task UpdatePackageData(IPackage package); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs.meta new file mode 100644 index 00000000..88c381c5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0ae017363fa41ff4d9926dc4a5852246 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/IWorkflowServices.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs new file mode 100644 index 00000000..cd3462af --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs @@ -0,0 +1,253 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Exporter; +using AssetStoreTools.Previews; +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Previews.Generators; +using AssetStoreTools.Uploader.Services.Analytics.Data; +using AssetStoreTools.Utility; +using AssetStoreTools.Validator; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine; + +namespace AssetStoreTools.Uploader.Data +{ + internal abstract class WorkflowBase : IWorkflow + { + protected IPackage Package; + + public abstract string Name { get; } + public abstract string DisplayName { get; } + public string PackageName => Package.Name; + public abstract string PackageExtension { get; } + public abstract bool IsPathSet { get; } + + protected string LocalPackageGuid; + protected string LocalPackagePath; + protected string LocalProjectPath; + + public bool GenerateHighQualityPreviews { get; set; } + public ValidationSettings LastValidationSettings { get; private set; } + public ValidationResult LastValidationResult { get; private set; } + + private IWorkflowServices _services; + private IPackageUploader _activeUploader; + + public abstract event Action OnChanged; + public event Action OnUploadStateChanged; + + public WorkflowBase(IPackage package, IWorkflowServices services) + { + Package = package; + _services = services; + } + + public abstract IEnumerable GetAllPaths(); + + public abstract IValidator CreateValidator(); + + public ValidationResult Validate() + { + var validator = CreateValidator(); + var result = CreateValidator().Validate(); + + LastValidationSettings = validator.Settings; + LastValidationResult = result; + + return result; + } + + protected IPreviewGenerator CreatePreviewGenerator(List inputPaths) + { + PreviewGenerationSettings settings; + IPreviewGenerator generator; + + // Filter out ProjectSettings + inputPaths = inputPaths.Where(x => x == "Assets" || x.StartsWith("Assets/") || x.StartsWith("Packages/")).ToList(); + + if (!GenerateHighQualityPreviews) + { + settings = new NativePreviewGenerationSettings() + { + InputPaths = inputPaths.ToArray(), + OverwriteExisting = false, + OutputPath = Constants.Previews.Native.DefaultOutputPath, + Format = Constants.Previews.Native.DefaultFormat, + PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat, + WaitForPreviews = Constants.Previews.Native.DefaultWaitForPreviews, + ChunkedPreviewLoading = Constants.Previews.Native.DefaultChunkedPreviewLoading, + ChunkSize = Constants.Previews.Native.DefaultChunkSize + }; + + generator = new NativePreviewGenerator((NativePreviewGenerationSettings)settings); + } + else + { + settings = new CustomPreviewGenerationSettings() + { + InputPaths = inputPaths.ToArray(), + OverwriteExisting = false, + Width = Constants.Previews.Custom.DefaultWidth, + Height = Constants.Previews.Custom.DefaultHeight, + Depth = Constants.Previews.Custom.DefaultDepth, + NativeWidth = Constants.Previews.Custom.DefaultNativeWidth, + NativeHeight = Constants.Previews.Custom.DefaultNativeHeight, + OutputPath = Constants.Previews.Custom.DefaultOutputPath, + Format = Constants.Previews.Custom.DefaultFormat, + PreviewFileNamingFormat = Constants.Previews.DefaultFileNameFormat, + AudioSampleColor = Constants.Previews.Custom.DefaultAudioSampleColor, + AudioBackgroundColor = Constants.Previews.Custom.DefaultAudioBackgroundColor, + }; + + generator = new CustomPreviewGenerator((CustomPreviewGenerationSettings)settings); + } + + return generator; + } + + public abstract IPackageExporter CreateExporter(string outputPath); + + public virtual async Task ExportPackage(string outputPath) + { + var exporter = CreateExporter(outputPath); + var result = await exporter.Export(); + return result; + } + + public async Task ValidatePackageUploadedVersions() + { + var unityVersionSupported = string.Compare(Application.unityVersion, Constants.Uploader.MinRequiredUnitySupportVersion, StringComparison.Ordinal) >= 0; + if (unityVersionSupported) + return true; + + var response = await _services.GetPackageUploadedVersions(Package, 5000); + if (response.Cancelled || response.Success == false) + return true; + + return response.UnityVersions.Any(x => string.Compare(x, Constants.Uploader.MinRequiredUnitySupportVersion, StringComparison.Ordinal) >= 0); + } + + private bool ValidatePackageBeforeUpload(string packagePath, out string error) + { + error = string.Empty; + + if (!File.Exists(packagePath)) + { + error = $"File '{packagePath}' was not found."; + return false; + } + + if (!ValidatePackageSize(packagePath, out error)) + { + return false; + } + + return true; + } + + private bool ValidatePackageSize(string packagePath, out string error) + { + error = string.Empty; + + long packageSize = new FileInfo(packagePath).Length; + long packageSizeLimit = Constants.Uploader.MaxPackageSizeBytes; + + if (packageSize <= packageSizeLimit) + return true; + + float packageSizeInGB = packageSize / (float)1073741824; // (1024 * 1024 * 1024) + float maxPackageSizeInGB = packageSizeLimit / (float)1073741824; + error = $"The size of your package ({packageSizeInGB:0.0} GB) exceeds the maximum allowed package size of {maxPackageSizeInGB:0} GB. " + + $"Please reduce the size of your package."; + + return false; + } + + public async Task UploadPackage(string packagePath) + { + if (!ValidatePackageBeforeUpload(packagePath, out var error)) + { + return new PackageUploadResponse() { Success = false, Status = UploadStatus.Fail, Exception = new Exception(error) }; + } + + _activeUploader = CreatePackageUploader(packagePath); + var progress = new Progress(); + + var time = System.Diagnostics.Stopwatch.StartNew(); + + progress.ProgressChanged += ReportUploadProgress; + var response = await _services.UploadPackage(_activeUploader, progress); + progress.ProgressChanged -= ReportUploadProgress; + + // Send analytics + time.Stop(); + if (!response.Cancelled) + SendAnalytics(packagePath, response.Status, time.Elapsed.TotalSeconds); + + OnUploadStateChanged?.Invoke(response.Status, null); + _activeUploader = null; + return response; + } + + protected abstract IPackageUploader CreatePackageUploader(string exportedPackagePath); + + private void ReportUploadProgress(object _, float value) + { + OnUploadStateChanged?.Invoke(null, value); + } + + private void SendAnalytics(string packagePath, UploadStatus uploadStatus, double timeTakenSeconds) + { + try + { + var analytic = new PackageUploadAnalytic( + packageId: Package.PackageId, + category: Package.Category, + usedValidator: LastValidationResult != null, + validationSettings: LastValidationSettings, + validationResult: LastValidationResult, + uploadFinishedReason: uploadStatus, + timeTaken: timeTakenSeconds, + packageSize: new FileInfo(packagePath).Length, + workflow: Name + ); + + var result = _services.SendAnalytic(analytic); + } + catch (Exception e) { ASDebug.LogError($"Could not send analytics: {e}"); } + } + + public void AbortUpload() + { + if (_activeUploader != null) + _services.StopUploading(_activeUploader); + + _activeUploader = null; + } + + public void ResetUploadStatus() + { + OnUploadStateChanged?.Invoke(UploadStatus.Default, 0f); + } + + public async Task RefreshPackage() + { + var response = await _services.UpdatePackageData(Package); + if (!response.Success) + return; + + Package.UpdateData(response.Package); + } + + public abstract bool IsPathValid(string path, out string reason); + + protected abstract void Serialize(); + + protected abstract void Deserialize(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs.meta new file mode 100644 index 00000000..a7a6a651 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d0e87ee17aa944c42b1c335abe19daaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Abstractions/WorkflowBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs new file mode 100644 index 00000000..967bd9ba --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs @@ -0,0 +1,329 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Exporter; +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Utility; +using AssetStoreTools.Validator; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; + +namespace AssetStoreTools.Uploader.Data +{ + internal class AssetsWorkflow : WorkflowBase + { + public override string Name => "AssetsWorkflow"; + public override string DisplayName => "From Assets Folder"; + public override string PackageExtension => ".unitypackage"; + public override bool IsPathSet => !string.IsNullOrEmpty(_mainExportPath); + public bool IsCompleteProject => Package.IsCompleteProject; + + private AssetsWorkflowState _stateData; + + private string _mainExportPath; + private bool _includeDependencies; + private List _dependencies; + private List _specialFolders; + + public override event Action OnChanged; + + // Special folders that would not work if not placed directly in the 'Assets' folder + private readonly string[] _extraAssetFolderNames = + { + "Editor Default Resources", "Gizmos", "Plugins", + "StreamingAssets", "Standard Assets", "WebGLTemplates", + "ExternalDependencyManager", "XR" + }; + + public AssetsWorkflow(IPackage package, AssetsWorkflowState stateData, IWorkflowServices services) + : base(package, services) + { + _stateData = stateData; + Deserialize(); + } + + public string GetMainExportPath() + { + return _mainExportPath; + } + + public void SetMainExportPath(string path, bool serialize) + { + _mainExportPath = path; + SetMetadata(); + if (serialize) + Serialize(); + } + + private void SetMetadata() + { + LocalPackageGuid = AssetDatabase.AssetPathToGUID(_mainExportPath); + LocalPackagePath = _mainExportPath; + LocalProjectPath = _mainExportPath; + } + + public bool GetIncludeDependencies() + { + return _includeDependencies; + } + + public void SetIncludeDependencies(bool value, bool serialize) + { + _includeDependencies = value; + // Note: make sure that exporting does not fail when + // a serialized dependency that has been removed from a project is sent to exporter + if (serialize) + Serialize(); + } + + public List GetDependencies() + { + return _dependencies; + } + + public void SetDependencies(IEnumerable dependencies, bool serialize) + { + _dependencies.Clear(); + foreach (var dependency in dependencies) + { + if (!PackageUtility.GetPackageByPackageName(dependency, out var package)) + continue; + _dependencies.Add(package); + } + + if (serialize) + Serialize(); + } + + public List GetSpecialFolders() + { + return _specialFolders; + } + + public void SetSpecialFolders(IEnumerable specialFolders, bool serialize) + { + _specialFolders.Clear(); + foreach (var folder in specialFolders) + { + _specialFolders.Add(folder); + } + + if (serialize) + Serialize(); + } + + public override bool IsPathValid(string path, out string error) + { + error = string.Empty; + + var pathIsFolder = Directory.Exists(path); + if (!pathIsFolder) + { + error = "Path must point to a valid folder"; + return false; + } + + var pathWithinAssetsFolder = path.StartsWith("Assets/") && path != "Assets/"; + if (pathWithinAssetsFolder) + return true; + + var pathIsAssetsFolder = path == "Assets" || path == "Assets/"; + if (pathIsAssetsFolder) + { + var assetsFolderSelectionAllowed = Package.IsCompleteProject; + if (assetsFolderSelectionAllowed) + return true; + + error = "'Assets' folder is only available for packages tagged as a 'Complete Project'."; + return false; + } + + error = "Selected folder path must be within the project's Assets."; + return false; + } + + public List GetAvailableDependencies() + { + var registryPackages = PackageUtility.GetAllRegistryPackages(); + return registryPackages.Select(x => x.name).ToList(); + } + + public List GetAvailableSpecialFolders() + { + var specialFolders = new List(); + + foreach (var extraAssetFolderName in _extraAssetFolderNames) + { + var fullExtraPath = "Assets/" + extraAssetFolderName; + + if (!Directory.Exists(fullExtraPath)) + continue; + + if (_mainExportPath.ToLower().StartsWith(fullExtraPath.ToLower())) + continue; + + // Don't include nested paths + if (!fullExtraPath.ToLower().StartsWith(_mainExportPath.ToLower())) + specialFolders.Add(fullExtraPath); + } + + return specialFolders; + } + + public override IEnumerable GetAllPaths() + { + var paths = new List() + { + _mainExportPath + }; + paths.AddRange(GetSpecialFolders()); + + return paths; + } + + public override IValidator CreateValidator() + { + var validationPaths = GetAllPaths(); + + var validationSettings = new CurrentProjectValidationSettings() + { + Category = Package.Category, + ValidationPaths = validationPaths.ToList(), + ValidationType = ValidationType.UnityPackage + }; + + var validator = new CurrentProjectValidator(validationSettings); + return validator; + } + + public override IPackageExporter CreateExporter(string outputPath) + { + var exportPaths = GetAllPaths().ToList(); + + if (IsCompleteProject && !exportPaths.Contains("ProjectSettings")) + { + exportPaths.Add("ProjectSettings"); + } + + var dependenciesToInclude = new List(); + if (_includeDependencies) + { + dependenciesToInclude.AddRange(_dependencies.Select(x => x.name)); + } + + if (ASToolsPreferences.Instance.UseLegacyExporting) + { + var exportSettings = new LegacyExporterSettings() + { + ExportPaths = exportPaths.ToArray(), + OutputFilename = outputPath, + IncludeDependencies = _includeDependencies, + }; + + return new LegacyPackageExporter(exportSettings); + } + else + { + var exportSettings = new DefaultExporterSettings() + { + ExportPaths = exportPaths.ToArray(), + OutputFilename = outputPath, + Dependencies = dependenciesToInclude.ToArray(), + PreviewGenerator = CreatePreviewGenerator(exportPaths), + }; + + return new DefaultPackageExporter(exportSettings); + } + } + + protected override IPackageUploader CreatePackageUploader(string exportedPackagePath) + { + var uploaderSettings = new UnityPackageUploadSettings() + { + UnityPackagePath = exportedPackagePath, + VersionId = Package.VersionId, + RootGuid = LocalPackageGuid, + RootPath = LocalPackagePath, + ProjectPath = LocalProjectPath + }; + + var uploader = new UnityPackageUploader(uploaderSettings); + return uploader; + } + + protected override void Serialize() + { + _stateData.SetMainPath(_mainExportPath); + _stateData.SetIncludeDependencies(_includeDependencies); + _stateData.SetDependencies(_dependencies.Select(x => x.name)); + _stateData.SetSpecialFolders(_specialFolders); + OnChanged?.Invoke(); + } + + protected override void Deserialize() + { + _mainExportPath = _stateData.GetMainPath(); + + _specialFolders = new List(); + foreach (var path in _stateData.GetSpecialFolders()) + { + _specialFolders.Add(path); + } + + _includeDependencies = _stateData.GetIncludeDependencies(); + + _dependencies = new List(); + foreach (var dependency in _stateData.GetDependencies()) + { + if (!PackageUtility.GetPackageByPackageName(dependency, out var package)) + continue; + + _dependencies.Add(package); + } + + DeserializeFromUploadedData(); + } + + private void DeserializeFromUploadedData() + { + DeserializeFromUploadedDataByGuid(); + DeserializeFromUploadedDataByPath(); + } + + private void DeserializeFromUploadedDataByGuid() + { + if (!string.IsNullOrEmpty(_mainExportPath)) + return; + + var lastUploadedGuid = Package.RootGuid; + if (string.IsNullOrEmpty(lastUploadedGuid)) + return; + + var potentialPackagePath = AssetDatabase.GUIDToAssetPath(lastUploadedGuid); + DeserializeFromUploadedDataByPath(potentialPackagePath); + } + + private void DeserializeFromUploadedDataByPath() + { + if (!string.IsNullOrEmpty(_mainExportPath)) + return; + + var lastUploadedPath = Package.ProjectPath; + if (string.IsNullOrEmpty(lastUploadedPath)) + return; + + DeserializeFromUploadedDataByPath(lastUploadedPath); + } + + private void DeserializeFromUploadedDataByPath(string path) + { + if (string.IsNullOrEmpty(path) || !IsPathValid(path, out var _)) + return; + + _mainExportPath = path; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs.meta new file mode 100644 index 00000000..4e07adf0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4657d35aaf9d70948a0840dc615f64ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/AssetsWorkflow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs new file mode 100644 index 00000000..3759313d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs @@ -0,0 +1,251 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Exporter; +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Utility; +using AssetStoreTools.Validator; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.PackageManager; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; +using PackageManager = UnityEditor.PackageManager; + +namespace AssetStoreTools.Uploader.Data +{ + internal class HybridPackageWorkflow : WorkflowBase + { + public override string Name => "HybridPackageWorkflow"; + public override string DisplayName => "Local UPM Package"; + public override string PackageExtension => ".unitypackage"; + public override bool IsPathSet => _packageInfo != null; + + private HybridPackageWorkflowState _stateData; + + private PackageInfo _packageInfo; + private List _dependencies; + + public override event Action OnChanged; + + public HybridPackageWorkflow(IPackage package, HybridPackageWorkflowState stateData, IWorkflowServices services) + : base(package, services) + { + _stateData = stateData; + Deserialize(); + } + + public PackageInfo GetPackage() + { + return _packageInfo; + } + + public void SetPackage(PackageInfo packageInfo, bool serialize) + { + if (packageInfo == null) + throw new ArgumentException("Package is null"); + + _packageInfo = packageInfo; + SetMetadata(); + if (serialize) + Serialize(); + } + + public void SetPackage(string packageManifestPath, bool serialize) + { + if (!PackageUtility.GetPackageByManifestPath(packageManifestPath, out var package)) + throw new ArgumentException("Path does not correspond to a valid package"); + + SetPackage(package, serialize); + } + + private void SetMetadata() + { + LocalPackageGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(_packageInfo.GetManifestAsset())); + LocalPackagePath = _packageInfo.assetPath; + LocalProjectPath = _packageInfo.name; + } + + public List GetDependencies() + { + return _dependencies; + } + + public void SetDependencies(IEnumerable dependencies, bool serialize) + { + _dependencies.Clear(); + foreach (var dependency in dependencies) + { + if (!PackageUtility.GetPackageByPackageName(dependency, out var package)) + continue; + _dependencies.Add(package); + } + + if (serialize) + Serialize(); + } + + public List GetAvailableDependencies() + { + var availableDependencies = new List(); + if (_packageInfo == null) + return availableDependencies; + + var packageDependencies = _packageInfo.dependencies.Select(x => x.name); + foreach (var dependency in packageDependencies) + { + if (!PackageUtility.GetPackageByPackageName(dependency, out var package)) + continue; + + if (package.source != PackageManager.PackageSource.Local + && package.source != PackageManager.PackageSource.Embedded) + continue; + + availableDependencies.Add(package); + } + + return availableDependencies; + } + + public override IEnumerable GetAllPaths() + { + var paths = new List(); + + if (_packageInfo == null) + return paths; + + paths.Add(_packageInfo.assetPath); + paths.AddRange(_dependencies.Select(x => x.assetPath)); + + return paths; + } + + public override bool IsPathValid(string path, out string reason) + { + reason = string.Empty; + + if (!PackageUtility.GetPackageByManifestPath(path, out var package)) + { + reason = "Selected path must point to a package manifest for a package that is imported into the current project"; + return false; + } + + var packageSourceValid = package.source == PackageSource.Embedded || package.source == PackageSource.Local; + if (!packageSourceValid) + { + reason = "Selected package must be a local or an embedded package"; + return false; + } + + return true; + } + + public override IValidator CreateValidator() + { + var validationPaths = GetAllPaths(); + + var validationSettings = new CurrentProjectValidationSettings() + { + Category = Package?.Category, + ValidationPaths = validationPaths.ToList(), + ValidationType = ValidationType.UnityPackage + }; + + var validator = new CurrentProjectValidator(validationSettings); + return validator; + } + + public override IPackageExporter CreateExporter(string outputPath) + { + var exportPaths = GetAllPaths(); + + var exportSettings = new DefaultExporterSettings() + { + ExportPaths = exportPaths.ToArray(), + OutputFilename = outputPath, + PreviewGenerator = CreatePreviewGenerator(exportPaths.ToList()) + }; + + return new DefaultPackageExporter(exportSettings); + } + + protected override IPackageUploader CreatePackageUploader(string exportedPackagePath) + { + var uploaderSettings = new UnityPackageUploadSettings() + { + UnityPackagePath = exportedPackagePath, + VersionId = Package.VersionId, + RootGuid = LocalPackageGuid, + RootPath = LocalPackagePath, + ProjectPath = LocalProjectPath + }; + + var uploader = new UnityPackageUploader(uploaderSettings); + return uploader; + } + + protected override void Serialize() + { + if (_packageInfo == null) + return; + + _stateData.SetPackageName(_packageInfo.name); + _stateData.SetPackageDependencies(_dependencies.Select(x => x.name).OrderBy(x => x)); + OnChanged?.Invoke(); + } + + protected override void Deserialize() + { + var packageName = _stateData.GetPackageName(); + if (PackageUtility.GetPackageByPackageName(packageName, out var package)) + _packageInfo = package; + + _dependencies = new List(); + var dependencies = _stateData.GetPackageDependencies(); + foreach (var dependency in dependencies) + { + if (PackageUtility.GetPackageByPackageName(dependency, out var packageDependency)) + _dependencies.Add(packageDependency); + } + + DeserializeFromUploadedData(); + } + + private void DeserializeFromUploadedData() + { + DeserializeFromUploadedDataByPackageName(); + DeserializeFromUploadedDataByPackageGuid(); + } + + private void DeserializeFromUploadedDataByPackageName() + { + if (_packageInfo != null) + return; + + var lastUploadedPackageName = Package.ProjectPath; + if (!PackageUtility.GetPackageByPackageName(lastUploadedPackageName, out var package)) + return; + + _packageInfo = package; + } + + private void DeserializeFromUploadedDataByPackageGuid() + { + if (_packageInfo != null) + return; + + var lastUploadedGuid = Package.RootGuid; + if (string.IsNullOrEmpty(lastUploadedGuid)) + return; + + var potentialPackageManifestPath = AssetDatabase.GUIDToAssetPath(lastUploadedGuid); + if (string.IsNullOrEmpty(potentialPackageManifestPath) || !IsPathValid(potentialPackageManifestPath, out var _)) + return; + + if (!PackageUtility.GetPackageByManifestPath(potentialPackageManifestPath, out var package)) + return; + + _packageInfo = package; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs.meta new file mode 100644 index 00000000..8feba578 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3061839aba3894246a20195639eeda1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/HybridPackageWorkflow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs new file mode 100644 index 00000000..1a984e56 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs @@ -0,0 +1,91 @@ +using System; +using UnityEngine; +using PackageModel = AssetStoreTools.Api.Models.Package; + +namespace AssetStoreTools.Uploader.Data +{ + internal class Package : IPackage + { + private PackageModel _source; + + public string PackageId => _source.PackageId; + public string VersionId => _source.VersionId; + public string Name => _source.Name; + public string Status => _source.Status; + public string Category => _source.Category; + public bool IsCompleteProject => _source.IsCompleteProject; + public string RootGuid => _source.RootGuid; + public string RootPath => _source.RootPath; + public string ProjectPath => _source.ProjectPath; + public string Modified => _source.Modified; + public string Size => _source.Size; + public string IconUrl => _source.IconUrl; + public bool IsDraft => Status.Equals("draft", StringComparison.OrdinalIgnoreCase); + public Texture2D Icon { get; private set; } + + public event Action OnUpdate; + public event Action OnIconUpdate; + + public Package(PackageModel packageSource) + { + _source = packageSource; + } + + public void UpdateIcon(Texture2D texture) + { + if (texture == null) + return; + + Icon = texture; + OnIconUpdate?.Invoke(); + } + + public string FormattedSize() + { + var defaultSize = "0.00 MB"; + if (float.TryParse(Size, out var sizeBytes)) + return $"{sizeBytes / (1024f * 1024f):0.00} MB"; + + return defaultSize; + } + + public string FormattedModified() + { + var defaultDate = "Unknown"; + if (DateTime.TryParse(Modified, out var dt)) + return dt.Date.ToString("yyyy-MM-dd"); + + return defaultDate; + } + + public void UpdateData(PackageModel source) + { + if (source == null) + throw new ArgumentException("Provided package is null"); + + _source = source; + OnUpdate?.Invoke(); + } + + public PackageModel ToModel() + { + var model = new PackageModel() + { + PackageId = _source.PackageId, + VersionId = _source.VersionId, + Name = _source.Name, + Status = _source.Status, + Category = _source.Category, + IsCompleteProject = _source.IsCompleteProject, + RootGuid = _source.RootGuid, + RootPath = _source.RootPath, + ProjectPath = _source.ProjectPath, + Modified = _source.Modified, + Size = _source.Size, + IconUrl = _source.IconUrl + }; + + return model; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs.meta new file mode 100644 index 00000000..7e4f9df7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fc2198164bbd6394b87c51a74fe2915e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Package.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs new file mode 100644 index 00000000..bac6c08e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs @@ -0,0 +1,68 @@ +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Uploader.Services; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Uploader.Data +{ + internal class PackageContent : IPackageContent + { + private IWorkflow _activeWorkflow; + private List _workflows; + private WorkflowStateData _workflowStateData; + + private ICachingService _cachingService; + + public event Action OnActiveWorkflowChanged; + + public PackageContent(List workflows, WorkflowStateData workflowStateData, ICachingService cachingService) + { + _workflows = workflows; + _workflowStateData = workflowStateData; + _cachingService = cachingService; + + foreach (var workflow in _workflows) + { + workflow.OnChanged += Serialize; + } + + Deserialize(); + } + + public IWorkflow GetActiveWorkflow() + { + return _activeWorkflow; + } + + public void SetActiveWorkflow(IWorkflow workflow) + { + _activeWorkflow = workflow; + + OnActiveWorkflowChanged?.Invoke(_activeWorkflow); + + Serialize(); + } + + public List GetAvailableWorkflows() + { + return _workflows; + } + + private void Serialize() + { + _workflowStateData.SetActiveWorkflow(_activeWorkflow.Name); + _cachingService.CacheWorkflowStateData(_workflowStateData); + } + + private void Deserialize() + { + var serializedWorkflow = _workflowStateData.GetActiveWorkflow(); + var workflow = _workflows.FirstOrDefault(x => x.Name == serializedWorkflow); + if (workflow != null) + _activeWorkflow = workflow; + else + _activeWorkflow = _workflows[0]; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs.meta new file mode 100644 index 00000000..641626ba --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f36086f9380a49949ab45463abc6fee8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageContent.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs new file mode 100644 index 00000000..78e9aa1a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Uploader.Data +{ + internal class PackageGroup : IPackageGroup + { + private class FilteredPackage + { + public IPackage Package; + public bool IsInFilter; + } + + public string Name { get; private set; } + public List Packages { get; private set; } + + private List _filteredPackages; + + public event Action> OnPackagesSorted; + public event Action> OnPackagesFiltered; + + public PackageGroup(string name, List packages) + { + Name = name; + Packages = packages; + + _filteredPackages = new List(); + foreach (var package in Packages) + _filteredPackages.Add(new FilteredPackage() { Package = package, IsInFilter = true }); + } + + public void Sort(PackageSorting sortingType) + { + switch (sortingType) + { + case PackageSorting.Name: + _filteredPackages = _filteredPackages.OrderBy(x => x.Package.Name).ToList(); + break; + case PackageSorting.Date: + _filteredPackages = _filteredPackages.OrderByDescending(x => x.Package.Modified).ToList(); + break; + case PackageSorting.Category: + _filteredPackages = _filteredPackages.OrderBy(x => x.Package.Category).ThenBy(x => x.Package.Name).ToList(); + break; + default: + throw new NotImplementedException("Undefined sorting type"); + } + + OnPackagesSorted?.Invoke(_filteredPackages.Where(x => x.IsInFilter).Select(x => x.Package).ToList()); + } + + public void Filter(string filter) + { + foreach (var package in _filteredPackages) + { + bool inFilter = package.Package.Name.ToLower().Contains(filter.ToLower()); + package.IsInFilter = inFilter; + } + + OnPackagesFiltered?.Invoke(_filteredPackages.Where(x => x.IsInFilter).Select(x => x.Package).ToList()); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs.meta new file mode 100644 index 00000000..a8f9623b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c9cc17f6b95bb2c42913a1451b9af29e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageGroup.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs new file mode 100644 index 00000000..7ef00e42 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs @@ -0,0 +1,9 @@ +namespace AssetStoreTools.Uploader.Data +{ + internal enum PackageSorting + { + Name, + Category, + Date + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs.meta new file mode 100644 index 00000000..de09cab3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b1d61d0de90e022469b5ed312d4b7beb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/PackageSorting.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization.meta new file mode 100644 index 00000000..2ba3d4cc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b05e199f21f636439844a8cc7e2c225 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs new file mode 100644 index 00000000..4970e732 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs @@ -0,0 +1,59 @@ +using AssetStoreTools.Utility; +using Newtonsoft.Json; +using System.IO; +using UnityEditor; + +namespace AssetStoreTools.Uploader.Data.Serialization +{ + internal class AssetPath + { + [JsonProperty("path")] + private string _path = string.Empty; + [JsonProperty("guid")] + private string _guid = string.Empty; + + [JsonIgnore] + public string Path { get => _path; set { SetAssetPath(value); } } + [JsonIgnore] + public string Guid { get => _guid; set { _guid = value; } } + + public AssetPath() { } + + public AssetPath(string path) + { + SetAssetPath(path); + } + + private void SetAssetPath(string path) + { + _path = path.Replace("\\", "/"); + if (TryGetGuid(_path, out var guid)) + _guid = guid; + } + + private bool TryGetGuid(string path, out string guid) + { + guid = string.Empty; + + var relativePath = FileUtility.AbsolutePathToRelativePath(path, ASToolsPreferences.Instance.EnableSymlinkSupport); + + if (!relativePath.StartsWith("Assets/") && !relativePath.StartsWith("Packages/")) + return false; + + guid = AssetDatabase.AssetPathToGUID(relativePath); + return !string.IsNullOrEmpty(guid); + } + + public override string ToString() + { + var pathFromGuid = AssetDatabase.GUIDToAssetPath(_guid); + if (!string.IsNullOrEmpty(pathFromGuid) && (File.Exists(pathFromGuid) || Directory.Exists(pathFromGuid))) + return pathFromGuid; + + if (File.Exists(_path) || Directory.Exists(_path)) + return _path; + + return string.Empty; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs.meta new file mode 100644 index 00000000..3529bc17 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 920ff8e4ffe77ec44bede985593cc187 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetPath.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs new file mode 100644 index 00000000..8d955c36 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs @@ -0,0 +1,77 @@ +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace AssetStoreTools.Uploader.Data.Serialization +{ + internal class AssetsWorkflowState + { + [JsonProperty("main_path")] + private AssetPath _mainPath; + [JsonProperty("special_folders")] + private List _specialFolders; + [JsonProperty("include_dependencies")] + private bool _includeDependencies; + [JsonProperty("dependencies")] + private List _dependencies; + + public AssetsWorkflowState() + { + _mainPath = new AssetPath(); + _includeDependencies = false; + _dependencies = new List(); + _specialFolders = new List(); + } + + public string GetMainPath() + { + return _mainPath?.ToString(); + } + + public void SetMainPath(string path) + { + _mainPath = new AssetPath(path); + } + + public bool GetIncludeDependencies() + { + return _includeDependencies; + } + + public void SetIncludeDependencies(bool value) + { + _includeDependencies = value; + } + + public List GetDependencies() + { + return _dependencies; + } + + public void SetDependencies(IEnumerable dependencies) + { + _dependencies = new List(); + foreach (var dependency in dependencies) + _dependencies.Add(dependency); + } + + public List GetSpecialFolders() + { + var specialFolders = new List(); + foreach (var folder in _specialFolders) + { + var path = folder.ToString(); + if (!string.IsNullOrEmpty(path)) + specialFolders.Add(path); + } + + return specialFolders; + } + + public void SetSpecialFolders(List specialFolders) + { + _specialFolders = new List(); + foreach (var path in specialFolders) + _specialFolders.Add(new AssetPath(path)); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs.meta new file mode 100644 index 00000000..8c7d4771 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 505f0a5aa753b4445a467539e150190a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/AssetsWorkflowStateData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs new file mode 100644 index 00000000..58e428ea --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace AssetStoreTools.Uploader.Data.Serialization +{ + internal class HybridPackageWorkflowState + { + [JsonProperty("package_name")] + private string _packageName; + [JsonProperty("dependencies")] + private List _dependencies; + + public HybridPackageWorkflowState() + { + _packageName = string.Empty; + _dependencies = new List(); + } + + public string GetPackageName() + { + return _packageName; + } + + public void SetPackageName(string packageName) + { + _packageName = packageName; + } + + public List GetPackageDependencies() + { + return _dependencies; + } + + public void SetPackageDependencies(IEnumerable dependencies) + { + _dependencies.Clear(); + foreach (var dependency in dependencies) + _dependencies.Add(dependency); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs.meta new file mode 100644 index 00000000..7b9f72af --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2848375fcb0a4174495573190bfc3900 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/HybridPackageWorkflowState.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs new file mode 100644 index 00000000..ca14b882 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs @@ -0,0 +1,25 @@ +using Newtonsoft.Json; + +namespace AssetStoreTools.Uploader.Data.Serialization +{ + internal class UnityPackageWorkflowState + { + [JsonProperty("package_path")] + private AssetPath _packagePath; + + public UnityPackageWorkflowState() + { + _packagePath = new AssetPath(); + } + + public string GetPackagePath() + { + return _packagePath?.ToString(); + } + + public void SetPackagePath(string path) + { + _packagePath = new AssetPath(path); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs.meta new file mode 100644 index 00000000..65f718ec --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 101a66adc88639b43b07cc28214474cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/UnityPackageWorkflowStateData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs new file mode 100644 index 00000000..25e72c62 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs @@ -0,0 +1,68 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace AssetStoreTools.Uploader.Data.Serialization +{ + internal class WorkflowStateData + { + [JsonProperty("package_id")] + private string _packageId; + [JsonProperty("active_workflow")] + private string _activeWorkflow; + [JsonProperty("assets_workflow")] + private AssetsWorkflowState _assetsWorkflow; + [JsonProperty("unitypackage_workflow")] + private UnityPackageWorkflowState _unityPackageWorkflow; + [JsonProperty("hybrid_workflow")] + private HybridPackageWorkflowState _hybridPackageWorkflow; + + public WorkflowStateData() + { + _activeWorkflow = string.Empty; + + _assetsWorkflow = new AssetsWorkflowState(); + _unityPackageWorkflow = new UnityPackageWorkflowState(); + _hybridPackageWorkflow = new HybridPackageWorkflowState(); + } + + public WorkflowStateData(string packageId) : this() + { + SetPackageId(packageId); + } + + public string GetPackageId() + { + return _packageId; + } + + public void SetPackageId(string packageId) + { + _packageId = packageId; + } + + public string GetActiveWorkflow() + { + return _activeWorkflow; + } + + public void SetActiveWorkflow(string activeWorkflow) + { + _activeWorkflow = activeWorkflow; + } + + public AssetsWorkflowState GetAssetsWorkflowState() + { + return _assetsWorkflow; + } + + public UnityPackageWorkflowState GetUnityPackageWorkflowState() + { + return _unityPackageWorkflow; + } + + public HybridPackageWorkflowState GetHybridPackageWorkflowState() + { + return _hybridPackageWorkflow; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs.meta new file mode 100644 index 00000000..5fb89959 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: eecebbc83661a4f41a14e293c9fc3331 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/Serialization/WorkflowStateData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs new file mode 100644 index 00000000..6668fd6e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs @@ -0,0 +1,135 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Exporter; +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Validator; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Data +{ + internal class UnityPackageWorkflow : WorkflowBase + { + public override string Name => "UnityPackageWorkflow"; + public override string DisplayName => "Pre-exported .unitypackage"; + public override string PackageExtension => ".unitypackage"; + public override bool IsPathSet => !string.IsNullOrEmpty(_packagePath); + + private UnityPackageWorkflowState _workflowState; + private string _packagePath; + + public override event Action OnChanged; + + public UnityPackageWorkflow(IPackage package, UnityPackageWorkflowState workflowState, IWorkflowServices services) + : base(package, services) + { + _workflowState = workflowState; + Deserialize(); + } + + public void SetPackagePath(string path, bool serialize) + { + _packagePath = path; + SetMetadata(); + if (serialize) + Serialize(); + } + + private void SetMetadata() + { + LocalPackageGuid = string.Empty; + LocalPackagePath = string.Empty; + LocalProjectPath = _packagePath; + } + + public string GetPackagePath() + { + return _packagePath; + } + + public override IEnumerable GetAllPaths() + { + return new List() { _packagePath }; + } + + public override bool IsPathValid(string path, out string error) + { + error = null; + + var pathIsUnityPackage = path.EndsWith(PackageExtension); + var pathExists = File.Exists(path); + + if (!pathIsUnityPackage || !pathExists) + { + error = "Path must point to a .unitypackage file"; + return false; + } + + return true; + } + + public override IValidator CreateValidator() + { + var validationSettings = new ExternalProjectValidationSettings() + { + Category = Package.Category, + PackagePath = GetPackagePath() + }; + + var validator = new ExternalProjectValidator(validationSettings); + return validator; + } + + public override IPackageExporter CreateExporter(string _) + { + // This workflow already takes exported packages as input + throw new InvalidOperationException($"{nameof(UnityPackageWorkflow)} already takes exported packages as input"); + } + + public override Task ExportPackage(string _) + { + return Task.FromResult(new PackageExporterResult() { Success = true, ExportedPath = GetPackagePath() }); + } + + protected override IPackageUploader CreatePackageUploader(string exportedPackagePath) + { + var uploaderSettings = new UnityPackageUploadSettings() + { + VersionId = Package.VersionId, + UnityPackagePath = exportedPackagePath, + RootGuid = LocalPackageGuid, + RootPath = LocalPackagePath, + ProjectPath = LocalProjectPath + }; + + var uploader = new UnityPackageUploader(uploaderSettings); + return uploader; + } + + protected override void Serialize() + { + _workflowState.SetPackagePath(_packagePath); + OnChanged?.Invoke(); + } + + protected override void Deserialize() + { + _packagePath = _workflowState.GetPackagePath(); + DeserializeFromUploadedData(); + } + + private void DeserializeFromUploadedData() + { + if (!string.IsNullOrEmpty(_packagePath)) + return; + + var potentialPackagePath = Package.ProjectPath; + if (string.IsNullOrEmpty(potentialPackagePath) || !IsPathValid(potentialPackagePath, out var _)) + return; + + _packagePath = potentialPackagePath; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs.meta new file mode 100644 index 00000000..0179b484 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 47ee1db30792bf84aa1af8be7ce0dee6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/UnityPackageWorkflow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs new file mode 100644 index 00000000..525374dc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs @@ -0,0 +1,53 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Uploader.Services.Analytics; +using AssetStoreTools.Uploader.Services.Analytics.Data; +using AssetStoreTools.Uploader.Services.Api; +using System; +using System.Threading.Tasks; +using UnityEngine.Analytics; + +namespace AssetStoreTools.Uploader.Data +{ + internal class WorkflowServices : IWorkflowServices + { + private IPackageDownloadingService _downloadingService; + private IPackageUploadingService _uploadingService; + private IAnalyticsService _analyticsService; + + public WorkflowServices( + IPackageDownloadingService downloadingService, + IPackageUploadingService uploadingService, + IAnalyticsService analyticsService) + { + _downloadingService = downloadingService; + _uploadingService = uploadingService; + _analyticsService = analyticsService; + } + + public Task GetPackageUploadedVersions(IPackage package, int timeoutMs) + { + return _downloadingService.GetPackageUploadedVersions(package, timeoutMs); + } + + public Task UploadPackage(IPackageUploader uploader, IProgress progress) + { + return _uploadingService.UploadPackage(uploader, progress); + } + + public void StopUploading(IPackageUploader uploader) + { + _uploadingService.StopUploading(uploader); + } + + public Task UpdatePackageData(IPackage package) + { + return _downloadingService.UpdatePackageData(package); + } + + public AnalyticsResult SendAnalytic(IAssetStoreAnalytic data) + { + return _analyticsService.Send(data); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs.meta new file mode 100644 index 00000000..535d4494 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a78b96ae30966e94ba9ffdddf19c1692 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Data/WorkflowServices.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services.meta new file mode 100644 index 00000000..6d1acef2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9787842821f3d041904186d0e0cc61d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics.meta new file mode 100644 index 00000000..30b3cbf5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17f95678acdb51548908d81be7146b5b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs new file mode 100644 index 00000000..a2f6e1e4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs @@ -0,0 +1,45 @@ +using AssetStoreTools.Uploader.Services.Analytics.Data; +using UnityEditor; +using UnityEngine.Analytics; +#if !UNITY_2023_2_OR_NEWER +using AnalyticsConstants = AssetStoreTools.Constants.Uploader.Analytics; +#endif + +namespace AssetStoreTools.Uploader.Services.Analytics +{ + internal class AnalyticsService : IAnalyticsService + { + public AnalyticsResult Send(IAssetStoreAnalytic analytic) + { + if (!EditorAnalytics.enabled) + return AnalyticsResult.AnalyticsDisabled; + + if (!Register(analytic)) + return AnalyticsResult.AnalyticsDisabled; + +#if UNITY_2023_2_OR_NEWER + return EditorAnalytics.SendAnalytic(analytic); +#else + return EditorAnalytics.SendEventWithLimit(analytic.EventName, + analytic.Data, + analytic.EventVersion); +#endif + } + + private bool Register(IAssetStoreAnalytic analytic) + { +#if UNITY_2023_2_OR_NEWER + return true; +#else + var result = EditorAnalytics.RegisterEventWithLimit( + eventName: analytic.EventName, + maxEventPerHour: AnalyticsConstants.MaxEventsPerHour, + maxItems: AnalyticsConstants.MaxNumberOfElements, + vendorKey: AnalyticsConstants.VendorKey, + ver: analytic.EventVersion); + + return result == AnalyticsResult.Ok; +#endif + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs.meta new file mode 100644 index 00000000..0b230a0c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 408b5b0136da9ca4f9598b8688f6210e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/AnalyticsService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data.meta new file mode 100644 index 00000000..59ec0e40 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: df1fca726619f2f4fae3bd93b0ef5a8b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs new file mode 100644 index 00000000..74edf0e0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs @@ -0,0 +1,46 @@ +using AssetStoreTools.Api; +using System; +#if UNITY_2023_2_OR_NEWER +using UnityEngine.Analytics; +#endif +using AnalyticsConstants = AssetStoreTools.Constants.Uploader.Analytics; + +namespace AssetStoreTools.Uploader.Services.Analytics.Data +{ +#if UNITY_2023_2_OR_NEWER + [AnalyticInfo + (eventName: AnalyticsConstants.AuthenticationAnalytics.EventName, + vendorKey: AnalyticsConstants.VendorKey, + version: AnalyticsConstants.AuthenticationAnalytics.EventVersion, + maxEventsPerHour: AnalyticsConstants.MaxEventsPerHour, + maxNumberOfElements: AnalyticsConstants.MaxNumberOfElements)] +#endif + internal class AuthenticationAnalytic : BaseAnalytic + { + [Serializable] + public class AuthenticationAnalyticData : BaseAnalyticData + { + public string AuthenticationType; + public string PublisherId; + } + + public override string EventName => AnalyticsConstants.AuthenticationAnalytics.EventName; + public override int EventVersion => AnalyticsConstants.AuthenticationAnalytics.EventVersion; + + private AuthenticationAnalyticData _data; + + public AuthenticationAnalytic(IAuthenticationType authenticationType, string publisherId) + { + _data = new AuthenticationAnalyticData + { + AuthenticationType = authenticationType.GetType().Name, + PublisherId = publisherId + }; + } + + protected override BaseAnalyticData GetData() + { + return _data; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs.meta new file mode 100644 index 00000000..b7c28ede --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4b9389e3ee578484493d36775c75baa1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/AuthenticationAnalytic.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs new file mode 100644 index 00000000..60c3396b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs @@ -0,0 +1,35 @@ +using System; +#if UNITY_2023_2_OR_NEWER +using UnityEngine.Analytics; +#endif + +namespace AssetStoreTools.Uploader.Services.Analytics.Data +{ + internal abstract class BaseAnalytic : IAssetStoreAnalytic + { + [Serializable] + public class BaseAnalyticData : IAssetStoreAnalyticData + { + public string ToolVersion = Constants.Api.ApiVersion; + } + + public abstract string EventName { get; } + public abstract int EventVersion { get; } + + public IAssetStoreAnalyticData Data => GetData(); + protected abstract BaseAnalyticData GetData(); + +#if UNITY_2023_2_OR_NEWER + public bool TryGatherData(out IAnalytic.IData data, [System.Diagnostics.CodeAnalysis.NotNullWhen(false)] out Exception error) + { + error = null; + data = Data; + + if (data == null) + error = new Exception("Analytic data is null"); + + return error == null; + } +#endif + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs.meta new file mode 100644 index 00000000..a423c7e9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 51ec1e4b6505b694ab01f7c523744fbc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/BaseAnalytic.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs new file mode 100644 index 00000000..5207ca01 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs @@ -0,0 +1,16 @@ +#if UNITY_2023_2_OR_NEWER +using UnityEngine.Analytics; +#endif + +namespace AssetStoreTools.Uploader.Services.Analytics.Data +{ + internal interface IAssetStoreAnalytic +#if UNITY_2023_2_OR_NEWER + : IAnalytic +#endif + { + string EventName { get; } + int EventVersion { get; } + IAssetStoreAnalyticData Data { get; } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs.meta new file mode 100644 index 00000000..18e344dd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6e9b53aa176bbed48bafa538c26df304 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalytic.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs new file mode 100644 index 00000000..e08b8f80 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs @@ -0,0 +1,8 @@ +ο»Ώnamespace AssetStoreTools.Uploader.Services.Analytics.Data +{ + interface IAssetStoreAnalyticData +#if UNITY_2023_2_OR_NEWER + : UnityEngine.Analytics.IAnalytic.IData +#endif + { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs.meta new file mode 100644 index 00000000..a79af8db --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b639e25d9b9abd34d8eb67b0e17dde86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/IAssetStoreAnalyticData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs new file mode 100644 index 00000000..d8a34793 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs @@ -0,0 +1,72 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Validator.Data; +using System; +#if UNITY_2023_2_OR_NEWER +using UnityEngine.Analytics; +#endif +using AnalyticsConstants = AssetStoreTools.Constants.Uploader.Analytics; + +namespace AssetStoreTools.Uploader.Services.Analytics.Data +{ +#if UNITY_2023_2_OR_NEWER + [AnalyticInfo + (eventName: AnalyticsConstants.PackageUploadAnalytics.EventName, + vendorKey: AnalyticsConstants.VendorKey, + version: AnalyticsConstants.PackageUploadAnalytics.EventVersion, + maxEventsPerHour: AnalyticsConstants.MaxEventsPerHour, + maxNumberOfElements: AnalyticsConstants.MaxNumberOfElements)] +#endif + internal class PackageUploadAnalytic : BaseAnalytic + { + [Serializable] + public class PackageUploadAnalyticData : BaseAnalyticData + { + public string PackageId; + public string Category; + public bool UsedValidator; + public string ValidatorResults; + public string UploadFinishedReason; + public double TimeTaken; + public long PackageSize; + public string Workflow; + public string EndpointUrl; + } + + public override string EventName => AnalyticsConstants.PackageUploadAnalytics.EventName; + public override int EventVersion => AnalyticsConstants.PackageUploadAnalytics.EventVersion; + + private PackageUploadAnalyticData _data; + + public PackageUploadAnalytic( + string packageId, + string category, + bool usedValidator, + ValidationSettings validationSettings, + ValidationResult validationResult, + UploadStatus uploadFinishedReason, + double timeTaken, + long packageSize, + string workflow + ) + { + _data = new PackageUploadAnalyticData() + { + PackageId = packageId, + Category = category, + UsedValidator = usedValidator, + ValidatorResults = usedValidator ? + ValidationResultsSerializer.ConstructValidationResultsJson(validationSettings, validationResult) : null, + UploadFinishedReason = uploadFinishedReason.ToString(), + TimeTaken = timeTaken, + PackageSize = packageSize, + Workflow = workflow, + EndpointUrl = Constants.Api.AssetStoreBaseUrl + }; + } + + protected override BaseAnalyticData GetData() + { + return _data; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs.meta new file mode 100644 index 00000000..6e329ebc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6cc34de12dce9964b9c900d5bb159966 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/PackageUploadAnalytic.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs new file mode 100644 index 00000000..1bb7b56a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs @@ -0,0 +1,91 @@ +using AssetStoreTools.Validator.Data; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; +using System.Reflection; + +namespace AssetStoreTools.Uploader.Services.Analytics.Data +{ + internal class ValidationResultsSerializer + { + private class ValidationResults + { + public bool HasCompilationErrors; + public string[] Paths; + public Dictionary Results; + } + + private class TestResultOutcome + { + public int IntegerValue; + public string StringValue; + + public TestResultOutcome(TestResultStatus status) + { + IntegerValue = (int)status; + StringValue = status.ToString(); + } + } + + private class ValidationResultsResolver : DefaultContractResolver + { + private static ValidationResultsResolver _instance; + public static ValidationResultsResolver Instance => _instance ?? (_instance = new ValidationResultsResolver()); + + private Dictionary _propertyConversion; + + private ValidationResultsResolver() + { + _propertyConversion = new Dictionary() + { + { nameof(ValidationResults.HasCompilationErrors), "has_compilation_errors" }, + { nameof(ValidationResults.Paths), "validation_paths" }, + { nameof(ValidationResults.Results), "validation_results" }, + { nameof(TestResultOutcome.IntegerValue), "int" }, + { nameof(TestResultOutcome.StringValue), "string" }, + }; + } + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + if (_propertyConversion.ContainsKey(property.PropertyName)) + property.PropertyName = _propertyConversion[property.PropertyName]; + + return property; + } + } + + public static string ConstructValidationResultsJson(ValidationSettings settings, ValidationResult result) + { + if (result == null) + return string.Empty; + + var resultObject = new ValidationResults(); + resultObject.HasCompilationErrors = result.HadCompilationErrors; + + switch (settings) + { + case CurrentProjectValidationSettings currentProjectValidationSettings: + resultObject.Paths = currentProjectValidationSettings.ValidationPaths.ToArray(); + break; + case ExternalProjectValidationSettings externalProjectValidationSettings: + resultObject.Paths = new string[] { externalProjectValidationSettings.PackagePath }; + break; + } + + resultObject.Results = new Dictionary(); + foreach (var test in result.Tests) + { + resultObject.Results.Add(test.Id.ToString(), new TestResultOutcome(test.Result.Status)); + } + + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = ValidationResultsResolver.Instance + }; + + return JsonConvert.SerializeObject(resultObject, serializerSettings); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs.meta new file mode 100644 index 00000000..0dddcc24 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fa15fc27c7f3d044884885b3dad73efc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/Data/ValidationResultsSerializer.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs new file mode 100644 index 00000000..a64dce1e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs @@ -0,0 +1,10 @@ +using AssetStoreTools.Uploader.Services.Analytics.Data; +using UnityEngine.Analytics; + +namespace AssetStoreTools.Uploader.Services.Analytics +{ + internal interface IAnalyticsService : IUploaderService + { + AnalyticsResult Send(IAssetStoreAnalytic analytic); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs.meta new file mode 100644 index 00000000..2924eab0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: faa1f39fc83b86b438f6e0f34f01167b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Analytics/IAnalyticsService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api.meta new file mode 100644 index 00000000..7075aa49 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4d983b64bd0866a428f937434252f537 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs new file mode 100644 index 00000000..e0028182 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs @@ -0,0 +1,100 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Models; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Uploader.Services.Analytics; +using AssetStoreTools.Uploader.Services.Analytics.Data; +using AssetStoreTools.Utility; +using System; +using System.Threading.Tasks; +using UnityEditor; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal class AuthenticationService : IAuthenticationService + { + private IAssetStoreApi _api; + private ICachingService _cachingService; + private IAnalyticsService _analyticsService; + + public User User { get; private set; } + + public AuthenticationService(IAssetStoreApi api, ICachingService cachingService, IAnalyticsService analyticsService) + { + _api = api; + _cachingService = cachingService; + _analyticsService = analyticsService; + } + + public async Task AuthenticateWithCredentials(string email, string password) + { + var authenticationType = new CredentialsAuthentication(email, password); + return await Authenticate(authenticationType); + } + + public async Task AuthenticateWithSessionToken() + { + if (!_cachingService.GetCachedSessionToken(out var cachedSessionToken)) + { + return new AuthenticationResponse() { Success = false, Exception = new Exception("No cached session token found") }; + } + + var authenticationType = new SessionAuthentication(cachedSessionToken); + return await Authenticate(authenticationType); + } + + public async Task AuthenticateWithCloudToken() + { + var authenticationType = new CloudTokenAuthentication(CloudProjectSettings.accessToken); + return await Authenticate(authenticationType); + } + + private async Task Authenticate(IAuthenticationType authenticationType) + { + var response = await _api.Authenticate(authenticationType); + HandleLoginResponse(authenticationType, response); + return response; + } + + private void HandleLoginResponse(IAuthenticationType authenticationType, AuthenticationResponse response) + { + if (!response.Success) + { + Deauthenticate(); + return; + } + + User = response.User; + _cachingService.CacheSessionToken(User.SessionId); + SendAnalytics(authenticationType, User); + } + + public bool CloudAuthenticationAvailable(out string username, out string cloudToken) + { + username = CloudProjectSettings.userName; + cloudToken = CloudProjectSettings.accessToken; + return !username.Equals("anonymous"); + } + + public void Deauthenticate() + { + _api.Deauthenticate(); + + User = null; + _cachingService.ClearCachedSessionToken(); + } + + private void SendAnalytics(IAuthenticationType authenticationType, User user) + { + try + { + // Do not send session authentication events + if (authenticationType is SessionAuthentication) + return; + + var analytic = new AuthenticationAnalytic(authenticationType, user.PublisherId); + var result = _analyticsService.Send(analytic); + } + catch (Exception e) { ASDebug.LogError($"Could not send analytics: {e}"); } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs.meta new file mode 100644 index 00000000..8aa49830 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c1c3d6578d298d049a8dcf858fd3686e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/AuthenticationService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs new file mode 100644 index 00000000..96c9ee3d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs @@ -0,0 +1,16 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Api.Responses; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal interface IAuthenticationService : IUploaderService + { + User User { get; } + Task AuthenticateWithCredentials(string email, string password); + Task AuthenticateWithSessionToken(); + Task AuthenticateWithCloudToken(); + bool CloudAuthenticationAvailable(out string username, out string cloudToken); + void Deauthenticate(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs.meta new file mode 100644 index 00000000..ecf573fe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ff0518dc0d95d3540857d138215bb900 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IAuthenticationService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs new file mode 100644 index 00000000..4cef2c0f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs @@ -0,0 +1,16 @@ +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Uploader.Data; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal interface IPackageDownloadingService : IUploaderService + { + Task GetPackageData(); + Task UpdatePackageData(IPackage package); + void ClearPackageData(); + Task GetPackageThumbnail(IPackage package); + Task GetPackageUploadedVersions(IPackage package, int timeoutMs); + void StopDownloading(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs.meta new file mode 100644 index 00000000..0471c598 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 96acd12a628311d429cc285f418f8b90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageDownloadingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs new file mode 100644 index 00000000..f1ff1d4c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs @@ -0,0 +1,16 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using System; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal interface IPackageUploadingService : IUploaderService + { + bool IsUploading { get; } + + Task UploadPackage(IPackageUploader uploader, IProgress progress); + void StopUploading(IPackageUploader package); + void StopAllUploadinng(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs.meta new file mode 100644 index 00000000..b3fd4373 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9a3d78f3bc68d3d44b4300bc8ffe69c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/IPackageUploadingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs new file mode 100644 index 00000000..5ab052fa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs @@ -0,0 +1,109 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Uploader.Data; +using System.Threading; +using System.Threading.Tasks; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal class PackageDownloadingService : IPackageDownloadingService + { + public const int MaxConcurrentTumbnailDownloads = 10; + + private IAssetStoreApi _api; + private ICachingService _cachingService; + + private int _currentDownloads; + private CancellationTokenSource _cancellationTokenSource; + + public PackageDownloadingService(IAssetStoreApi api, ICachingService cachingService) + { + _api = api; + _cachingService = cachingService; + _cancellationTokenSource = new CancellationTokenSource(); + } + + public void ClearPackageData() + { + _cachingService.DeletePackageMetadata(); + } + + public async Task GetPackageData() + { + if (!_cachingService.GetCachedPackageMetadata(out var models)) + { + var cancellationToken = _cancellationTokenSource.Token; + var packagesResponse = await _api.GetPackages(cancellationToken); + + if (packagesResponse.Cancelled || !packagesResponse.Success) + return packagesResponse; + + _cachingService.CachePackageMetadata(packagesResponse.Packages); + return packagesResponse; + } + + return new PackagesDataResponse() { Success = true, Packages = models }; + } + + public async Task UpdatePackageData(IPackage package) + { + var response = await _api.RefreshPackageMetadata(package.ToModel()); + + if (response.Success) + _cachingService.UpdatePackageMetadata(response.Package); + + return response; + } + + public async Task GetPackageThumbnail(IPackage package) + { + if (_cachingService.GetCachedPackageThumbnail(package.PackageId, out var cachedTexture)) + { + return new PackageThumbnailResponse() { Success = true, Thumbnail = cachedTexture }; + } + + var cancellationToken = _cancellationTokenSource.Token; + while (_currentDownloads >= MaxConcurrentTumbnailDownloads) + await Task.Delay(100); + + if (cancellationToken.IsCancellationRequested) + return new PackageThumbnailResponse() { Success = false, Cancelled = true }; + + _currentDownloads++; + var result = await _api.GetPackageThumbnail(package.ToModel(), cancellationToken); + _currentDownloads--; + + if (result.Success && result.Thumbnail != null) + _cachingService.CachePackageThumbnail(package.PackageId, result.Thumbnail); + + return result; + } + + public async Task GetPackageUploadedVersions(IPackage package, int timeoutMs) + { + var timeoutTokenSource = new CancellationTokenSource(); + try + { + var versionsTask = _api.GetPackageUploadedVersions(package.ToModel(), timeoutTokenSource.Token); + + // Wait for versions to be retrieved, or a timeout to occur, whichever is first + if (await Task.WhenAny(versionsTask, Task.Delay(timeoutMs)) != versionsTask) + { + timeoutTokenSource.Cancel(); + } + + return await versionsTask; + } + finally + { + timeoutTokenSource.Dispose(); + } + } + + public void StopDownloading() + { + _cancellationTokenSource.Cancel(); + _cancellationTokenSource = new CancellationTokenSource(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs.meta new file mode 100644 index 00000000..7ff441da --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: adc44e974cb91b54fac3819284b7ba82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageDownloadingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs new file mode 100644 index 00000000..53da1bb5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs @@ -0,0 +1,103 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using UnityEditor; + +namespace AssetStoreTools.Uploader.Services.Api +{ + internal class PackageUploadingService : IPackageUploadingService + { + private class UploadInProgress + { + public IPackageUploader Uploader; + public IProgress Progress = new Progress(); + public CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); + + public UploadInProgress(IPackageUploader uploader, IProgress progress) + { + Uploader = uploader; + Progress = progress; + CancellationTokenSource = new CancellationTokenSource(); + } + } + + private IAssetStoreApi _api; + private List _uploadsInProgress; + + public bool IsUploading => _uploadsInProgress.Count > 0; + + public PackageUploadingService(IAssetStoreApi api) + { + _api = api; + _uploadsInProgress = new List(); + } + + public async Task UploadPackage(IPackageUploader uploader, IProgress progress) + { + using (var cancellationTokenSource = new CancellationTokenSource()) + { + var uploadInProgress = StartTrackingUpload(uploader, progress); + var response = await _api.UploadPackage(uploadInProgress.Uploader, uploadInProgress.Progress, uploadInProgress.CancellationTokenSource.Token); + StopTrackingUpload(uploadInProgress); + + return response; + } + } + + private UploadInProgress StartTrackingUpload(IPackageUploader uploader, IProgress progress) + { + // If this is the first upload - lock reload assemblies and prevent entering play mode + if (_uploadsInProgress.Count == 0) + { + EditorApplication.LockReloadAssemblies(); + EditorApplication.playModeStateChanged += PreventEnteringPlayMode; + } + + var uploadInProgress = new UploadInProgress(uploader, progress); + _uploadsInProgress.Add(uploadInProgress); + + return uploadInProgress; + } + + private void StopTrackingUpload(UploadInProgress uploadInProgress) + { + _uploadsInProgress.Remove(uploadInProgress); + + // If this was the last upload - unlock reload assemblies and allow entering play mode + if (_uploadsInProgress.Count > 0) + return; + + EditorApplication.UnlockReloadAssemblies(); + EditorApplication.playModeStateChanged -= PreventEnteringPlayMode; + } + + private void PreventEnteringPlayMode(PlayModeStateChange change) + { + if (change != PlayModeStateChange.ExitingEditMode) + return; + + EditorApplication.ExitPlaymode(); + EditorUtility.DisplayDialog("Notice", "Entering Play Mode is not allowed while there's a package upload in progress.\n\n" + + "Please wait until the upload is finished or cancel the upload from the Asset Store Uploader window", "OK"); + } + + public void StopUploading(IPackageUploader uploader) + { + var uploadInProgress = _uploadsInProgress.FirstOrDefault(x => x.Uploader == uploader); + if (uploadInProgress == null) + return; + + uploadInProgress.CancellationTokenSource.Cancel(); + } + + public void StopAllUploadinng() + { + foreach (var uploadInProgress in _uploadsInProgress) + uploadInProgress.CancellationTokenSource.Cancel(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs.meta new file mode 100644 index 00000000..54f5defb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 22e23997fe339a74bb5355d6a88ce731 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Api/PackageUploadingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching.meta new file mode 100644 index 00000000..7267ddb5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a834946d92154754493879c5fcc7dbc9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs new file mode 100644 index 00000000..c86ee80e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs @@ -0,0 +1,157 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Utility; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.Services +{ + internal class CachingService : ICachingService + { + private VisualElement _cachedUploaderWindow; + + public bool GetCachedUploaderWindow(out VisualElement uploaderWindow) + { + uploaderWindow = _cachedUploaderWindow; + return uploaderWindow != null; + } + + public void CacheUploaderWindow(VisualElement uploaderWindow) + { + _cachedUploaderWindow = uploaderWindow; + } + + public void CacheSessionToken(string sessionToken) + { + if (string.IsNullOrEmpty(sessionToken)) + throw new ArgumentException("Session token cannot be null"); + + EditorPrefs.SetString(Constants.Cache.SessionTokenKey, sessionToken); + } + + public bool GetCachedSessionToken(out string sessionToken) + { + sessionToken = EditorPrefs.GetString(Constants.Cache.SessionTokenKey, string.Empty); + return !string.IsNullOrEmpty(sessionToken); + } + + public void ClearCachedSessionToken() + { + EditorPrefs.DeleteKey(Constants.Cache.SessionTokenKey); + } + + public bool GetCachedPackageMetadata(out List data) + { + data = new List(); + if (!CacheUtil.GetFileFromTempCache(Constants.Cache.PackageDataFileName, out var filePath)) + return false; + + try + { + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = Package.CachedPackageResolver.Instance + }; + + data = JsonConvert.DeserializeObject>(File.ReadAllText(filePath, Encoding.UTF8), serializerSettings); + return true; + } + catch + { + return false; + } + } + + public void CachePackageMetadata(List data) + { + if (data == null) + throw new ArgumentException("Package data cannot be null"); + + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = Package.CachedPackageResolver.Instance, + Formatting = Formatting.Indented + }; + + CacheUtil.CreateFileInTempCache(Constants.Cache.PackageDataFileName, JsonConvert.SerializeObject(data, serializerSettings), true); + } + + public void DeletePackageMetadata() + { + CacheUtil.DeleteFileFromTempCache(Constants.Cache.PackageDataFileName); + } + + public void UpdatePackageMetadata(Package data) + { + if (!GetCachedPackageMetadata(out var cachedData)) + return; + + var index = cachedData.FindIndex(x => x.PackageId.Equals(data.PackageId)); + if (index == -1) + { + cachedData.Add(data); + } + else + { + cachedData.RemoveAt(index); + cachedData.Insert(index, data); + } + + CachePackageMetadata(cachedData); + } + + public bool GetCachedPackageThumbnail(string packageId, out Texture2D texture) + { + texture = null; + if (!CacheUtil.GetFileFromTempCache(Constants.Cache.PackageThumbnailFileName(packageId), out var filePath)) + return false; + + texture = new Texture2D(1, 1); + texture.LoadImage(File.ReadAllBytes(filePath)); + return true; + } + + public void CachePackageThumbnail(string packageId, Texture2D texture) + { + CacheUtil.CreateFileInTempCache(Constants.Cache.PackageThumbnailFileName(packageId), texture.EncodeToPNG(), true); + } + + public bool GetCachedWorkflowStateData(string packageId, out WorkflowStateData data) + { + data = null; + + if (string.IsNullOrEmpty(packageId)) + return false; + + if (!CacheUtil.GetFileFromPersistentCache(Constants.Cache.WorkflowStateDataFileName(packageId), out var filePath)) + return false; + + try + { + data = JsonConvert.DeserializeObject(File.ReadAllText(filePath, Encoding.UTF8)); + if (string.IsNullOrEmpty(data.GetPackageId())) + return false; + } + catch + { + return false; + } + + return true; + } + + public void CacheWorkflowStateData(WorkflowStateData data) + { + if (data == null) + throw new ArgumentException("Workflow state data cannot be null"); + + CacheUtil.CreateFileInPersistentCache(Constants.Cache.WorkflowStateDataFileName(data.GetPackageId()), JsonConvert.SerializeObject(data, Formatting.Indented), true); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs.meta new file mode 100644 index 00000000..0999689e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fffaed09a3f76f945a7ececfb355f3e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/CachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs new file mode 100644 index 00000000..10772814 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs @@ -0,0 +1,25 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Uploader.Data.Serialization; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.Services +{ + internal interface ICachingService : IUploaderService + { + void CacheUploaderWindow(VisualElement uploaderWindow); + bool GetCachedUploaderWindow(out VisualElement uploaderWindow); + void CacheSessionToken(string sessionToken); + bool GetCachedSessionToken(out string sessionToken); + void ClearCachedSessionToken(); + bool GetCachedPackageMetadata(out List data); + void UpdatePackageMetadata(Package data); + void CachePackageMetadata(List data); + void DeletePackageMetadata(); + bool GetCachedPackageThumbnail(string packageId, out Texture2D texture); + void CachePackageThumbnail(string packageId, Texture2D texture); + bool GetCachedWorkflowStateData(string packageId, out WorkflowStateData data); + void CacheWorkflowStateData(WorkflowStateData data); + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs.meta new file mode 100644 index 00000000..2af6a1de --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a904477679e07bc4889bc15e894c0c48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/Caching/ICachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs new file mode 100644 index 00000000..424dd9c0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs @@ -0,0 +1,4 @@ +namespace AssetStoreTools.Uploader.Services +{ + internal interface IUploaderService { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs.meta new file mode 100644 index 00000000..ee2c2d3d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 757d7a4dc29863740859c936be514fea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/IUploaderService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory.meta new file mode 100644 index 00000000..cb9e723a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 02e4a5ee9e2fb7941b876b207078e01d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs new file mode 100644 index 00000000..83c9c489 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs @@ -0,0 +1,18 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Uploader.Data.Serialization; +using System.Collections.Generic; +using PackageModel = AssetStoreTools.Api.Models.Package; + +namespace AssetStoreTools.Uploader.Services +{ + internal interface IPackageFactoryService : IUploaderService + { + IPackageGroup CreatePackageGroup(string groupName, List packages); + IPackage CreatePackage(PackageModel packageModel); + IPackageContent CreatePackageContent(IPackage package); + List CreateWorkflows(IPackage package, WorkflowStateData stateData); + AssetsWorkflow CreateAssetsWorkflow(IPackage package, AssetsWorkflowState stateData); + UnityPackageWorkflow CreateUnityPackageWorkflow(IPackage package, UnityPackageWorkflowState stateData); + HybridPackageWorkflow CreateHybridPackageWorkflow(IPackage package, HybridPackageWorkflowState stateData); + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs.meta new file mode 100644 index 00000000..e1084507 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 14324b71768a1ea499baa06de33f05af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/IPackageFactoryService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs new file mode 100644 index 00000000..a9fffa5e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs @@ -0,0 +1,95 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Uploader.Data.Serialization; +using AssetStoreTools.Uploader.Services.Analytics; +using AssetStoreTools.Uploader.Services.Api; +using System.Collections.Generic; +using PackageModel = AssetStoreTools.Api.Models.Package; + +namespace AssetStoreTools.Uploader.Services +{ + internal class PackageFactoryService : IPackageFactoryService + { + private IWorkflowServices _workflowServices; + + // Service dependencies + private ICachingService _cachingService; + private IPackageDownloadingService _packageDownloadingService; + private IPackageUploadingService _packageUploadingService; + private IAnalyticsService _analyticsService; + + public PackageFactoryService( + ICachingService cachingService, + IPackageDownloadingService packageDownloadingService, + IPackageUploadingService packageUploadingService, + IAnalyticsService analyticsService + ) + { + _cachingService = cachingService; + _packageDownloadingService = packageDownloadingService; + _packageUploadingService = packageUploadingService; + _analyticsService = analyticsService; + + _workflowServices = new WorkflowServices(_packageDownloadingService, _packageUploadingService, _analyticsService); + } + + public IPackage CreatePackage(PackageModel packageModel) + { + var package = new Package(packageModel); + return package; + } + + public IPackageGroup CreatePackageGroup(string groupName, List packages) + { + return new PackageGroup(groupName, packages); + } + + public IPackageContent CreatePackageContent(IPackage package) + { + if (!package.IsDraft) + return null; + + WorkflowStateData stateData = GetOrCreateWorkflowStateData(package); + + var workflows = CreateWorkflows(package, stateData); + var packageContent = new PackageContent(workflows, stateData, _cachingService); + return packageContent; + } + + public List CreateWorkflows(IPackage package, WorkflowStateData stateData) + { + var workflows = new List + { + CreateAssetsWorkflow(package, stateData.GetAssetsWorkflowState()), + CreateUnityPackageWorkflow(package, stateData.GetUnityPackageWorkflowState()), +#if UNITY_ASTOOLS_EXPERIMENTAL + CreateHybridPackageWorkflow(package, stateData.GetHybridPackageWorkflowState()), +#endif + }; + + return workflows; + } + + public AssetsWorkflow CreateAssetsWorkflow(IPackage package, AssetsWorkflowState stateData) + { + return new AssetsWorkflow(package, stateData, _workflowServices); + } + + public UnityPackageWorkflow CreateUnityPackageWorkflow(IPackage package, UnityPackageWorkflowState stateData) + { + return new UnityPackageWorkflow(package, stateData, _workflowServices); + } + + public HybridPackageWorkflow CreateHybridPackageWorkflow(IPackage package, HybridPackageWorkflowState stateData) + { + return new HybridPackageWorkflow(package, stateData, _workflowServices); + } + + private WorkflowStateData GetOrCreateWorkflowStateData(IPackage package) + { + if (!_cachingService.GetCachedWorkflowStateData(package.PackageId, out var stateData)) + stateData = new WorkflowStateData(package.PackageId); + + return stateData; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs.meta new file mode 100644 index 00000000..86dfc2c3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4074a5b21b6201d449974dcfb652a00b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/PackageFactory/PackageFactoryService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs new file mode 100644 index 00000000..0aaa6866 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs @@ -0,0 +1,26 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Uploader.Services.Analytics; +using AssetStoreTools.Uploader.Services.Api; +using AssetStoreTools.Utility; + +namespace AssetStoreTools.Uploader.Services +{ + internal class UploaderServiceProvider : ServiceProvider + { + public static UploaderServiceProvider Instance => _instance ?? (_instance = new UploaderServiceProvider()); + private static UploaderServiceProvider _instance; + + private UploaderServiceProvider() { } + + protected override void RegisterServices() + { + var api = new AssetStoreApi(new AssetStoreClient()); + Register(); + Register(); + Register(() => new AuthenticationService(api, GetService(), GetService())); + Register(() => new PackageDownloadingService(api, GetService())); + Register(() => new PackageUploadingService(api)); + Register(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs.meta new file mode 100644 index 00000000..298a1cfe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e66f9c7f198baff41ba77f4d0ed7b60f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/Services/UploaderServiceProvider.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI.meta new file mode 100644 index 00000000..e39a22fb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed759a6e886dbfd4fbcecc2beb7248b8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements.meta new file mode 100644 index 00000000..497fc1d7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d14df9cf4e7e9b54c8c94a8cc1aa70c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions.meta new file mode 100644 index 00000000..9ec9955e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 144a518ff26df1e41845217c0f0002d7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs new file mode 100644 index 00000000..27957b2c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs @@ -0,0 +1,170 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Validator.Data; +using System.Linq; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal abstract class ValidationElementBase : VisualElement + { + // Data + protected IWorkflow Workflow; + + // UI + protected VisualElement ResultsBox; + protected Image ResultsBoxImage; + protected Label ResultsBoxLabel; + + protected ValidationElementBase(IWorkflow workflow) + { + Workflow = workflow; + Create(); + } + + private void Create() + { + CreateInfoRow(); + CreateResultsBox(); + } + + private void CreateInfoRow() + { + VisualElement validatorButtonRow = new VisualElement(); + validatorButtonRow.AddToClassList("package-content-option-box"); + + VisualElement validatorLabelHelpRow = new VisualElement(); + validatorLabelHelpRow.AddToClassList("package-content-option-label-help-row"); + + Label validatorLabel = new Label { text = "Validation" }; + Image validatorLabelTooltip = new Image + { + tooltip = "You can use the Asset Store Validator to check your package for common publishing issues" + }; + + var validateButton = new Button(Validate) { name = "ValidateButton", text = "Validate" }; + + validatorLabelHelpRow.Add(validatorLabel); + validatorLabelHelpRow.Add(validatorLabelTooltip); + + validatorButtonRow.Add(validatorLabelHelpRow); + validatorButtonRow.Add(validateButton); + + Add(validatorButtonRow); + } + + private void CreateResultsBox() + { + ResultsBox = new Box { name = "InfoBox" }; + ResultsBox.style.display = DisplayStyle.None; + ResultsBox.AddToClassList("validation-result-box"); + + ResultsBoxImage = new Image(); + ResultsBoxLabel = new Label { name = "ValidationLabel" }; + + ResultsBox.Add(ResultsBoxImage); + ResultsBox.Add(ResultsBoxLabel); + + Add(ResultsBox); + } + + protected virtual bool ConfirmValidation() + { + // Child classes can implement pre-validation prompts + return true; + } + + private void Validate() + { + if (!ConfirmValidation()) + return; + + var validationResult = Workflow.Validate(); + + if (validationResult.Status == ValidationStatus.Cancelled) + return; + + if (validationResult.Status != ValidationStatus.RanToCompletion) + { + EditorUtility.DisplayDialog("Validation failed", $"Package validation failed: {validationResult.Exception.Message}", "OK"); + return; + } + + DisplayResult(validationResult); + } + + private void DisplayResult(ValidationResult result) + { + ResultsBox.style.display = DisplayStyle.Flex; + UpdateValidationResultImage(result); + UpdateValidationResultLabel(result); + } + + public void HideResult() + { + ResultsBox.style.display = DisplayStyle.None; + } + + protected void UpdateValidationResultImage(ValidationResult result) + { + switch (GetValidationSummaryStatus(result)) + { + case TestResultStatus.Pass: + ResultsBoxImage.image = EditorGUIUtility.IconContent("console.infoicon@2x").image; + break; + case TestResultStatus.Warning: + ResultsBoxImage.image = EditorGUIUtility.IconContent("console.warnicon@2x").image; + break; + case TestResultStatus.Fail: + ResultsBoxImage.image = EditorGUIUtility.IconContent("console.erroricon@2x").image; + break; + default: + ResultsBoxImage.image = EditorGUIUtility.IconContent("_Help@2x").image; + break; + } + } + + private void UpdateValidationResultLabel(ValidationResult result) + { + var errorCount = result.Tests.Where(x => x.Result.Status == TestResultStatus.Fail).Count(); + var warningCount = result.Tests.Where(x => x.Result.Status == TestResultStatus.Warning).Count(); + + string text = string.Empty; + if (result.HadCompilationErrors) + { + text += "- Package caused compilation errors\n"; + } + if (errorCount > 0) + { + text += $"- Validation reported {errorCount} error(s)\n"; + } + if (warningCount > 0) + { + text += $"- Validation reported {warningCount} warning(s)\n"; + } + + if (string.IsNullOrEmpty(text)) + { + text = "No issues were found!"; + } + else + { + text = text.Substring(0, text.Length - "\n".Length); + } + + ResultsBoxLabel.text = text; + } + + private TestResultStatus GetValidationSummaryStatus(ValidationResult result) + { + if (result.HadCompilationErrors || + result.Tests.Any(x => x.Result.Status == TestResultStatus.Fail)) + return TestResultStatus.Fail; + + if (result.Tests.Any(x => x.Result.Status == TestResultStatus.Warning)) + return TestResultStatus.Warning; + + return TestResultStatus.Pass; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs.meta new file mode 100644 index 00000000..d8cbc88f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cb20404763eac7144b562c18ad1c37fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/ValidationElementBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs new file mode 100644 index 00000000..f4b22b78 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs @@ -0,0 +1,151 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal abstract class WorkflowElementBase : VisualElement + { + // Data + protected IWorkflow Workflow; + public string Name => Workflow.Name; + public string DisplayName => Workflow.DisplayName; + + // UI Elements that all workflows have + protected PathSelectionElement PathSelectionElement; + protected PreviewGenerationElement PreviewGenerationElement; + protected ValidationElementBase ValidationElement; + protected PackageUploadElement UploadElement; + + public event Action OnInteractionAvailable; + public event Action OnInteractionUnavailable; + + public WorkflowElementBase(IWorkflow workflow) + { + Workflow = workflow; + } + + protected void CreatePathElement(string labelText, string labelTooltip) + { + PathSelectionElement = new PathSelectionElement(labelText, labelTooltip); + PathSelectionElement.OnBrowse += BrowsePath; + Add(PathSelectionElement); + } + + protected void CreatePreviewGenerationElement() + { + PreviewGenerationElement = new PreviewGenerationElement(Workflow); + PreviewGenerationElement.style.display = DisplayStyle.None; + var callback = new Action(() => + PreviewGenerationElement.style.display = ASToolsPreferences.Instance.UseLegacyExporting + ? DisplayStyle.None + : DisplayStyle.Flex); + RegisterCallback((_) => { ASToolsPreferences.OnSettingsChange += callback; }); + RegisterCallback((_) => { ASToolsPreferences.OnSettingsChange -= callback; }); + Add(PreviewGenerationElement); + } + + protected void CreateValidationElement(ValidationElementBase validationElement) + { + ValidationElement = validationElement; + ValidationElement.style.display = DisplayStyle.None; + Add(ValidationElement); + } + + protected void CreateUploadElement(IWorkflow workflow, bool exposeExportButton) + { + UploadElement = new PackageUploadElement(workflow, exposeExportButton); + UploadElement.OnInteractionAvailable += EnableInteraction; + UploadElement.OnInteractionUnavailable += DisableInteraction; + UploadElement.style.display = DisplayStyle.None; + Add(UploadElement); + } + + protected abstract void BrowsePath(); + + protected void SetPathSelectionTextField(string value) + { + if (string.IsNullOrEmpty(value)) + return; + + PathSelectionElement.SetPath(value); + ValidationElement.style.display = DisplayStyle.Flex; + UploadElement.style.display = DisplayStyle.Flex; + + if (PreviewGenerationElement != null && !ASToolsPreferences.Instance.UseLegacyExporting) + { + PreviewGenerationElement.style.display = DisplayStyle.Flex; + } + } + + protected void CheckForMissingMetas(IEnumerable paths) + { + bool displayDialog = ASToolsPreferences.Instance.DisplayHiddenMetaDialog && FileUtility.IsMissingMetaFiles(paths); + if (!displayDialog) + return; + + var selectedOption = EditorUtility.DisplayDialogComplex( + "Notice", + "Your package includes hidden folders which do not contain meta files. " + + "Hidden folders will not be exported unless they contain meta files.\n\nWould you like meta files to be generated?", + "Yes", "No", "No and do not display this again"); + + switch (selectedOption) + { + case 0: + try + { + FileUtility.GenerateMetaFiles(paths); + EditorUtility.DisplayDialog( + "Success", + "Meta files have been generated. Please note that further manual tweaking may be required to set up correct references", + "OK"); + } + catch (Exception e) + { + EditorUtility.DisplayDialog( + "Error", + $"Meta file generation failed: {e.Message}", + "OK" + ); + } + break; + case 1: + // Do nothing + return; + case 2: + ASToolsPreferences.Instance.DisplayHiddenMetaDialog = false; + ASToolsPreferences.Instance.Save(); + return; + } + } + + public bool Is(IWorkflow workflow) + { + return Workflow == workflow; + } + + protected virtual void EnableInteraction() + { + PathSelectionElement.SetEnabled(true); + ValidationElement.SetEnabled(true); + PreviewGenerationElement?.SetEnabled(true); + UploadElement.SetEnabled(true); + OnInteractionAvailable?.Invoke(); + } + + protected virtual void DisableInteraction() + { + PathSelectionElement.SetEnabled(false); + ValidationElement.SetEnabled(false); + PreviewGenerationElement?.SetEnabled(false); + UploadElement.SetEnabled(false); + OnInteractionUnavailable?.Invoke(); + } + + protected abstract void Deserialize(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs.meta new file mode 100644 index 00000000..60d00d41 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 45d1bf267c3ea9048bfdd75d0d19c8bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/Abstractions/WorkflowElementBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs new file mode 100644 index 00000000..393c4aa6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs @@ -0,0 +1,102 @@ +using AssetStoreTools.Api.Models; +using System; +using System.Threading.Tasks; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class AccountToolbar : VisualElement + { + private Image _accountImage; + private Label _accountEmailLabel; + private Button _refreshButton; + + public event Func OnRefresh; + public event Action OnLogout; + + public AccountToolbar() + { + Create(); + } + + private void Create() + { + AddToClassList("account-toolbar"); + + // Left side of the toolbar + VisualElement leftSideContainer = new VisualElement { name = "LeftSideContainer" }; + leftSideContainer.AddToClassList("account-toolbar-left-side-container"); + + _accountImage = new Image(); + _accountImage.AddToClassList("account-toolbar-user-image"); + + _accountEmailLabel = new Label() { name = "AccountEmail" }; + _accountEmailLabel.AddToClassList("account-toolbar-email-label"); + + leftSideContainer.Add(_accountImage); + leftSideContainer.Add(_accountEmailLabel); + + // Right side of the toolbar + VisualElement rightSideContainer = new VisualElement { name = "RightSideContainer" }; + rightSideContainer.AddToClassList("account-toolbar-right-side-container"); + + // Refresh button + _refreshButton = new Button(Refresh) { name = "RefreshButton", text = "Refresh" }; + _refreshButton.AddToClassList("account-toolbar-button-refresh"); + + // Logout button + var logoutButton = new Button(Logout) { name = "LogoutButton", text = "Log out" }; + logoutButton.AddToClassList("account-toolbar-button-logout"); + + rightSideContainer.Add(_refreshButton); + rightSideContainer.Add(logoutButton); + + // Constructing the final toolbar + Add(leftSideContainer); + Add(rightSideContainer); + } + + private async void Refresh() + { + _refreshButton.SetEnabled(false); + await OnRefresh?.Invoke(); + _refreshButton.SetEnabled(true); + } + + private void Logout() + { + OnLogout?.Invoke(); + } + + public void SetUser(User user) + { + if (user == null) + { + _accountEmailLabel.text = string.Empty; + _accountImage.tooltip = string.Empty; + return; + } + + var userEmail = !string.IsNullOrEmpty(user.Username) ? user.Username : "Unknown"; + var publisherName = !string.IsNullOrEmpty(user.Name) ? user.Name : "Unknown"; + var publisherId = !string.IsNullOrEmpty(user.PublisherId) ? user.PublisherId : "Unknown"; + var userInfo = + $"Username: {userEmail}\n" + + $"Publisher Name: {publisherName}\n" + + $"Publisher ID: {publisherId}"; + + _accountEmailLabel.text = userEmail; + _accountImage.tooltip = userInfo; + } + + public void EnableButtons() + { + _refreshButton.SetEnabled(true); + } + + public void DisableButtons() + { + _refreshButton.SetEnabled(false); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs.meta new file mode 100644 index 00000000..b179c6aa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3c275be3817d1684ca1802c2738ac4d9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AccountToolbar.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs new file mode 100644 index 00000000..283017d4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs @@ -0,0 +1,215 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class AssetsWorkflowElement : WorkflowElementBase + { + // Data + private AssetsWorkflow _workflow; + + // UI + private VisualElement _dependenciesToggleElement; + private Toggle _dependenciesToggle; + private MultiToggleSelectionElement _dependenciesElement; + private MultiToggleSelectionElement _specialFoldersElement; + + private const string PathSelectionTooltip = "Select the main folder of your package" + + "\n\nAll files and folders of your package should preferably be contained within a single root folder that is named after your package" + + "\n\nExample: 'Assets/[MyPackageName]'" + + "\n\nNote: If your content makes use of special folders that are required to be placed in the root Assets folder (e.g. 'StreamingAssets')," + + " you will be able to include them after selecting the main folder"; + + public AssetsWorkflowElement(AssetsWorkflow workflow) : base(workflow) + { + _workflow = workflow; + + Create(); + Deserialize(); + } + + private void Create() + { + CreatePathElement("Folder path", PathSelectionTooltip); + CreateDependenciesToggleElement(); + CreateDependenciesSelectionElement(); + CreateSpecialFoldersElement(); + CreatePreviewGenerationElement(); + CreateValidationElement(new CurrentProjectValidationElement(_workflow)); + CreateUploadElement(_workflow, true); + } + + private void CreateDependenciesToggleElement() + { + _dependenciesToggleElement = new VisualElement() { name = "Dependencies Toggle" }; + _dependenciesToggleElement.AddToClassList("package-content-option-box"); + + VisualElement dependenciesLabelHelpRow = new VisualElement(); + dependenciesLabelHelpRow.AddToClassList("package-content-option-label-help-row"); + + Label dependenciesLabel = new Label { text = "Dependencies" }; + Image dependenciesLabelTooltip = new Image + { + tooltip = "Tick this checkbox if your package content has dependencies on Unity packages from the Package Manager" + }; + + _dependenciesToggle = new Toggle { name = "DependenciesToggle", text = "Include Package Manifest" }; + _dependenciesToggle.AddToClassList("package-content-option-toggle"); + + var callback = new Action(() => DependencyToggleValueChange(true)); + _dependenciesToggle.RegisterValueChangedCallback((_) => DependencyToggleValueChange(true)); + RegisterCallback((_) => { ASToolsPreferences.OnSettingsChange += callback; }); + RegisterCallback((_) => { ASToolsPreferences.OnSettingsChange -= callback; }); + + dependenciesLabelHelpRow.Add(dependenciesLabel); + dependenciesLabelHelpRow.Add(dependenciesLabelTooltip); + + _dependenciesToggleElement.Add(dependenciesLabelHelpRow); + _dependenciesToggleElement.Add(_dependenciesToggle); + + _dependenciesToggleElement.style.display = DisplayStyle.None; + Add(_dependenciesToggleElement); + } + + private void CreateDependenciesSelectionElement() + { + _dependenciesElement = new MultiToggleSelectionElement() + { + DisplayElementLabel = false, + ElementLabel = "Dependencies", + NoSelectionLabel = "No packages match this criteria" + }; + + var setDependencies = new Action>((dict) => _workflow.SetDependencies(dict.Where(x => x.Value).Select(x => x.Key), true)); + _dependenciesElement.OnValuesChanged += setDependencies; + _dependenciesElement.style.display = DisplayStyle.None; + Add(_dependenciesElement); + } + + private void CreateSpecialFoldersElement() + { + _specialFoldersElement = new MultiToggleSelectionElement() + { + ElementLabel = "Special Folders", + ElementTooltip = "If your package content relies on Special Folders (e.g. StreamingAssets), please select which of these folders should be included in the package.", + NoSelectionLabel = "No folders match this criteria." + }; + + var setSpecialFolders = new Action>((dict) => _workflow.SetSpecialFolders(dict.Where(x => x.Value).Select(x => x.Key), true)); + _specialFoldersElement.OnValuesChanged += setSpecialFolders; + _specialFoldersElement.style.display = DisplayStyle.None; + Add(_specialFoldersElement); + } + + protected override void BrowsePath() + { + string absoluteExportPath = string.Empty; + bool includeAllAssets = false; + + if (_workflow.IsCompleteProject) + { + includeAllAssets = EditorUtility.DisplayDialog("Notice", + "Your package draft is set to a category that is treated" + + " as a complete project. Project settings will be included automatically. Would you like everything in the " + + "'Assets' folder to be included?\n\nYou will still be able to change the selected assets before uploading", + "Yes, include all folders and assets", + "No, I'll select what to include manually"); + + if (includeAllAssets) + absoluteExportPath = Application.dataPath; + } + + if (!includeAllAssets) + { + absoluteExportPath = EditorUtility.OpenFolderPanel( + "Select folder to compress into a package", "Assets/", ""); + + if (string.IsNullOrEmpty(absoluteExportPath)) + return; + } + + var relativeExportPath = FileUtility.AbsolutePathToRelativePath(absoluteExportPath, ASToolsPreferences.Instance.EnableSymlinkSupport); + if (!_workflow.IsPathValid(relativeExportPath, out var error)) + { + EditorUtility.DisplayDialog("Invalid selection", error, "OK"); + return; + } + + HandlePathSelection(relativeExportPath, true); + CheckForMissingMetas(); + } + + private void HandlePathSelection(string relativeExportPath, bool serialize) + { + if (string.IsNullOrEmpty(relativeExportPath)) + return; + + _workflow.SetMainExportPath(relativeExportPath, serialize); + SetPathSelectionTextField(relativeExportPath + "/"); + + _dependenciesToggleElement.style.display = DisplayStyle.Flex; + UpdateSpecialFoldersElement(); + } + + private void CheckForMissingMetas() + { + var paths = new List() { _workflow.GetMainExportPath() }; + paths.AddRange(_workflow.GetSpecialFolders()); + CheckForMissingMetas(paths); + } + + private void DependencyToggleValueChange(bool serialize) + { + _workflow.SetIncludeDependencies(_dependenciesToggle.value, serialize); + + if (_dependenciesToggle.value && !ASToolsPreferences.Instance.UseLegacyExporting) + { + var allDependencies = _workflow.GetAvailableDependencies(); + var selectedDependencies = allDependencies.ToDictionary(x => x, y => _workflow.GetDependencies().Any(x => x.name == y)); + _dependenciesElement.Populate(selectedDependencies); + _dependenciesElement.style.display = DisplayStyle.Flex; + } + else + { + _dependenciesElement.style.display = DisplayStyle.None; + } + } + + private void UpdateSpecialFoldersElement() + { + var availableSpecialFolders = _workflow.GetAvailableSpecialFolders(); + var selectedSpecialFolders = availableSpecialFolders.ToDictionary(x => x, y => _workflow.GetSpecialFolders().Any(x => x == y)); + _specialFoldersElement.Populate(selectedSpecialFolders); + _specialFoldersElement.style.display = availableSpecialFolders.Count > 0 ? DisplayStyle.Flex : DisplayStyle.None; + } + + protected override void EnableInteraction() + { + base.EnableInteraction(); + _dependenciesToggleElement.SetEnabled(true); + _dependenciesElement.SetEnabled(true); + _specialFoldersElement.SetEnabled(true); + } + + protected override void DisableInteraction() + { + base.DisableInteraction(); + _dependenciesToggleElement.SetEnabled(false); + _dependenciesElement.SetEnabled(false); + _specialFoldersElement.SetEnabled(false); + } + + protected override void Deserialize() + { + HandlePathSelection(_workflow.GetMainExportPath(), false); + _dependenciesToggle.SetValueWithoutNotify(_workflow.GetIncludeDependencies()); + DependencyToggleValueChange(false); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs.meta new file mode 100644 index 00000000..4720aaaa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 1f62ea8ab5c102e4fa574a3dcac7f6fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/AssetsWorkflowElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs new file mode 100644 index 00000000..adfeab1f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs @@ -0,0 +1,31 @@ +using AssetStoreTools.Uploader.Data; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class CurrentProjectValidationElement : ValidationElementBase + { + public CurrentProjectValidationElement(IWorkflow workflow) : base(workflow) + { + Create(); + } + + private void Create() + { + CreateResultsBox(); + } + + private void CreateResultsBox() + { + var _viewReportButton = new Button(ViewReport) { text = "View report" }; + _viewReportButton.AddToClassList("validation-result-view-report-button"); + + ResultsBox.Add(_viewReportButton); + } + + private void ViewReport() + { + AssetStoreTools.ShowAssetStoreToolsValidator(Workflow.LastValidationSettings, Workflow.LastValidationResult); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs.meta new file mode 100644 index 00000000..e3073c3e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 21a1f13231b167b4c80079a2c1212101 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/CurrentProjectValidationElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs new file mode 100644 index 00000000..12c596b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs @@ -0,0 +1,92 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using AssetStoreTools.Validator; +using System; +using System.IO; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class ExternalProjectValidationElement : ValidationElementBase + { + private VisualElement _projectButtonContainer; + + public ExternalProjectValidationElement(IWorkflow workflow) : base(workflow) + { + Create(); + } + + private void Create() + { + CreateProjectButtonContainer(); + CreateProjectButtons(); + } + + private void CreateProjectButtonContainer() + { + _projectButtonContainer = new VisualElement(); + _projectButtonContainer.AddToClassList("validation-result-view-report-button-container"); + + ResultsBox.Add(_projectButtonContainer); + } + + private void CreateProjectButtons() + { + var openButton = new Button(OpenProject) { text = "Open Project" }; + openButton.AddToClassList("validation-result-view-report-button"); + + var saveButton = new Button(SaveProject) { text = "Save Project" }; + saveButton.AddToClassList("validation-result-view-report-button"); + + _projectButtonContainer.Add(openButton); + _projectButtonContainer.Add(saveButton); + } + + private void OpenProject() + { + try + { + EditorUtility.DisplayProgressBar("Waiting...", "Validation project is open. Waiting for it to exit...", 0.4f); + var projectPath = Workflow.LastValidationResult.ProjectPath; + ExternalProjectValidator.OpenExternalValidationProject(projectPath); + } + finally + { + EditorUtility.ClearProgressBar(); + } + } + + private void SaveProject() + { + try + { + var projectPath = Workflow.LastValidationResult.ProjectPath; + var savePath = EditorUtility.SaveFolderPanel("Select a folder", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), string.Empty); + if (string.IsNullOrEmpty(savePath)) + return; + + var saveDir = new DirectoryInfo(savePath); + if (!saveDir.Exists || saveDir.GetFileSystemInfos().Length != 0) + { + EditorUtility.DisplayDialog("Saving project failed", "Selected directory must be an empty folder", "OK"); + return; + } + + EditorUtility.DisplayProgressBar("Saving...", "Saving project...", 0.4f); + FileUtility.CopyDirectory(projectPath, savePath, true); + } + finally + { + EditorUtility.ClearProgressBar(); + } + } + + protected override bool ConfirmValidation() + { + return EditorUtility.DisplayDialog("Notice", "Pre-exported package validation is performed in a separate temporary project. " + + "It may take some time for the temporary project to be created, which will halt any actions in the current project. " + + "The current project will resume work after the temporary project is exited.\n\nDo you wish to proceed?", "Yes", "No"); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs.meta new file mode 100644 index 00000000..5178519e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 706f01d53c7eaf04bae07fb36684e31b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/ExternalProjectValidationElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs new file mode 100644 index 00000000..75981425 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs @@ -0,0 +1,116 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class HybridPackageWorkflowElement : WorkflowElementBase + { + // Data + private HybridPackageWorkflow _workflow; + + // UI + private MultiToggleSelectionElement _dependenciesElement; + + public HybridPackageWorkflowElement(HybridPackageWorkflow workflow) : base(workflow) + { + _workflow = workflow; + + Create(); + Deserialize(); + } + + private void Create() + { + CreatePathElement("Package path", "Select a local Package you would like to export and upload to the Store."); + CreateDependenciesElement(); + CreatePreviewGenerationElement(); + CreateValidationElement(new CurrentProjectValidationElement(_workflow)); + CreateUploadElement(_workflow, true); + } + + private void CreateDependenciesElement() + { + _dependenciesElement = new MultiToggleSelectionElement() + { + ElementLabel = "Dependencies", + ElementTooltip = "Select which local package dependencies should be included when exporting." + + "\n\nNote that only local or embedded dependencies defined in the package.json can be selected.", + NoSelectionLabel = "No packages match this criteria" + }; + + var setDependencies = new Action>((dict) => _workflow.SetDependencies(dict.Where(x => x.Value).Select(x => x.Key), true)); + _dependenciesElement.OnValuesChanged += setDependencies; + Add(_dependenciesElement); + _dependenciesElement.style.display = DisplayStyle.None; + } + + protected override void BrowsePath() + { + var absoluteExportPath = EditorUtility.OpenFilePanel("Select a package.json file", "Packages/", "json"); + if (string.IsNullOrEmpty(absoluteExportPath)) + return; + + if (!_workflow.IsPathValid(absoluteExportPath, out var error)) + { + EditorUtility.DisplayDialog("Invalid selection", error, "OK"); + return; + } + + HandlePathSelection(absoluteExportPath, true); + CheckForMissingMetas(); + } + + private void HandlePathSelection(string packageManifestPath, bool serialize) + { + if (string.IsNullOrEmpty(packageManifestPath)) + return; + + _workflow.SetPackage(packageManifestPath, serialize); + var packageFolderPath = _workflow.GetPackage().assetPath; + SetPathSelectionTextField(packageFolderPath + "/"); + + UpdateDependenciesElement(); + } + + private void CheckForMissingMetas() + { + var paths = new List() { _workflow.GetPackage().assetPath }; + paths.AddRange(_workflow.GetDependencies().Select(x => x.assetPath)); + CheckForMissingMetas(paths); + } + + private void UpdateDependenciesElement() + { + var availableDependencies = _workflow.GetAvailableDependencies(); + var selectedDependencies = availableDependencies.ToDictionary(x => x.name, y => _workflow.GetDependencies().Any(x => x.name == y.name)); + _dependenciesElement.Populate(selectedDependencies); + _dependenciesElement.style.display = availableDependencies.Count > 0 ? DisplayStyle.Flex : DisplayStyle.None; + } + + protected override void EnableInteraction() + { + base.EnableInteraction(); + _dependenciesElement.SetEnabled(true); + } + + protected override void DisableInteraction() + { + base.DisableInteraction(); + _dependenciesElement.SetEnabled(false); + } + + protected override void Deserialize() + { + var package = _workflow.GetPackage(); + if (package == null) + return; + + HandlePathSelection(AssetDatabase.GetAssetPath(package.GetManifestAsset()), false); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs.meta new file mode 100644 index 00000000..e39801ca --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 34cd1e5cbe87bb546937a521bd2bc69c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/HybridPackageWorkflowElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs new file mode 100644 index 00000000..b2ad70b1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs @@ -0,0 +1,52 @@ +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class LoadingSpinner : VisualElement + { + // Data + private int _spinIndex; + private double _spinTimer; + private double _spinThreshold = 0.1; + + // UI + private Image _spinnerImage; + + public LoadingSpinner() + { + AddToClassList("loading-spinner-box"); + + _spinnerImage = new Image { name = "SpinnerImage" }; + _spinnerImage.AddToClassList("loading-spinner-image"); + + Add(_spinnerImage); + } + + public void Show() + { + EditorApplication.update += SpinnerLoop; + style.display = DisplayStyle.Flex; + } + + public void Hide() + { + EditorApplication.update -= SpinnerLoop; + style.display = DisplayStyle.None; + } + + private void SpinnerLoop() + { + if (_spinTimer + _spinThreshold > EditorApplication.timeSinceStartup) + return; + + _spinTimer = EditorApplication.timeSinceStartup; + _spinnerImage.image = EditorGUIUtility.IconContent($"WaitSpin{_spinIndex:00}").image; + + _spinIndex += 1; + + if (_spinIndex > 11) + _spinIndex = 0; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs.meta new file mode 100644 index 00000000..d3c31ba8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7c7cdef91eb9a894091869ca10d9d178 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/LoadingSpinner.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs new file mode 100644 index 00000000..175a095e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class MultiToggleSelectionElement : VisualElement + { + // Data + private Dictionary _selections; + private readonly List _selectionFilters = new List { "All", "Selected", "Not Selected" }; + private string _activeFilter; + + public bool DisplayElementLabel + { + get => _multiToggleSelectionHelpRow.style.visibility == Visibility.Visible; + set { _multiToggleSelectionHelpRow.style.visibility = value ? Visibility.Visible : Visibility.Hidden; } + } + + public string ElementLabel { get => _multiToggleSelectionLabel.text; set { _multiToggleSelectionLabel.text = value; } } + public string ElementTooltip { get => _multiToggleSelectionTooltip.tooltip; set { _multiToggleSelectionTooltip.tooltip = value; } } + public string NoSelectionLabel { get => _noSelectionsLabel.text; set { _noSelectionsLabel.text = value; } } + + // UI + private VisualElement _multiToggleSelectionHelpRow; + private Label _multiToggleSelectionLabel; + private Image _multiToggleSelectionTooltip; + + private ScrollView _selectionTogglesBox; + private Label _noSelectionsLabel; + private ToolbarMenu _filteringDropdown; + + public event Action> OnValuesChanged; + + public MultiToggleSelectionElement() + { + _activeFilter = _selectionFilters[0]; + AddToClassList("package-content-option-box"); + Create(); + } + + private void Create() + { + _multiToggleSelectionHelpRow = new VisualElement(); + _multiToggleSelectionHelpRow.AddToClassList("package-content-option-label-help-row"); + + _multiToggleSelectionLabel = new Label(); + _multiToggleSelectionTooltip = new Image(); + + VisualElement fullSelectionBox = new VisualElement(); + fullSelectionBox.AddToClassList("multi-toggle-box"); + + _selectionTogglesBox = new ScrollView { name = "DependencyToggles" }; + _selectionTogglesBox.AddToClassList("multi-toggle-box-scrollview"); + + _noSelectionsLabel = new Label(); + _noSelectionsLabel.AddToClassList("multi-toggle-box-empty-label"); + + var scrollContainer = _selectionTogglesBox.Q("unity-content-viewport"); + scrollContainer.Add(_noSelectionsLabel); + + VisualElement filteringBox = new VisualElement(); + filteringBox.AddToClassList("multi-toggle-box-toolbar"); + + // Select - deselect buttons + VisualElement selectingBox = new VisualElement(); + selectingBox.AddToClassList("multi-toggle-box-toolbar-selecting-box"); + + Button selectAllButton = new Button(SelectAllToggles) + { + text = "Select All" + }; + + Button deSelectAllButton = new Button(UnselectAllToggles) + { + text = "Deselect All" + }; + + selectingBox.Add(selectAllButton); + selectingBox.Add(deSelectAllButton); + + // Filtering dropdown + VisualElement filteringDropdownBox = new VisualElement(); + filteringDropdownBox.AddToClassList("multi-toggle-box-toolbar-filtering-box"); + + _filteringDropdown = new ToolbarMenu { text = _selectionFilters[0] }; + + foreach (var filter in _selectionFilters) + _filteringDropdown.menu.AppendAction(filter, (_) => { FilterDependencies(filter); }); + + filteringDropdownBox.Add(_filteringDropdown); + + // Final adding + filteringBox.Add(filteringDropdownBox); + filteringBox.Add(selectingBox); + + fullSelectionBox.Add(_selectionTogglesBox); + fullSelectionBox.Add(filteringBox); + + _multiToggleSelectionHelpRow.Add(_multiToggleSelectionLabel); + _multiToggleSelectionHelpRow.Add(_multiToggleSelectionTooltip); + + Add(_multiToggleSelectionHelpRow); + Add(fullSelectionBox); + } + + public void Populate(Dictionary selections) + { + _selectionTogglesBox.Clear(); + _selections = selections; + + EventCallback, string> callback = OnToggle; + + foreach (var kvp in selections) + { + var toggle = new Toggle() { text = kvp.Key, value = kvp.Value }; + toggle.AddToClassList("multi-toggle-box-toggle"); + toggle.RegisterCallback(callback, toggle.text); + _selectionTogglesBox.Add(toggle); + } + + FilterDependencies(_activeFilter); + } + + private void FilterDependencies(string filter) + { + _activeFilter = filter; + + var allToggles = _selectionTogglesBox.Children().Cast().ToArray(); + var selectedIndex = _selectionFilters.FindIndex(x => x == filter); + + switch (selectedIndex) + { + case 0: + foreach (var toggle in allToggles) + toggle.style.display = DisplayStyle.Flex; + break; + case 1: + foreach (var toggle in allToggles) + toggle.style.display = toggle.value ? DisplayStyle.Flex : DisplayStyle.None; + break; + case 2: + foreach (var toggle in allToggles) + toggle.style.display = toggle.value ? DisplayStyle.None : DisplayStyle.Flex; + break; + } + + // Check if any toggles are displayed + var count = allToggles.Count(toggle => toggle.style.display == DisplayStyle.Flex); + _noSelectionsLabel.style.display = count > 0 ? DisplayStyle.None : DisplayStyle.Flex; + + _filteringDropdown.text = filter; + } + + private void OnToggle(ChangeEvent evt, string text) + { + FilterDependencies(_activeFilter); + _selections[text] = evt.newValue; + OnValuesChanged?.Invoke(_selections); + } + + private void OnAllToggles(bool value) + { + var allToggles = _selectionTogglesBox.Children().Cast(); + foreach (var toggle in allToggles) + toggle.SetValueWithoutNotify(value); + + foreach (var key in _selections.Keys.ToArray()) + _selections[key] = value; + + FilterDependencies(_activeFilter); + OnValuesChanged?.Invoke(_selections); + } + + private void SelectAllToggles() + { + OnAllToggles(true); + } + + private void UnselectAllToggles() + { + OnAllToggles(false); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs.meta new file mode 100644 index 00000000..ec5d84c6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 19e30766043794345beb432973e0eb3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/MultiToggleSelectionElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs new file mode 100644 index 00000000..eac8455f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs @@ -0,0 +1,137 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using System.Collections.Generic; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PackageContentElement : VisualElement + { + // Data + private IPackageContent _content; + private List _workflowElements; + + // UI + private VisualElement _workflowSelectionBox; + private ToolbarMenu _toolbarMenu; + + public PackageContentElement(IPackageContent content) + { + _content = content; + content.OnActiveWorkflowChanged += ActiveWorkflowChanged; + + _workflowElements = new List(); + + Create(); + } + + private void Create() + { + AddToClassList("package-content-element"); + + CreateWorkflowSelection(); + CreateWorkflows(); + Deserialize(); + } + + private void CreateWorkflowSelection() + { + _workflowSelectionBox = new VisualElement(); + _workflowSelectionBox.AddToClassList("package-content-option-box"); + + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("package-content-option-label-help-row"); + + Label workflowLabel = new Label { text = "Upload type" }; + Image workflowLabelTooltip = new Image + { + tooltip = "Select what content you are uploading to the Asset Store" + + "\n\n- From Assets Folder - content located within the project's 'Assets' folder or one of its subfolders" + + "\n\n- Pre-exported .unitypackage - content that has already been compressed into a .unitypackage file" +#if UNITY_ASTOOLS_EXPERIMENTAL + + "\n\n- Local UPM Package - content that is located within the project's 'Packages' folder. Only embedded and local packages are supported" +#endif + }; + + labelHelpRow.Add(workflowLabel); + labelHelpRow.Add(workflowLabelTooltip); + + _toolbarMenu = new ToolbarMenu(); + _toolbarMenu.AddToClassList("package-content-option-dropdown"); + + foreach (var workflow in _content.GetAvailableWorkflows()) + { + AppendToolbarActionForWorkflow(workflow); + } + + _workflowSelectionBox.Add(labelHelpRow); + _workflowSelectionBox.Add(_toolbarMenu); + + Add(_workflowSelectionBox); + } + + private void AppendToolbarActionForWorkflow(IWorkflow workflow) + { + _toolbarMenu.menu.AppendAction(workflow.DisplayName, _ => + { + _content.SetActiveWorkflow(workflow); + }); + } + + private void CreateWorkflows() + { + foreach (var workflow in _content.GetAvailableWorkflows()) + { + WorkflowElementBase element; + switch (workflow) + { + case AssetsWorkflow assetsWorkflow: + element = new AssetsWorkflowElement(assetsWorkflow); + break; + case UnityPackageWorkflow unityPackageWorkflow: + element = new UnityPackageWorkflowElement(unityPackageWorkflow); + break; +#if UNITY_ASTOOLS_EXPERIMENTAL + case HybridPackageWorkflow hybridPackageWorkflow: + element = new HybridPackageWorkflowElement(hybridPackageWorkflow); + break; +#endif + default: + ASDebug.LogWarning("Package Content Element received an undefined workflow"); + continue; + } + + element.OnInteractionAvailable += EnableInteraction; + element.OnInteractionUnavailable += DisableInteraction; + _workflowElements.Add(element); + Add(element); + } + } + + private void ActiveWorkflowChanged(IWorkflow workflow) + { + _toolbarMenu.text = workflow.DisplayName; + foreach (var workflowElement in _workflowElements) + { + bool show = workflowElement.Is(workflow); + workflowElement.style.display = show ? DisplayStyle.Flex : DisplayStyle.None; + } + } + + private void EnableInteraction() + { + _workflowSelectionBox.SetEnabled(true); + } + + private void DisableInteraction() + { + _workflowSelectionBox.SetEnabled(false); + } + + private void Deserialize() + { + ActiveWorkflowChanged(_content.GetActiveWorkflow()); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs.meta new file mode 100644 index 00000000..e751748e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 09927e9c8fd6e074fa451add92b7ab6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageContentElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs new file mode 100644 index 00000000..f934979a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs @@ -0,0 +1,215 @@ +ο»Ώusing AssetStoreTools.Api; +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Uploader.Services; +using System; +#if !UNITY_2021_1_OR_NEWER +using UnityEditor.UIElements; +#endif +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PackageElement : VisualElement + { + // Data + private IPackage _package; + private bool _isSelected; + + private IPackageFactoryService _packageFactory; + + // UI + private Button _foldoutBox; + private Label _expanderLabel; + private Label _assetLabel; + private Label _lastDateSizeLabel; + private Image _assetImage; + + private ProgressBar _uploadProgressBar; + private VisualElement _uploadProgressBarBackground; + + private PackageContentElement _contentElement; + + public event Action OnSelected; + + public PackageElement(IPackage package, IPackageFactoryService packageFactory) + { + _package = package; + _package.OnUpdate += Refresh; + _package.OnIconUpdate += SetPackageThumbnail; + + _packageFactory = packageFactory; + + _isSelected = false; + + Create(); + } + + private void Create() + { + AddToClassList("package-full-box"); + + _foldoutBox = new Button { name = "Package" }; + _foldoutBox.AddToClassList("package-foldout-box"); + if (_package.IsDraft) + _foldoutBox.AddToClassList("package-foldout-box-draft"); + _foldoutBox.clickable.clicked += Toggle; + + // Expander, Icon and Asset Label + VisualElement foldoutBoxInfo = new VisualElement { name = "foldoutBoxInfo" }; + foldoutBoxInfo.AddToClassList("package-foldout-box-info"); + + VisualElement labelExpanderRow = new VisualElement { name = "labelExpanderRow" }; + labelExpanderRow.AddToClassList("package-expander-label-row"); + + _expanderLabel = new Label { name = "ExpanderLabel", text = "β–Ί" }; + _expanderLabel.AddToClassList("package-expander"); + _expanderLabel.style.display = _package.IsDraft ? DisplayStyle.Flex : DisplayStyle.None; + + _assetImage = new Image { name = "AssetImage" }; + _assetImage.AddToClassList("package-image"); + + VisualElement assetLabelInfoBox = new VisualElement { name = "assetLabelInfoBox" }; + assetLabelInfoBox.AddToClassList("package-label-info-box"); + + _assetLabel = new Label { name = "AssetLabel", text = _package.Name }; + _assetLabel.AddToClassList("package-label"); + + _lastDateSizeLabel = new Label { name = "AssetInfoLabel", text = FormatDateSize() }; + _lastDateSizeLabel.AddToClassList("package-info"); + + assetLabelInfoBox.Add(_assetLabel); + assetLabelInfoBox.Add(_lastDateSizeLabel); + + labelExpanderRow.Add(_expanderLabel); + labelExpanderRow.Add(_assetImage); + labelExpanderRow.Add(assetLabelInfoBox); + + var openInBrowserButton = new Button(OpenPackageInBrowser) + { + name = "OpenInBrowserButton", + tooltip = "View your package in the Publishing Portal." + }; + openInBrowserButton.AddToClassList("package-open-in-browser-button"); + + // Header Progress bar + _uploadProgressBar = new ProgressBar { name = "HeaderProgressBar" }; + _uploadProgressBar.AddToClassList("package-header-progress-bar"); + _uploadProgressBar.style.display = DisplayStyle.None; + _uploadProgressBarBackground = _uploadProgressBar.Q(className: "unity-progress-bar__progress"); + + // Connect it all + foldoutBoxInfo.Add(labelExpanderRow); + foldoutBoxInfo.Add(openInBrowserButton); + + _foldoutBox.Add(foldoutBoxInfo); + _foldoutBox.Add(_uploadProgressBar); + + Add(_foldoutBox); + } + + private void CreateFoldoutContent() + { + var content = _packageFactory.CreatePackageContent(_package); + if (content == null) + return; + + _contentElement = new PackageContentElement(content); + _contentElement.style.display = DisplayStyle.None; + Add(_contentElement); + + SubscribeToContentWorkflowUpdates(content); + } + + private void SubscribeToContentWorkflowUpdates(IPackageContent content) + { + foreach (var workflow in content.GetAvailableWorkflows()) + { + workflow.OnUploadStateChanged += UpdateProgressBar; + } + } + + private void UpdateProgressBar(UploadStatus? status, float? progress) + { + if (status != null) + { + _uploadProgressBarBackground.style.backgroundColor = PackageUploadElement.GetColorByStatus(status.Value); + } + + if (progress != null) + { + _uploadProgressBar.value = progress.Value; + } + } + + private void Toggle() + { + if (!_package.IsDraft) + return; + + if (!Contains(_contentElement)) + CreateFoldoutContent(); + + var shouldExpand = !_isSelected; + _expanderLabel.text = shouldExpand ? "β–Ό" : "β–Ί"; + + if (shouldExpand) + _foldoutBox.AddToClassList("package-foldout-box-expanded"); + else + _foldoutBox.RemoveFromClassList("package-foldout-box-expanded"); + _contentElement.style.display = shouldExpand ? DisplayStyle.Flex : DisplayStyle.None; + + _isSelected = !_isSelected; + ToggleProgressBar(); + + if (_isSelected) + OnSelected?.Invoke(); + } + + private void ToggleProgressBar() + { + if (!_isSelected && _uploadProgressBar.value != 0) + _uploadProgressBar.style.display = DisplayStyle.Flex; + else + _uploadProgressBar.style.display = DisplayStyle.None; + } + + public bool Is(IPackage package) + { + return package == _package; + } + + public void Select() + { + if (!_isSelected) + Toggle(); + } + + public void Unselect() + { + if (_isSelected) + Toggle(); + } + + private void SetPackageThumbnail() + { + _assetImage.image = _package.Icon; + } + + private void Refresh() + { + _assetLabel.text = _package.Name; + _lastDateSizeLabel.text = FormatDateSize(); + } + + private string FormatDateSize() + { + return $"{_package.Category} | {_package.FormattedSize()} | {_package.FormattedModified()}"; + } + + private void OpenPackageInBrowser() + { + Application.OpenURL($"https://publisher.unity.com/packages/{_package.VersionId}/edit/upload"); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs.meta new file mode 100644 index 00000000..9305aebd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cef5f23043d318945b844bcac7a7a984 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs new file mode 100644 index 00000000..6c549c0c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs @@ -0,0 +1,149 @@ +ο»Ώusing AssetStoreTools.Uploader.Data; +using AssetStoreTools.Uploader.Services; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PackageGroupElement : VisualElement + { + // Data + public string Name => _packageGroup.Name; + private IPackageGroup _packageGroup; + private List _packageElements; + private bool _isExpanded; + + private IPackageFactoryService _packageFactory; + + // UI + private Button _groupExpanderBox; + private VisualElement _groupContent; + + private Label _expanderLabel; + private Label _groupLabel; + + public PackageGroupElement(IPackageGroup packageGroup, IPackageFactoryService packageFactory) + { + _packageGroup = packageGroup; + _packageElements = new List(); + _packageGroup.OnPackagesSorted += RefreshPackages; + _packageGroup.OnPackagesFiltered += RefreshPackages; + + _packageFactory = packageFactory; + + Create(); + } + + private void Create() + { + CreatePackageGroup(); + CreatePackageGroupContent(); + AddPackagesToGroupContent(); + } + + protected void CreatePackageGroup() + { + _groupExpanderBox = new Button(OnPackageGroupClicked); + _groupExpanderBox.AddToClassList("package-group-expander-box"); + + _expanderLabel = new Label { name = "ExpanderLabel", text = "β–Ί" }; + _expanderLabel.AddToClassList("package-group-expander"); + + _groupLabel = new Label { text = $"{_packageGroup.Name} ({_packageGroup.Packages.Count})" }; + _groupLabel.AddToClassList("package-group-label"); + FormatGroupLabel(_packageGroup.Packages.Count); + + _groupExpanderBox.Add(_expanderLabel); + _groupExpanderBox.Add(_groupLabel); + + Add(_groupExpanderBox); + } + + private void CreatePackageGroupContent() + { + _groupContent = new VisualElement { name = "GroupContentBox" }; + _groupContent.AddToClassList("package-group-content-box"); + Toggle(false); + + var groupSeparator = new VisualElement { name = "GroupSeparator" }; + groupSeparator.AddToClassList("package-group-separator"); + + if (_packageGroup.Name.ToLower() != "draft") + { + _groupLabel.SetEnabled(false); + _groupContent.AddToClassList("unity-disabled"); + groupSeparator.style.display = DisplayStyle.Flex; + } + + Add(_groupContent); + Add(groupSeparator); + } + + private void AddPackagesToGroupContent() + { + foreach (var package in _packageGroup.Packages) + { + var packageElement = new PackageElement(package, _packageFactory); + packageElement.OnSelected += () => OnPackageSelected(packageElement); + _packageElements.Add(packageElement); + } + } + + private void FormatGroupLabel(int displayedPackageCount) + { + if (_packageGroup.Packages.Count == displayedPackageCount) + _groupLabel.text = $"{Name} ({displayedPackageCount})"; + else + _groupLabel.text = $"{Name} ({displayedPackageCount}/{_packageGroup.Packages.Count})"; + } + + private void RefreshPackages(List packages) + { + _groupContent.Clear(); + + foreach (var package in packages) + { + var correspondingElement = _packageElements.FirstOrDefault(x => x.Is(package)); + if (correspondingElement == null) + continue; + + _groupContent.Add(correspondingElement); + } + + FormatGroupLabel(packages.Count()); + } + + private void OnPackageGroupClicked() + { + Toggle(!_isExpanded); + } + + public void Toggle(bool expand) + { + if (expand) + { + _expanderLabel.text = "β–Ό"; + _groupContent.style.display = DisplayStyle.Flex; + } + else + { + _expanderLabel.text = "β–Ί"; + _groupContent.style.display = DisplayStyle.None; + } + + _isExpanded = expand; + } + + private void OnPackageSelected(PackageElement packageElement) + { + foreach (var element in _packageElements) + { + if (element == packageElement) + continue; + + element.Unselect(); + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs.meta new file mode 100644 index 00000000..a3216321 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 41e322a1418ab824182eade111145dff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageGroupElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs new file mode 100644 index 00000000..0dfc3c26 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs @@ -0,0 +1,58 @@ +ο»Ώusing AssetStoreTools.Uploader.Data; +using System.Collections.Generic; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PackageListToolbar : VisualElement + { + private List _packageGroups; + + public PackageListToolbar() + { + Create(); + } + + private void Create() + { + AddToClassList("package-list-toolbar"); + + // Search + var searchField = new ToolbarSearchField { name = "SearchField" }; + searchField.AddToClassList("package-search-field"); + + // Sorting menu button + var sortMenu = new ToolbarMenu() { text = "Sort: Name ↓" }; + sortMenu.menu.AppendAction("Sort: Name ↓", (_) => { sortMenu.text = "Sort: Name ↓"; Sort(PackageSorting.Name); }); + sortMenu.menu.AppendAction("Sort: Updated ↓", (_) => { sortMenu.text = "Sort: Updated ↓"; Sort(PackageSorting.Date); }); + sortMenu.menu.AppendAction("Sort: Category ↓", (_) => { sortMenu.text = "Sort: Category ↓"; Sort(PackageSorting.Category); }); + sortMenu.AddToClassList("package-sort-menu"); + + // Finalize the bar + Add(searchField); + Add(sortMenu); + + // Add Callbacks and click events + searchField.RegisterCallback>(SearchFilter); + } + + public void SetPackageGroups(List packageGroups) + { + _packageGroups = packageGroups; + } + + private void SearchFilter(ChangeEvent evt) + { + var searchString = evt.newValue.ToLower(); + foreach (var packageGroup in _packageGroups) + packageGroup.Filter(searchString); + } + + public void Sort(PackageSorting sortingType) + { + foreach (var packageGroup in _packageGroups) + packageGroup.Sort(sortingType); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs.meta new file mode 100644 index 00000000..afedf2ea --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6d2659328222e0e4cb36cd194e023f4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageListToolbar.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs new file mode 100644 index 00000000..06fe8eaa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs @@ -0,0 +1,321 @@ +using AssetStoreTools.Api; +using AssetStoreTools.Api.Responses; +using AssetStoreTools.Exporter; +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEditor; +#if !UNITY_2021_1_OR_NEWER +using UnityEditor.UIElements; +#endif +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PackageUploadElement : VisualElement + { + // Data + private IWorkflow _workflow; + private bool _enableExporting; + + // UI + private VisualElement _exportAndUploadContainer; + + private Button _cancelUploadButton; + private VisualElement _uploadProgressContainer; + private ProgressBar _uploadProgressBar; + private VisualElement _uploadProgressBarBackground; + + public event Action OnInteractionAvailable; + public event Action OnInteractionUnavailable; + + public PackageUploadElement(IWorkflow workflow, bool exposeExportButton) + { + _workflow = workflow; + _enableExporting = exposeExportButton; + + Create(); + } + + private void Create() + { + AddToClassList("uploading-box"); + + CreateButtonContainer(); + CreateProgressContainer(); + } + + private void CreateButtonContainer() + { + _exportAndUploadContainer = new VisualElement(); + _exportAndUploadContainer.AddToClassList("uploading-export-and-upload-container"); + + CreateExportButton(); + CreateUploadButton(); + Add(_exportAndUploadContainer); + } + + private void CreateExportButton() + { + if (!_enableExporting) + return; + + var _exportAndUploadButton = new Button(async () => await Export(true)) { name = "ExportButton", text = "Export" }; + _exportAndUploadButton.AddToClassList("uploading-export-button"); + + _exportAndUploadContainer.Add(_exportAndUploadButton); + } + + private void CreateUploadButton() + { + var _uploadButton = new Button(Upload) { name = "UploadButton" }; + _uploadButton.text = _enableExporting ? "Export and Upload" : "Upload"; + _uploadButton.AddToClassList("uploading-upload-button"); + + _exportAndUploadContainer.Add(_uploadButton); + } + + private void CreateProgressContainer() + { + _uploadProgressContainer = new VisualElement(); + _uploadProgressContainer.AddToClassList("uploading-progress-container"); + _uploadProgressContainer.style.display = DisplayStyle.None; + + _uploadProgressBar = new ProgressBar { name = "UploadProgressBar" }; + _uploadProgressBar.AddToClassList("uploading-progress-bar"); + _uploadProgressBarBackground = _uploadProgressBar.Q(className: "unity-progress-bar__progress"); + + _cancelUploadButton = new Button() { name = "CancelButton", text = "Cancel" }; + _cancelUploadButton.AddToClassList("uploading-cancel-button"); + + _uploadProgressContainer.Add(_uploadProgressBar); + _uploadProgressContainer.Add(_cancelUploadButton); + + Add(_uploadProgressContainer); + } + + private async Task Export(bool interactive) + { + try + { + DisableInteraction(); + + if (!_workflow.IsPathSet) + { + EditorUtility.DisplayDialog("Exporting failed", "No path was selected. Please " + + "select a path and try again.", "OK"); + return new PackageExporterResult() { Success = false, Exception = new Exception("No path was selected.") }; + } + + var rootProjectPath = Constants.RootProjectPath; + var packageNameStripped = Regex.Replace(_workflow.PackageName, "[^a-zA-Z0-9]", ""); + var outputName = $"{packageNameStripped}-{DateTime.Now:yyyy-dd-M--HH-mm-ss}"; + + string outputPath; + if (interactive) + { + outputPath = EditorUtility.SaveFilePanel("Export Package", rootProjectPath, + outputName, _workflow.PackageExtension.Remove(0, 1)); // Ignoring the '.' character since SaveFilePanel already appends it + + if (string.IsNullOrEmpty(outputPath)) + return new PackageExporterResult() { Success = false, Exception = null }; + } + else + { + outputPath = $"Temp/{outputName}{_workflow.PackageExtension}"; + } + + var exportResult = await _workflow.ExportPackage(outputPath); + if (!exportResult.Success) + { + Debug.LogError($"Package exporting failed: {exportResult.Exception}"); + EditorUtility.DisplayDialog("Exporting failed", exportResult.Exception.Message, "OK"); + } + else if (interactive) + Debug.Log($"Package exported to '{Path.GetFullPath(exportResult.ExportedPath).Replace("\\", "/")}'"); + + return exportResult; + } + finally + { + if (interactive) + EnableInteraction(); + } + } + + private async void Upload() + { + DisableInteraction(); + + if (await ValidateUnityVersionsBeforeUpload() == false) + { + EnableInteraction(); + return; + } + + var exportResult = await Export(false); + if (!exportResult.Success) + { + EnableInteraction(); + return; + } + + if (!_workflow.IsPathSet) + { + EditorUtility.DisplayDialog("Uploading failed", "No path was selected. Please " + + "select a path and try again.", "OK"); + EnableInteraction(); + return; + } + + _exportAndUploadContainer.style.display = DisplayStyle.None; + _uploadProgressContainer.style.display = DisplayStyle.Flex; + + _cancelUploadButton.clicked += Cancel; + _workflow.OnUploadStateChanged += UpdateProgressBar; + var response = await _workflow.UploadPackage(exportResult.ExportedPath); + _workflow.OnUploadStateChanged -= UpdateProgressBar; + + await OnUploadingStopped(response); + } + + private async Task ValidateUnityVersionsBeforeUpload() + { + var validationEnabled = ASToolsPreferences.Instance.UploadVersionCheck; + if (!validationEnabled) + return true; + + var requiredVersionUploaded = await _workflow.ValidatePackageUploadedVersions(); + if (requiredVersionUploaded) + return true; + + var result = EditorUtility.DisplayDialogComplex("Asset Store Tools", $"You may upload this package, but you will need to add a package using Unity version {Constants.Uploader.MinRequiredUnitySupportVersion} " + + "or higher to be able to submit a new asset", "Upload", "Cancel", "Upload and do not display this again"); + + switch (result) + { + case 1: + return false; + case 2: + ASToolsPreferences.Instance.UploadVersionCheck = false; + ASToolsPreferences.Instance.Save(); + break; + } + + return true; + } + + private void UpdateProgressBar(UploadStatus? status, float? progress) + { + if (status != null) + { + _uploadProgressBarBackground.style.backgroundColor = GetColorByStatus(status.Value); + } + + if (progress != null) + { + _uploadProgressBar.value = progress.Value; + _uploadProgressBar.title = $"{progress.Value:0.#}%"; + + if (progress == 100f && _cancelUploadButton.enabledInHierarchy) + _cancelUploadButton.SetEnabled(false); + } + } + + private void Cancel() + { + _cancelUploadButton.SetEnabled(false); + _workflow.AbortUpload(); + } + + private async Task OnUploadingStopped(PackageUploadResponse response) + { + if (!response.Success && !response.Cancelled) + { + Debug.LogException(response.Exception); + } + + if (response.Success) + { + await _workflow.RefreshPackage(); + } + + if (response.Status == UploadStatus.ResponseTimeout) + { + Debug.LogWarning($"All bytes for the package '{_workflow.PackageName}' have been uploaded, but a response " + + $"from the server was not received. This can happen because of Firewall restrictions. " + + $"Please make sure that a new version of your package has reached the Publishing Portal."); + } + + _uploadProgressBar.title = GetProgressBarTitleByStatus(response.Status); + + _cancelUploadButton.clickable = null; + _cancelUploadButton.clicked += Reset; + _cancelUploadButton.text = "Done"; + _cancelUploadButton.SetEnabled(true); + } + + private void Reset() + { + _cancelUploadButton.clickable = null; + _cancelUploadButton.text = "Cancel"; + + _workflow.ResetUploadStatus(); + UpdateProgressBar(UploadStatus.Default, 0f); + + _uploadProgressContainer.style.display = DisplayStyle.None; + _exportAndUploadContainer.style.display = DisplayStyle.Flex; + EnableInteraction(); + } + + public static Color GetColorByStatus(UploadStatus status) + { + switch (status) + { + default: + case UploadStatus.Default: + return new Color(0.13f, 0.59f, 0.95f); + case UploadStatus.Success: + case UploadStatus.ResponseTimeout: + return new Color(0f, 0.50f, 0.14f); + case UploadStatus.Cancelled: + return new Color(0.78f, 0.59f, 0f); + case UploadStatus.Fail: + return new Color(0.69f, 0.04f, 0.04f); + } + } + + private string GetProgressBarTitleByStatus(UploadStatus status) + { + var progressBarTitle = "Upload: "; + switch (status) + { + case UploadStatus.ResponseTimeout: + progressBarTitle += UploadStatus.Success; + break; + default: + progressBarTitle += status; + break; + } + + return progressBarTitle; + } + + private void EnableInteraction() + { + _exportAndUploadContainer.SetEnabled(true); + OnInteractionAvailable?.Invoke(); + } + + private void DisableInteraction() + { + _exportAndUploadContainer.SetEnabled(false); + OnInteractionUnavailable?.Invoke(); + SetEnabled(true); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs.meta new file mode 100644 index 00000000..8fed4c2e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 242524e968bd4484eaeb154d8013f427 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PackageUploadElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs new file mode 100644 index 00000000..d8d79bfb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs @@ -0,0 +1,63 @@ +using System; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PathSelectionElement : VisualElement + { + // Data + private string _labelText; + private string _labelTooltip; + + public event Action OnBrowse; + + // UI + private TextField _pathSelectionTextField; + + public PathSelectionElement(string labelText, string labelTooltip) + { + AddToClassList("package-content-option-box"); + + _labelText = labelText; + _labelTooltip = labelTooltip; + + Create(); + } + + private void Create() + { + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("package-content-option-label-help-row"); + + Label folderPathLabel = new Label { text = _labelText }; + Image folderPathLabelTooltip = new Image + { + tooltip = _labelTooltip + }; + + labelHelpRow.Add(folderPathLabel); + labelHelpRow.Add(folderPathLabelTooltip); + + _pathSelectionTextField = new TextField(); + _pathSelectionTextField.AddToClassList("package-content-option-textfield"); + _pathSelectionTextField.isReadOnly = true; + + Button browsePathButton = new Button(Browse) { name = "BrowsePathButton", text = "Browse" }; + browsePathButton.AddToClassList("package-content-option-button"); + + Add(labelHelpRow); + Add(_pathSelectionTextField); + Add(browsePathButton); + } + + private void Browse() + { + OnBrowse?.Invoke(); + } + + public void SetPath(string path) + { + _pathSelectionTextField.value = path; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs.meta new file mode 100644 index 00000000..22dc5e73 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 753d4442293e5cc4b9efcab089da4d59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PathSelectionElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs new file mode 100644 index 00000000..85332076 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs @@ -0,0 +1,109 @@ +using AssetStoreTools.Previews.Data; +using AssetStoreTools.Uploader.Data; +using System.Linq; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class PreviewGenerationElement : VisualElement + { + // Data + private IWorkflow _workflow; + + // UI + private VisualElement _toggleRow; + private Toggle _previewToggle; + + private VisualElement _buttonRow; + private VisualElement _viewButton; + + public PreviewGenerationElement(IWorkflow workflow) + { + _workflow = workflow; + + Create(); + } + + private void Create() + { + CreateInfoRow(); + CreateViewButton(); + } + + private void CreateInfoRow() + { + _toggleRow = new VisualElement(); + _toggleRow.AddToClassList("package-content-option-box"); + + VisualElement toggleLabelHelpRow = new VisualElement(); + toggleLabelHelpRow.AddToClassList("package-content-option-label-help-row"); + + Label toggleLabel = new Label { text = "Asset Previews" }; + Image toggleLabelTooltip = new Image + { + tooltip = "Select how the previews for your assets will be generated.\n\n" + + "Unity generates asset preview images natively up to a size of 128x128. " + + "You can try generating previews which are of higher resolution, up to 300x300.\n\n" + + "Note: these asset preview images will only be displayed in the 'Package Content' section of the " + + "Asset Store listing page once the package is published, and in the package importer window that appears during the package import process.\n" + + "They will not replace the images used for the assets in the Project window after the package gets imported." + }; + + _previewToggle = new Toggle { name = "PreviewToggle", text = "Generate Hi-Res (experimental)" }; + _previewToggle.AddToClassList("package-content-option-toggle"); + _previewToggle.RegisterValueChangedCallback((_) => DependencyToggleValueChange()); + + toggleLabelHelpRow.Add(toggleLabel); + toggleLabelHelpRow.Add(toggleLabelTooltip); + + _toggleRow.Add(toggleLabelHelpRow); + _toggleRow.Add(_previewToggle); + + Add(_toggleRow); + } + + private void CreateViewButton() + { + _buttonRow = new VisualElement(); + _buttonRow.AddToClassList("package-content-option-box"); + _buttonRow.style.display = DisplayStyle.None; + + var spaceFiller = new VisualElement(); + spaceFiller.AddToClassList("package-content-option-label-help-row"); + + _viewButton = new Button(ViewClicked) { text = "Inspect Previews" }; + + _buttonRow.Add(spaceFiller); + _buttonRow.Add(_viewButton); + + Add(_buttonRow); + } + + private void DependencyToggleValueChange() + { + _workflow.GenerateHighQualityPreviews = _previewToggle.value; + _buttonRow.style.display = _previewToggle.value ? DisplayStyle.Flex : DisplayStyle.None; + } + + private void ViewClicked() + { + PreviewGenerationSettings settings; + if (_workflow.GenerateHighQualityPreviews) + { + settings = new CustomPreviewGenerationSettings() { InputPaths = _workflow.GetAllPaths().ToArray() }; + } + else + { + settings = new NativePreviewGenerationSettings() { InputPaths = _workflow.GetAllPaths().ToArray() }; + } + + AssetStoreTools.ShowAssetStoreToolsPreviewGenerator(settings); + } + + private void DisplayProgress(float value) + { + EditorUtility.DisplayProgressBar("Generating", "Generating previews...", value); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs.meta new file mode 100644 index 00000000..2d303ac6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 54c7971e2ad639644936d3552b4f4f49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/PreviewGenerationElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs new file mode 100644 index 00000000..2d61e6d7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs @@ -0,0 +1,58 @@ +using AssetStoreTools.Uploader.Data; +using AssetStoreTools.Utility; +using UnityEditor; + +namespace AssetStoreTools.Uploader.UI.Elements +{ + internal class UnityPackageWorkflowElement : WorkflowElementBase + { + // Data + private UnityPackageWorkflow _workflow; + + public UnityPackageWorkflowElement(UnityPackageWorkflow workflow) : base(workflow) + { + _workflow = workflow; + Create(); + } + + private void Create() + { + CreatePathElement("Package path", "Select the .unitypackage file you would like to upload."); + CreateValidationElement(new ExternalProjectValidationElement(_workflow)); + CreateUploadElement(_workflow, false); + Deserialize(); + } + + protected override void BrowsePath() + { + // Path retrieval + var absolutePackagePath = EditorUtility.OpenFilePanel("Select a .unitypackage file", Constants.RootProjectPath, "unitypackage"); + + if (string.IsNullOrEmpty(absolutePackagePath)) + return; + + var relativeExportPath = FileUtility.AbsolutePathToRelativePath(absolutePackagePath, ASToolsPreferences.Instance.EnableSymlinkSupport); + if (!_workflow.IsPathValid(relativeExportPath, out var error)) + { + EditorUtility.DisplayDialog("Invalid selection", error, "OK"); + return; + } + + HandleUnityPackageUploadPathSelection(relativeExportPath, true); + } + + private void HandleUnityPackageUploadPathSelection(string selectedPackagePath, bool serialize) + { + if (string.IsNullOrEmpty(selectedPackagePath)) + return; + + _workflow.SetPackagePath(selectedPackagePath, serialize); + SetPathSelectionTextField(selectedPackagePath); + } + + protected override void Deserialize() + { + HandleUnityPackageUploadPathSelection(_workflow.GetPackagePath(), false); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs.meta new file mode 100644 index 00000000..d599e1ee --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7a0c8a79b7dba9e458ddc54eec30ea66 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Elements/UnityPackageWorkflowElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views.meta new file mode 100644 index 00000000..e5882f0d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7511d6ab930f33c469562bc3c1c2aab2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs new file mode 100644 index 00000000..30395723 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs @@ -0,0 +1,284 @@ +ο»Ώusing AssetStoreTools.Api.Models; +using AssetStoreTools.Uploader.Services.Api; +using AssetStoreTools.Utility; +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader.UI.Views +{ + internal class LoginView : VisualElement + { + // Data + private IAuthenticationService _authenticationService; + private double _cloudLoginRefreshTime = 1d; + private double _lastRefreshTime; + + // UI + private Button _cloudLoginButton; + private Label _cloudLoginLabel; + + private Box _errorBox; + private Label _errorLabel; + + private TextField _emailField; + private TextField _passwordField; + private Button _credentialsLoginButton; + + public event Action OnAuthenticated; + + public LoginView(IAuthenticationService authenticationService) + { + _authenticationService = authenticationService; + Create(); + } + + public void Create() + { + styleSheets.Add(StyleSelector.UploaderWindow.LoginViewStyle); + styleSheets.Add(StyleSelector.UploaderWindow.LoginViewTheme); + + CreateAssetStoreLogo(); + CreateCloudLogin(); + CreateErrorBox(); + CreateCredentialsLogin(); + } + + private void CreateAssetStoreLogo() + { + // Asset Store logo + Image assetStoreLogo = new Image { name = "AssetStoreLogo" }; + assetStoreLogo.AddToClassList("asset-store-logo"); + + Add(assetStoreLogo); + } + + private void CreateCloudLogin() + { + VisualElement cloudLogin = new VisualElement { name = "CloudLogin" }; + + _cloudLoginButton = new Button(LoginWithCloudToken) { name = "LoginButtonCloud" }; + _cloudLoginButton.AddToClassList("cloud-button-login"); + _cloudLoginButton.SetEnabled(false); + + _cloudLoginLabel = new Label { text = "Cloud login unavailable" }; + _cloudLoginLabel.AddToClassList("cloud-button-login-label"); + + Label orLabel = new Label { text = "or" }; + orLabel.AddToClassList("cloud-label-or"); + + _cloudLoginButton.Add(_cloudLoginLabel); + + cloudLogin.Add(_cloudLoginButton); + cloudLogin.Add(orLabel); + + UpdateCloudLoginButton(); + EditorApplication.update += UpdateCloudLoginButton; + Add(cloudLogin); + } + + private void CreateErrorBox() + { + _errorBox = new Box() { name = "LoginErrorBox" }; + _errorBox.AddToClassList("error-container"); + _errorBox.style.display = DisplayStyle.None; + + var errorImage = new Image(); + _errorBox.Add(errorImage); + + _errorLabel = new Label(); + _errorBox.Add(_errorLabel); + + Add(_errorBox); + } + + public void DisplayError(string message) + { + if (string.IsNullOrEmpty(message)) + return; + + _errorLabel.text = message; + Debug.LogError(message); + + _errorBox.style.display = DisplayStyle.Flex; + } + + private void ClearError() + { + _errorLabel.text = string.Empty; + _errorBox.style.display = DisplayStyle.None; + } + + private void CreateCredentialsLogin() + { + // Manual login + VisualElement manualLoginBox = new VisualElement { name = "ManualLoginBox" }; + manualLoginBox.AddToClassList("credentials-container"); + + // Email input box + VisualElement inputBoxEmail = new VisualElement(); + inputBoxEmail.AddToClassList("credentials-input-container"); + + Label emailTitle = new Label { text = "Email" }; + _emailField = new TextField(); + + inputBoxEmail.Add(emailTitle); + inputBoxEmail.Add(_emailField); + + manualLoginBox.Add(inputBoxEmail); + + // Password input box + VisualElement inputBoxPassword = new VisualElement(); + inputBoxPassword.AddToClassList("credentials-input-container"); + + Label passwordTitle = new Label { text = "Password" }; + _passwordField = new TextField { isPasswordField = true }; + + inputBoxPassword.Add(passwordTitle); + inputBoxPassword.Add(_passwordField); + + manualLoginBox.Add(inputBoxPassword); + + // Login button + _credentialsLoginButton = new Button(LoginWithCredentials) { name = "LoginButtonCredentials" }; + _credentialsLoginButton.AddToClassList("credentials-button-login"); + + Label loginDescriptionCredentials = new Label { text = "Login" }; + loginDescriptionCredentials.AddToClassList("credentials-button-login-label"); + + _credentialsLoginButton.Add(loginDescriptionCredentials); + + manualLoginBox.Add(_credentialsLoginButton); + + Add(manualLoginBox); + + // Credentials login helpers + VisualElement helperBox = new VisualElement { name = "HelperBox" }; + helperBox.AddToClassList("help-section-container"); + + Button createAccountButton = new Button { name = "CreateAccountButton", text = "Create Publisher ID" }; + Button forgotPasswordButton = new Button { name = "ForgotPasswordButton", text = "Reset Password" }; + + createAccountButton.AddToClassList("help-section-hyperlink-button"); + forgotPasswordButton.AddToClassList("help-section-hyperlink-button"); + + createAccountButton.clicked += () => Application.OpenURL(Constants.Uploader.AccountRegistrationUrl); + forgotPasswordButton.clicked += () => Application.OpenURL(Constants.Uploader.AccountForgottenPasswordUrl); + + helperBox.Add(createAccountButton); + helperBox.Add(forgotPasswordButton); + + Add(helperBox); + } + + public async void LoginWithSessionToken() + { + ASDebug.Log("Authenticating with session token..."); + ClearError(); + SetEnabled(false); + + var result = await _authenticationService.AuthenticateWithSessionToken(); + if (!result.Success) + { + // Session authentication fail does not display errors in the UI + ASDebug.Log("No existing session was found"); + SetEnabled(true); + return; + } + + OnLoginSuccess(result.User); + } + + private async void LoginWithCloudToken() + { + ASDebug.Log("Authenticating with cloud token..."); + ClearError(); + SetEnabled(false); + + var result = await _authenticationService.AuthenticateWithCloudToken(); + if (!result.Success) + { + OnLoginFail(result.Exception.Message); + return; + } + + OnLoginSuccess(result.User); + } + + private async void LoginWithCredentials() + { + ASDebug.Log("Authenticating with credentials..."); + ClearError(); + var isValid = IsLoginDataValid(_emailField.text, _passwordField.value); + SetEnabled(!isValid); + + if (!isValid) + return; + + var result = await _authenticationService.AuthenticateWithCredentials(_emailField.text, _passwordField.text); + if (result.Success) + OnLoginSuccess(result.User); + else + OnLoginFail(result.Exception.Message); + } + + private bool IsLoginDataValid(string email, string password) + { + if (string.IsNullOrEmpty(email)) + { + DisplayError("Email field cannot be empty."); + return false; + } + + if (string.IsNullOrEmpty(password)) + { + DisplayError("Password field cannot be empty."); + return false; + } + + return true; + } + + private void UpdateCloudLoginButton() + { + if (_cloudLoginLabel == null) + return; + + if (_lastRefreshTime + _cloudLoginRefreshTime > EditorApplication.timeSinceStartup) + return; + + _lastRefreshTime = EditorApplication.timeSinceStartup; + + // Cloud login + if (_authenticationService.CloudAuthenticationAvailable(out var username, out var _)) + { + _cloudLoginLabel.text = $"Login as {username}"; + _cloudLoginButton.SetEnabled(true); + } + else + { + _cloudLoginLabel.text = "Cloud login unavailable"; + _cloudLoginButton.SetEnabled(false); + } + } + + private void OnLoginSuccess(User user) + { + ASDebug.Log($"Successfully authenticated as {user.Username}\n{user}"); + + _emailField.value = string.Empty; + _passwordField.value = string.Empty; + + OnAuthenticated?.Invoke(user); + SetEnabled(true); + } + + private void OnLoginFail(string message) + { + ASDebug.LogError($"Authentication failed: {message}"); + DisplayError(message); + SetEnabled(true); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs.meta new file mode 100644 index 00000000..394be9b1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e20b8602a9bd8ca48a5689b3f32cdd90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/LoginView.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs new file mode 100644 index 00000000..a980d663 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs @@ -0,0 +1,249 @@ +ο»Ώusing AssetStoreTools.Uploader.Data; +using AssetStoreTools.Uploader.Services; +using AssetStoreTools.Uploader.Services.Api; +using AssetStoreTools.Uploader.UI.Elements; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine.SceneManagement; +using UnityEngine.UIElements; +using PackageModel = AssetStoreTools.Api.Models.Package; + +namespace AssetStoreTools.Uploader.UI.Views +{ + internal class PackageListView : VisualElement + { + // Data + private List _packages; + private readonly string[] _priorityGroupNames = { "draft", "published" }; + + private IPackageDownloadingService _packageDownloadingService; + private IPackageFactoryService _packageFactory; + + // UI + private LoadingSpinner _loadingSpinner; + private ScrollView _packageScrollView; + private PackageListToolbar _packageListToolbar; + + public event Action OnInitializeError; + + public PackageListView(IPackageDownloadingService packageDownloadingService, IPackageFactoryService elementFactory) + { + _packages = new List(); + _packageDownloadingService = packageDownloadingService; + _packageFactory = elementFactory; + + Create(); + EditorSceneManager.activeSceneChangedInEditMode += OnSceneChange; + } + + private void Create() + { + styleSheets.Add(StyleSelector.UploaderWindow.PackageListViewStyle); + styleSheets.Add(StyleSelector.UploaderWindow.PackageListViewTheme); + + AddToClassList("package-list-view"); + + CreateFilteringTools(); + CreateLoadingSpinner(); + CreateScrollView(); + + ShowPackagesView(); + } + + private void CreateScrollView() + { + _packageScrollView = new ScrollView(); + Add(_packageScrollView); + } + + private void CreateFilteringTools() + { + _packageListToolbar = new PackageListToolbar(); + Add(_packageListToolbar); + } + + private void CreateLoadingSpinner() + { + _loadingSpinner = new LoadingSpinner(); + Add(_loadingSpinner); + } + + private void InsertReadOnlyInfoBox(string infoText) + { + var groupHeader = new Box { name = "GroupReadOnlyInfoBox" }; + groupHeader.AddToClassList("package-group-info-box"); + + var infoImage = new Image(); + groupHeader.Add(infoImage); + + var infoLabel = new Label { text = infoText }; + groupHeader.Add(infoLabel); + + _packageScrollView.Add(groupHeader); + } + + public async Task LoadPackages(bool useCachedData) + { + _packages.Clear(); + _packageScrollView.Clear(); + _packageListToolbar.SetEnabled(false); + + if (!useCachedData) + { + _packageDownloadingService.ClearPackageData(); + } + + _loadingSpinner.Show(); + await Task.Delay(100); + + try + { + var response = await _packageDownloadingService.GetPackageData(); + + if (response.Cancelled) + { + ASDebug.Log("Package retrieval was cancelled"); + return; + } + + if (!response.Success) + { + ASDebug.LogError(response.Exception); + OnInitializeError?.Invoke(response.Exception); + return; + } + + var packageModels = response.Packages; + ASDebug.Log($"Found {packageModels.Count} packages"); + + if (packageModels.Count == 0) + { + InsertReadOnlyInfoBox("You do not have any packages yet. Please visit the Publishing Portal if you " + + "would like to create one."); + return; + } + + // Create package groups + _packages = CreatePackages(packageModels); + var packageGroups = CreatePackageGroups(_packages); + var packageGroupElements = CreatePackageGroupElements(packageGroups); + PopulatePackageList(packageGroupElements); + + // Setup filtering and thumbnails + SetupFilteringToolbar(packageGroups); + DownloadAndSetThumbnails(); + } + finally + { + _loadingSpinner.Hide(); + } + } + + private List CreatePackages(List packageModels) + { + return _packages = packageModels.Select(x => _packageFactory.CreatePackage(x)).ToList(); + } + + private List CreatePackageGroups(List packages) + { + var packageGroups = new List(); + var packagesByStatus = packages.GroupBy(x => x.Status).ToDictionary(x => x.Key, x => x.ToList()); + + foreach (var kvp in packagesByStatus) + { + var groupName = char.ToUpper(kvp.Key[0]) + kvp.Key.Substring(1); + var groupPackages = kvp.Value; + var packageGroup = _packageFactory.CreatePackageGroup(groupName, groupPackages); + packageGroups.Add(packageGroup); + } + + return packageGroups; + } + + private List CreatePackageGroupElements(List packageGroups) + { + var elements = new List(); + foreach (var packageGroup in packageGroups) + elements.Add(new PackageGroupElement(packageGroup, _packageFactory)); + + return elements; + } + + private void PopulatePackageList(List packageGroups) + { + // Draft group + var draftGroup = packageGroups.FirstOrDefault(x => x.Name.Equals("draft", StringComparison.OrdinalIgnoreCase)); + if (draftGroup != null) + { + draftGroup.Toggle(true); + _packageScrollView.Add(draftGroup); + } + + // Infobox will only be shown if: + // 1) There is more than 1 group OR + // 2) There is only 1 group, but it is not draft + var showInfoBox = packageGroups.Count > 1 + || packageGroups.Count == 1 && !packageGroups[0].Name.Equals("draft", StringComparison.OrdinalIgnoreCase); + + if (showInfoBox) + InsertReadOnlyInfoBox("Only packages with a 'Draft' status can be selected for uploading Assets"); + + // Priority groups + foreach (var priorityName in _priorityGroupNames) + { + var priorityGroup = packageGroups.FirstOrDefault(x => x.Name.Equals(priorityName, StringComparison.OrdinalIgnoreCase)); + if (priorityGroup == null || _packageScrollView.Contains(priorityGroup)) + continue; + + _packageScrollView.Add(priorityGroup); + } + + // The rest + foreach (var group in packageGroups) + { + if (!_packageScrollView.Contains(group)) + _packageScrollView.Add(group); + } + } + + private void SetupFilteringToolbar(List packageGroups) + { + _packageListToolbar.SetPackageGroups(packageGroups); + _packageListToolbar.Sort(PackageSorting.Name); + _packageListToolbar.SetEnabled(true); + } + + private void DownloadAndSetThumbnails() + { + foreach (var package in _packages) + { + DownloadAndSetThumbnail(package); + } + } + + private async void DownloadAndSetThumbnail(IPackage package) + { + var response = await _packageDownloadingService.GetPackageThumbnail(package); + if (!response.Success) + return; + + package.UpdateIcon(response.Thumbnail); + } + + private void ShowPackagesView() + { + _packageScrollView.style.display = DisplayStyle.Flex; + _packageListToolbar.style.display = DisplayStyle.Flex; + } + + private void OnSceneChange(Scene _, Scene __) + { + DownloadAndSetThumbnails(); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs.meta new file mode 100644 index 00000000..43e9178f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3c499c2d0a5e8fd4b9984184c59893e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Scripts/UI/Views/PackageListView.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta new file mode 100644 index 00000000..6040ca4a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9398c14296d30f479b9de5f3ec3b827 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView.meta new file mode 100644 index 00000000..03dac6e6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7564d91cabdce1344ba4a0fca25e13d5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss new file mode 100644 index 00000000..d97cb7a5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss @@ -0,0 +1,134 @@ +/* Logo */ + +.asset-store-logo { + width: 90%; + height: 32px; + + align-self: center; + + margin: 40px 0; + + -unity-background-scale-mode: scale-to-fit; +} + +/* Cloud Login */ + +.cloud-button-login { + align-self: center; + + width: 75%; +} + +.cloud-button-login-label { + -unity-text-align: middle-center; + white-space: normal; + + min-height: 24px; + padding-right: 4px; +} + +.cloud-label-or { + align-self: center; + + -unity-text-align: middle-center; + + margin: 10px 0; +} + +/* Error Section */ + +.error-container { + flex-direction: row; + flex-shrink: 0; + + align-self: center; + + min-width: 300px; + max-width: 300px; + + margin: 5px 0 5px 1px; +} + +.error-container > Image { + flex-direction: row; + + width: 32px; + height: 32px; + + margin: 5px 10px; +} + +.error-container > Label { + flex-grow: 1; + flex-shrink: 1; + + -unity-text-align: middle-left; + white-space: normal; + + margin-right: 5px; + padding: 2px 0; +} + +/* Credentials Login */ + +.credentials-container { + align-self: center; + + width: 75%; + + padding: 15px; +} + +.credentials-input-container { + align-self: center; + + width: 100%; + + margin: 5px 0; +} + +.credentials-input-container > Label { + -unity-text-align: upper-left; + + margin: 2px 0; +} + +.credentials-input-container > TextField { + height: 20px; + margin: 0 1px; +} + +.credentials-button-login { + align-self: center; + + width: 100%; + margin: 10px 0 15px 0; +} + +.credentials-button-login-label { + -unity-text-align: middle-center; + white-space: normal; + + min-height: 24px; + padding-right: 4px; +} + +/* Help Section */ + +.help-section-container { + flex-direction: row; + + justify-content: space-between; + align-self: center; + + width: 75%; + margin: 5px 0; +} + +.help-section-hyperlink-button { + margin: 0 10px; + padding: 0; + + flex-shrink: 1; + white-space: normal; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss.meta new file mode 100644 index 00000000..91ce4b51 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5e05fbdf7dd89a14985a87aa62a03a0e +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss new file mode 100644 index 00000000..39e3dfce --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss @@ -0,0 +1,44 @@ +/* Logo */ + +.asset-store-logo { + background-image: url("../../Icons/publisher-portal-dark.png"); +} + +/* Cloud Login */ + +.cloud-label-or { + color: rgb(200, 200, 200); +} + +/* Error Section */ + +.error-container { + background-color: rgb(63, 63, 63); +} + +.error-container > Image { + --unity-image: resource("console.erroricon@2x"); +} + +/* Credentials Login */ + +.credentials-container { + background-color: rgb(63, 63, 63); +} + +/* Help Section */ + +.help-section-hyperlink-button { + color: rgb(68, 113, 229); + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.help-section-hyperlink-button:hover { + color: rgb(68, 133, 229); + cursor: link; +} + +.help-section-hyperlink-button:active { + color: rgb(68, 93, 229); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss.meta new file mode 100644 index 00000000..2beccfd3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: bea9503736c358b4e99eac03c0db32b7 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss new file mode 100644 index 00000000..993c2b8c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss @@ -0,0 +1,44 @@ +/* Logo */ + +.asset-store-logo { + background-image: url("../../Icons/publisher-portal-light.png"); +} + +/* Cloud Login */ + +.cloud-label-or { + color: rgb(28, 28, 28); +} + +/* Error Section */ + +.error-container { + background-color: rgb(212, 212, 212); +} + +.error-container > Image { + --unity-image: resource("console.erroricon@2x"); +} + +/* Credentials Login */ + +.credentials-container { + background-color: rgb(212, 212, 212); +} + +/* Help Section */ + +.help-section-hyperlink-button { + color: rgb(68, 113, 229); + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.help-section-hyperlink-button:hover { + color: rgb(68, 133, 229); + cursor: link; +} + +.help-section-hyperlink-button:active { + color: rgb(68, 93, 229); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss.meta new file mode 100644 index 00000000..10f17a4a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 895ecc4cb6c82b144b8423996c89f7ef +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/LoginView/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView.meta new file mode 100644 index 00000000..f5446fd0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46d44b66f60dc484897f0afeee574dbe +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss new file mode 100644 index 00000000..d36598c1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss @@ -0,0 +1,485 @@ +.package-list-view { + flex-grow: 1; +} + +/* Package List Toolbar */ + +.package-list-toolbar { + flex-direction: row; + flex-shrink: 0; + + justify-content: space-between; + + height: 24px; +} + +.package-search-field { + flex-grow: 1; + flex-shrink: 1; + align-items: center; + + margin: 1px; +} + +.package-search-field > #unity-search { + margin-top: 0; +} + +.package-search-field > * > .unity-base-field__input { + font-size: 12px; + + padding-left: 5px; +} + +.package-sort-menu { + flex-shrink: 0.001; + align-self: center; + + height: 21px; + + margin: 1px; + padding: 1px 6px; +} + +/* Loading Spinner */ + +.loading-spinner-box +{ + flex-grow: 1; + flex-shrink: 1; + + justify-content: center; +} + +.loading-spinner-image { + align-self: center; + + width: 16px; + height: 16px; +} + +/* Package Group */ + +.package-group-expander-box { + flex-direction: row; + flex-grow: 0; + flex-shrink: 0; + + align-items: center; + + min-height: 30px; + + margin: 10px 0 2px 0; + padding: 1px 5px; +} + +.package-group-expander +{ + align-self: center; + + width: 30px; + height: 30px; +} + +.package-group-label { + font-size: 14px; + -unity-font-style: bold; +} + +.package-group-content-box { + margin: 0; +} + +.package-group-separator { + height: 2px; + + margin: 5px 15px; + + display: none; +} + +.package-group-info-box { + flex-direction: row; + align-items: center; + font-size: 12px; + margin: 5px; + margin-top: 5px; +} + +.package-group-info-box > Image +{ + flex-direction: row; + flex-shrink: 0; + + width: 32px; + height: 32px; + + margin: 5px 10px; +} + +.package-group-info-box > Label +{ + flex-grow: 1; + flex-shrink: 1; + + -unity-text-align: middle-left; + white-space: normal; + + margin-right: 5px; +} + +/* Package Element */ + +.package-full-box { + flex-direction: column; + flex-shrink: 0; + flex-grow: 0; + + min-width: 280px; +} + +.package-foldout-box { + flex-direction: column; + margin: 0; +} + +.package-foldout-box-expanded { + padding-top: 3px; + top: -2px; +} + +.package-foldout-box-info { + flex-direction: row; + flex-grow: 0; + flex-shrink: 0; + + align-items: center; + justify-content: space-between; + + min-width: 200px; + min-height: 50px; + + margin: 2px; +} + +.package-expander-label-row { + flex-basis: 200px; + flex-direction: row; + flex-grow: 1; +} + +.package-expander { + align-self: center; + + width: 30px; + height: 30px; +} + +.package-image { + flex-shrink: 0; + + width: 48px; + height: 48px; + + margin: 0 5px; +} + +.package-label-info-box { + flex-direction: column; + flex-grow: 1; + flex-shrink: 1; + + align-self: center; +} + +.package-label { + flex-shrink: 1; + + align-self: stretch; + + -unity-text-align: middle-left; + -unity-font-style: bold; + white-space: normal; +} + +.package-info { + font-size: 11px; + -unity-text-align: middle-left; + white-space: normal; +} + +.package-open-in-browser-button { + flex-shrink: 0; + + width: 16px; + height: 16px; + + -unity-background-scale-mode: scale-to-fit; +} + +.package-header-progress-bar { + margin: 0 -6px -1px -6px; + padding: 0 0 2px 0; +} + +.package-header-progress-bar > * > .unity-progress-bar__background { + height: 5px; +} + +/* Package Content Element & its nested elements */ + +.package-content-element { + flex-grow: 1; + flex-shrink: 0; + + overflow: hidden; + + margin: -5px 0px 2px 0px; + padding: 5px 10px 5px 40px; +} + +.package-content-option-box { + flex-direction: row; + + margin-top: 10px; +} + +.package-content-option-label-help-row { + flex-direction: row; + flex-shrink: 0; + + align-self: flex-start; + align-items: center; + justify-content: flex-start; + + width: 115px; +} + +.package-content-option-label-help-row > Label { + -unity-text-align: middle-left; +} + +.package-content-option-label-help-row > Image { + height: 16px; + width: 16px; +} + +.package-content-option-dropdown { + flex-grow: 1; + flex-shrink: 1; + + align-self: stretch; + + margin-right: 0; + margin-left: 3px; +} + +.package-content-option-textfield { + flex-grow: 1; + flex-shrink: 1; + + align-self: stretch; +} + +.package-content-option-button { + margin-right: 0; +} + +.package-content-option-toggle { + flex-shrink: 1; +} + +.package-content-option-toggle > * { + flex-shrink: 1; +} + +.package-content-option-toggle * > .unity-label { + flex-shrink: 1; + overflow: hidden; + text-overflow: ellipsis; + margin-left: 5px; +} + +/* MutliToggleSelection Element */ + +.multi-toggle-box { + flex-grow: 1; + flex-direction: column; +} + +.multi-toggle-box-scrollview { + flex-grow: 1; + + height: 100px; + margin-left: 3px; +} + +.multi-toggle-box-scrollview > .unity-scroll-view__content-viewport +{ + margin-left: 1px; +} + +.multi-toggle-box-scrollview > * > .unity-scroll-view__content-container +{ + padding: 3px 0 5px 0; +} + +.multi-toggle-box-scrollview > * > .unity-scroll-view__vertical-scroller +{ + margin: -1px 0; +} + +.multi-toggle-box-empty-label { + flex-grow: 1; + + font-size: 11px; + -unity-text-align: middle-center; + white-space: normal; + + display: none; +} + +.multi-toggle-box-toolbar { + flex-direction: row; + margin: -1px 0 0 3px; +} + +.multi-toggle-box-toolbar-selecting-box { + flex-grow: 1; + flex-shrink: 1; + flex-direction: row; + + align-items: center; + justify-content: flex-end; + + margin-top: 1px; +} + +.multi-toggle-box-toolbar-selecting-box > Button { + flex-shrink: 1; + width: 75px; + margin-right: 0; +} + +.multi-toggle-box-toolbar-filtering-box { + flex-grow: 1; + flex-direction: row; + + align-items: center; + justify-content: flex-start; + + margin-top: 1px; + margin-left: 1px; +} + +.multi-toggle-box-toolbar-filtering-box > ToolbarMenu { + width: 100px; + margin: 0; +} + +.multi-toggle-box-toggle { + padding: 2px 0 0 5px; +} + +.multi-toggle-box-toggle > * > .unity-label { + margin-left: 5px; +} + +/* Validation Element */ + +.validation-result-box { + flex-direction: row; + + align-items: center; + + font-size: 12px; + + margin-top: 5px; +} + +.validation-result-box > Image { + flex-direction: row; + flex-shrink: 0; + + width: 32px; + height: 32px; + + margin: 5px 10px; +} + +.validation-result-box > Label { + flex-grow: 1; + flex-shrink: 1; + + -unity-text-align: middle-left; + white-space: normal; + + margin-right: 5px; +} + +.validation-result-box > Button { + margin-right: 10px; +} + +.validation-result-view-report-button-container { + flex-shrink: 0; + padding: 0 10px 0 10px; +} + +.validation-result-view-report-button { + margin: 0; + padding: 4px 0 4px 0; +} + +.validation-result-view-report-button:hover { + cursor: link; +} + +/* Uploading Element */ + +.uploading-box { + margin-top: 10px; +} + +.uploading-export-and-upload-container { + flex-direction: row; + flex-wrap: wrap; +} + +.uploading-export-button { + flex-basis: 110px; + flex-grow: 1; + height: 24px; + margin: 1px 2px 0 2px; +} + +.uploading-upload-button { + flex-basis: 110px; + flex-grow: 1; + height: 24px; + margin: 1px 2px 0 2px; +} + +.uploading-progress-container { + flex-direction: row; +} + +.uploading-progress-bar { + flex-grow: 1; + flex-shrink: 1; + + justify-content: center; + + padding: 0; + margin: 0 10px 0 0; +} + +.uploading-progress-bar > * > .unity-progress-bar__background { + height: 22px; +} + +.uploading-cancel-button { + width: 95px; + height: 24px; + margin: 0; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss.meta new file mode 100644 index 00000000..d2610f84 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4b3b52dc166e3e24bb1ce4acd2592f3a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss new file mode 100644 index 00000000..a0ef9ed4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss @@ -0,0 +1,238 @@ +/* Package List Toolbar */ + +.package-list-toolbar { + border-bottom-width: 1px; + border-color: rgb(33, 33, 33); + + background-color: rgb(68, 68, 68); +} + +.package-sort-menu { + color: rgb(238, 238, 238); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(36, 36, 36); + + background-color: rgb(88, 88, 88); +} + +.package-sort-menu:hover { + background-color: rgb(103, 103, 103); +} + +.package-sort-menu:active { + background-color: rgb(73, 73, 73); +} + +/* Loading Spinner */ + +.loading-spinner-image { + --unity-image: resource("WaitSpin00"); +} + +/* Package Group */ + +.package-group-expander-box { + border-width: 0; + border-color: rgba(33, 33, 33, 0); + + background-color: rgba(68, 68, 68, 0); +} + +.package-group-expander { + color: rgb(104, 104, 104); +} + +.package-group-label { + color: rgb(255, 255, 255); +} + +.package-group-separator { + background-color: rgb(48, 48, 48); +} + +.package-group-info-box { + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.package-group-info-box > Image { + --unity-image: resource("console.infoicon@2x"); +} + +/* Package Element */ + +.package-foldout-box { + border-width: 0; + border-radius: 0; + background-color: rgb(56, 56, 56); +} + +.package-foldout-box:hover { + background-color: rgb(68, 68, 68); +} + +.package-foldout-box-draft:active { + background-color: rgb(48, 48, 48); +} + +.package-foldout-box-expanded { + background-color: rgb(68, 68, 68); +} + +.package-expander { + color: rgb(104, 104, 104); +} + +.package-image { + border-radius: 5px; + background-image: resource("Sprite Icon"); +} + +.package-label { + color: rgb(255, 255, 255); +} + +.package-info { + color: rgb(200, 200, 200); +} + +.package-open-in-browser-button { + border-width: 0; + border-radius: 0; + + background-color: rgba(0, 0, 0, 0); + background-image: url("../../Icons/open-in-browser.png"); + + -unity-background-image-tint-color: rgb(200, 200, 200); +} + +.package-open-in-browser-button:hover { + -unity-background-image-tint-color: rgb(255, 255, 255); +} + +.package-open-in-browser-button:active { + -unity-background-image-tint-color: rgb(155, 155, 155); +} + +.package-header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background { + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.package-header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress { + background-image: none; + background-color: rgb(33, 150, 243); +} + +/* Package Content Element */ + +.package-content-element { + background-color: rgb(68, 68, 68); +} + +.package-content-option-label-help-row > Image { + --unity-image: resource("d__Help@2x"); +} + +.package-content-option-dropdown { + color: rgb(238, 238, 238); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(36, 36, 36); + + background-color: rgb(88, 88, 88); +} + +.package-content-option-dropdown:hover { + background-color: rgb(103, 103, 103); +} + +/* MultiToggleSelection Element */ + +.multi-toggle-box-scrollview { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(58, 58, 58); +} + +.multi-toggle-box-scrollview > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.multi-toggle-box-empty-label { + color: rgb(200, 200, 200); +} + +.multi-toggle-box-toolbar { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(58, 58, 58); +} + +.multi-toggle-box-toolbar-filtering-box > ToolbarMenu { + color: rgb(188, 188, 188); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(36, 36, 36); + + background-color: rgb(88, 88, 88); +} + +/* Validation Element */ + +.validation-result-box { + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.validation-result-box > Image { + --unity-image: resource("console.infoicon@2x"); +} + +.validation-result-view-report-button { + color: rgb(68, 113, 229); + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.validation-result-view-report-button:hover { + color: rgb(68, 133, 229); +} + +.validation-result-view-report-button:active { + color: rgb(68, 93, 229); +} + +/* Uploading Element */ + +.uploading-export-button { + color: rgb(220, 220, 220); + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.uploading-upload-button { + color: rgb(220, 220, 220); + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.uploading-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background { + border-width: 0; + border-radius: 2px; +} + +.uploading-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress { + background-image: none; + background-color: rgb(33, 150, 243); +} + +.uploading-cancel-button { + color: rgb(220, 220, 220); + border-width: 1px; + border-color: rgb(33, 33, 33); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss.meta new file mode 100644 index 00000000..59f35b0c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2096f0ee5b05ec643b409ded0d725eb3 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss new file mode 100644 index 00000000..d375fca0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss @@ -0,0 +1,238 @@ +/* Package List Toolbar */ + +.package-list-toolbar { + border-bottom-width: 1px; + border-color: rgb(127, 127, 127); + + background-color: rgb(203, 203, 203); +} + +.package-sort-menu { + color: rgb(9, 9, 9); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(178, 178, 178); + + background-color: rgb(228, 228, 228); +} + +.package-sort-menu:hover { + background-color: rgb(236, 236, 236); +} + +.package-sort-menu:active { + background-color: rgb(220, 220, 220); +} + +/* Loading Spinner */ + +.loading-spinner-image { + --unity-image: resource("WaitSpin00"); +} + +/* Package Group */ + +.package-group-expander-box { + border-width: 0; + border-color: rgba(0, 0, 0, 0); + + background-color: rgba(0, 0, 0, 0); +} + +.package-group-expander { + color: rgb(77, 77, 77); +} + +.package-group-label { + color: rgb(0, 0, 0); +} + +.package-group-separator +{ + background-color: rgb(48, 48, 48); +} + +.package-group-info-box +{ + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.package-group-info-box > Image +{ + --unity-image: resource("console.infoicon@2x"); +} + +/* Package Element */ + +.package-foldout-box { + border-width: 0; + border-radius: 0; + background-color: rgb(198, 198, 198); +} + +.package-foldout-box:hover { + background-color: rgb(212, 212, 212); +} + +.package-foldout-box-draft:active { + background-color: rgb(180, 180, 180); +} + +.package-foldout-box-expanded { + background-color: rgb(212, 212, 212); +} + +.package-expander { + color: rgb(77, 77, 77); +} + +.package-image { + border-radius: 5px; + background-image: resource("Sprite Icon"); +} + +.package-label { + color: rgb(0, 0, 0); +} + +.package-info { + color: rgb(48, 48, 48); +} + +.package-open-in-browser-button { + border-width: 0; + border-radius: 0; + + background-color: rgba(0, 0, 0, 0); + background-image: url("../../Icons/open-in-browser.png"); + + -unity-background-image-tint-color: rgb(150, 150, 150); +} + +.package-open-in-browser-button:hover { + -unity-background-image-tint-color: rgb(100, 100, 100); +} + +.package-open-in-browser-button:active { + -unity-background-image-tint-color: rgb(50, 50, 50); +} + +.package-header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background { + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.package-header-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress { + background-image: none; + background-color: rgb(108, 157, 243); +} + +/* Package Content Element */ + +.package-content-element { + background-color: rgb(212, 212, 212); +} + +.package-content-option-label-help-row > Image { + --unity-image: resource("_Help@2x"); +} + +.package-content-option-dropdown { + color: rgb(9, 9, 9); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(178, 178, 178); + + background-color: rgb(228, 228, 228); +} + +.package-content-option-dropdown:hover { + background-color: rgb(236, 236, 236); +} + +/* MultiToggleSelection Element */ + +.multi-toggle-box-scrollview { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(200, 200, 200); +} + +.multi-toggle-box-scrollview > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.multi-toggle-box-empty-label { + color: rgb(0, 0, 0); +} + +.multi-toggle-box-toolbar { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(200, 200, 200); +} + +.multi-toggle-box-toolbar-filtering-box > ToolbarMenu { + color: rgb(9, 9, 9); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(178, 178, 178); + + background-color: rgb(228, 228, 228); +} + +/* Validation Element */ + +.validation-result-box { + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.validation-result-box > Image { + --unity-image: resource("console.infoicon@2x"); +} + +.validation-result-view-report-button { + color: rgb(68, 113, 229); + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.validation-result-view-report-button:hover { + color: rgb(68, 133, 229); +} + +.validation-result-view-report-button:active { + color: rgb(68, 93, 229); +} + +/* Uploading Element */ + +.uploading-export-button { + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.uploading-upload-button { + border-width: 1px; + border-color: rgb(33, 33, 33); +} + +.uploading-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background { + border-width: 0; + border-radius: 2px; +} + +.uploading-progress-bar > .unity-progress-bar__container > .unity-progress-bar__background > .unity-progress-bar__progress { + background-image: none; + background-color: rgb(108, 157, 243); +} + +.uploading-cancel-button { + border-width: 1px; + border-color: rgb(33, 33, 33); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss.meta new file mode 100644 index 00000000..3c75bb10 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9b79808cdce73b949abc32c5fada1bda +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/PackageListView/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss new file mode 100644 index 00000000..6a692613 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss @@ -0,0 +1,74 @@ +.uploader-window-root { + flex-grow: 1; +} + +.uploader-window-root-scrollview { + flex-grow: 1; +} + +.uploader-window-root-scrollview > * > .unity-scroll-view__content-container { + flex-grow: 1; +} + +.uploader-window-root-scrollview > * > .unity-scroll-view__content-viewport { + flex-shrink: 1; +} + +.uploader-window-root-scrollview > * > * > .unity-scroll-view__content-container { + flex-grow: 1; + flex-shrink: 1; +} + +.account-toolbar { + flex-direction: row; + flex-shrink: 0; + + justify-content: space-between; + margin: 0; +} + +.account-toolbar-left-side-container { + flex-grow: 1; + flex-shrink: 0; + flex-basis: 0px; + overflow: hidden; + min-width: 16px; + align-self: center; + flex-direction: row; + margin: 3px 0px 3px 1px; +} + +.account-toolbar-right-side-container { + flex-shrink: 1; + flex-grow: 0; + flex-wrap: wrap; + align-self: center; + flex-direction: row; + margin: 0; +} + +.account-toolbar-user-image { + width: 16px; + height: 16px; + flex-shrink: 0; + margin-right: 1px; +} + +.account-toolbar-email-label { + flex-shrink: 1; + overflow: hidden; + text-overflow: ellipsis; + -unity-font-style: bold; +} + +.account-toolbar-button-refresh { + flex-grow: 1; + min-width: 50px; + margin-right: 1px; +} + +.account-toolbar-button-logout { + flex-grow: 1; + min-width: 50px; + margin-right: 1px; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss.meta new file mode 100644 index 00000000..5c66c3e7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6f0343bfa66bbb344bee68a23d24cca8 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss new file mode 100644 index 00000000..7f836d43 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss @@ -0,0 +1,9 @@ +.account-toolbar { + background-color: rgb(68, 68, 68); + border-color: rgb(33, 33, 33); + border-top-width: 1px; +} + +.account-toolbar-user-image { + background-image: url("../Icons/account-dark.png"); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss.meta new file mode 100644 index 00000000..ee3b491d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 26d328c2ffac2ff44af266e9c632f2ab +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss new file mode 100644 index 00000000..16e3de4d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss @@ -0,0 +1,9 @@ +.account-toolbar { + background-color: rgb(203, 203, 203); + border-color: rgb(127, 127, 127); + border-top-width: 1px; +} + +.account-toolbar-user-image { + background-image: url("../Icons/account-light.png"); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss.meta new file mode 100644 index 00000000..8ddebb5f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a994594cc493b7346b4d4a71d39908dc +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/Styles/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs b/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs new file mode 100644 index 00000000..f9fffa9b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs @@ -0,0 +1,232 @@ +using AssetStoreTools.Api.Models; +using AssetStoreTools.Uploader.Services; +using AssetStoreTools.Uploader.Services.Analytics; +using AssetStoreTools.Uploader.Services.Api; +using AssetStoreTools.Uploader.UI.Elements; +using AssetStoreTools.Uploader.UI.Views; +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Uploader +{ + internal class UploaderWindow : AssetStoreToolsWindow + { + private const string DebugPhrase = "debug"; + + // Services + private ICachingService _cachingService; + private IAuthenticationService _authenticationService; + private IPackageDownloadingService _packageDownloadingService; + private IPackageUploadingService _packageUploadingService; + private IAnalyticsService _analyticsService; + private IPackageFactoryService _packageFactoryService; + + // Data + private bool _isQuitting = false; + + // UI + private VisualElement _uploaderWindowRoot; + private ScrollView _rootScrollView; + + private LoginView _loginView; + private PackageListView _packageListView; + private AccountToolbar _accountToolbar; + + protected override string WindowTitle => "Asset Store Uploader"; + + protected override void Init() + { + RegisterServices(); + SetupWindow(); + } + + private void RegisterServices() + { + var uploaderServiceProvider = UploaderServiceProvider.Instance; + _analyticsService = uploaderServiceProvider.GetService(); + _cachingService = uploaderServiceProvider.GetService(); + _authenticationService = uploaderServiceProvider.GetService(); + _packageDownloadingService = uploaderServiceProvider.GetService(); + _packageUploadingService = uploaderServiceProvider.GetService(); + _packageFactoryService = uploaderServiceProvider.GetService(); + } + + private void SetupWindow() + { + minSize = new Vector2(400, 430); + this.SetAntiAliasing(4); + rootVisualElement.styleSheets.Add(StyleSelector.UploaderWindow.UploaderWindowStyle); + rootVisualElement.styleSheets.Add(StyleSelector.UploaderWindow.UploaderWindowTheme); + + if (_cachingService.GetCachedUploaderWindow(out _uploaderWindowRoot)) + { + rootVisualElement.Add(_uploaderWindowRoot); + return; + } + + _uploaderWindowRoot = new VisualElement(); + _uploaderWindowRoot.AddToClassList("uploader-window-root"); + rootVisualElement.Add(_uploaderWindowRoot); + + _rootScrollView = new ScrollView(); + _rootScrollView.AddToClassList("uploader-window-root-scrollview"); + _uploaderWindowRoot.Add(_rootScrollView); + + CreateLoginView(); + CreatePackageListView(); + CreateAccountToolbar(); + EditorApplication.wantsToQuit += OnWantsToQuit; + + _cachingService.CacheUploaderWindow(_uploaderWindowRoot); + + PerformAuthentication(); + } + + private void CreateLoginView() + { + _loginView = new LoginView(_authenticationService); + _loginView.OnAuthenticated += OnAuthenticationSuccess; + _rootScrollView.Add(_loginView); + } + + private void CreatePackageListView() + { + _packageListView = new PackageListView(_packageDownloadingService, _packageFactoryService); + _packageListView.OnInitializeError += PackageViewInitializationError; + _rootScrollView.Add(_packageListView); + } + + private void CreateAccountToolbar() + { + _accountToolbar = new AccountToolbar(); + _accountToolbar.OnRefresh += RefreshPackages; + _accountToolbar.OnLogout += LogOut; + _uploaderWindowRoot.Add(_accountToolbar); + } + + private void PerformAuthentication() + { + ShowAuthenticationView(); + _loginView.LoginWithSessionToken(); + } + + private async void OnAuthenticationSuccess(User user) + { + _accountToolbar.SetUser(user); + _accountToolbar.DisableButtons(); + + ShowAccountPackageView(); + await _packageListView.LoadPackages(true); + + _accountToolbar.EnableButtons(); + } + + private async Task RefreshPackages() + { + _packageUploadingService.StopAllUploadinng(); + _packageDownloadingService.StopDownloading(); + + await _packageListView.LoadPackages(false); + } + + private void LogOut() + { + _packageUploadingService.StopAllUploadinng(); + _packageDownloadingService.StopDownloading(); + + _authenticationService.Deauthenticate(); + _packageDownloadingService.ClearPackageData(); + + _accountToolbar.SetUser(null); + ShowAuthenticationView(); + } + + private void PackageViewInitializationError(Exception e) + { + _loginView.DisplayError(e.Message); + LogOut(); + } + + private void ShowAuthenticationView() + { + HideElement(_accountToolbar); + HideElement(_packageListView); + ShowElement(_loginView); + } + + private void ShowAccountPackageView() + { + HideElement(_loginView); + ShowElement(_accountToolbar); + ShowElement(_packageListView); + } + + private void ShowElement(params VisualElement[] elements) + { + foreach (var e in elements) + e.style.display = DisplayStyle.Flex; + } + + private void HideElement(params VisualElement[] elements) + { + foreach (var e in elements) + e.style.display = DisplayStyle.None; + } + + private void OnDestroy() + { + if (!_isQuitting && _packageUploadingService.IsUploading) + { + EditorUtility.DisplayDialog("Notice", "Assets are still being uploaded to the Asset Store. " + + "If you wish to check on the progress, please re-open the Asset Store Uploader window", "OK"); + } + } + + private bool OnWantsToQuit() + { + if (!_packageUploadingService.IsUploading) + return true; + + _isQuitting = EditorUtility.DisplayDialog("Notice", "Assets are still being uploaded to the Asset Store. " + + "Would you still like to close Unity Editor?", "Yes", "No"); + + return _isQuitting; + } + + #region Debug Utility + + private readonly List _debugBuffer = new List(); + + private void OnGUI() + { + CheckForDebugMode(); + } + + private void CheckForDebugMode() + { + Event e = Event.current; + + if (e.type != EventType.KeyDown || e.keyCode == KeyCode.None) + return; + + _debugBuffer.Add(e.keyCode.ToString().ToLower()[0]); + if (_debugBuffer.Count > DebugPhrase.Length) + _debugBuffer.RemoveAt(0); + + if (string.Join(string.Empty, _debugBuffer.ToArray()) != DebugPhrase) + return; + + ASDebug.DebugModeEnabled = !ASDebug.DebugModeEnabled; + ASDebug.Log($"DEBUG MODE ENABLED: {ASDebug.DebugModeEnabled}"); + _debugBuffer.Clear(); + } + + #endregion + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs.meta new file mode 100644 index 00000000..2a90137e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7b5319699cc84194a9a768ad33b86c21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Uploader/UploaderWindow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility.meta b/Packages/com.unity.asset-store-tools/Editor/Utility.meta new file mode 100644 index 00000000..9a2bdffe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3dfd03e520c145b45a32c7e2915fe3cb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs new file mode 100644 index 00000000..16fc4c8b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs @@ -0,0 +1,65 @@ +ο»Ώusing UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Utility +{ + internal static class ASDebug + { + private enum LogType + { + Info, + Warning, + Error + } + + private static string FormatInfo(object message) => $"[AST Info] {message}"; + private static string FormatWarning(object message) => $"[AST Warning] {message}"; + private static string FormatError(object message) => $"[AST Error] {message}"; + + + private static bool s_debugModeEnabled = EditorPrefs.GetBool(Constants.Debug.DebugModeKey); + + public static bool DebugModeEnabled + { + get => s_debugModeEnabled; + set { s_debugModeEnabled = value; EditorPrefs.SetBool(Constants.Debug.DebugModeKey, value); } + } + + public static void Log(object message) + { + LogMessage(message, LogType.Info); + } + + public static void LogWarning(object message) + { + LogMessage(message, LogType.Warning); + } + + public static void LogError(object message) + { + LogMessage(message, LogType.Error); + } + + private static void LogMessage(object message, LogType type) + { + if (!DebugModeEnabled) + return; + + switch (type) + { + case LogType.Info: + Debug.Log(FormatInfo(message)); + break; + case LogType.Warning: + Debug.LogWarning(FormatWarning(message)); + break; + case LogType.Error: + Debug.LogError(FormatError(message)); + break; + default: + Debug.Log(message); + break; + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta new file mode 100644 index 00000000..2af38a3e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 478caa497d99100429a0509fa487bfe4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASDebug.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs new file mode 100644 index 00000000..73ad2bde --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs @@ -0,0 +1,134 @@ +ο»Ώusing System; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Utility +{ + internal class ASToolsPreferences + { + private static ASToolsPreferences s_instance; + public static ASToolsPreferences Instance => s_instance ?? (s_instance = new ASToolsPreferences()); + + public static event Action OnSettingsChange; + + private ASToolsPreferences() + { + Load(); + } + + private void Load() + { + CheckForUpdates = PlayerPrefs.GetInt("AST_CheckForUpdates", 1) == 1; + LegacyVersionCheck = PlayerPrefs.GetInt("AST_LegacyVersionCheck", 1) == 1; + UploadVersionCheck = PlayerPrefs.GetInt("AST_UploadVersionCheck", 1) == 1; + DisplayHiddenMetaDialog = PlayerPrefs.GetInt("AST_HiddenFolderMetaCheck", 1) == 1; + EnableSymlinkSupport = PlayerPrefs.GetInt("AST_EnableSymlinkSupport", 0) == 1; + UseLegacyExporting = PlayerPrefs.GetInt("AST_UseLegacyExporting", 0) == 1; + } + + public void Save(bool triggerSettingsChange = false) + { + PlayerPrefs.SetInt("AST_CheckForUpdates", CheckForUpdates ? 1 : 0); + PlayerPrefs.SetInt("AST_LegacyVersionCheck", LegacyVersionCheck ? 1 : 0); + PlayerPrefs.SetInt("AST_UploadVersionCheck", UploadVersionCheck ? 1 : 0); + PlayerPrefs.SetInt("AST_HiddenFolderMetaCheck", DisplayHiddenMetaDialog ? 1 : 0); + PlayerPrefs.SetInt("AST_EnableSymlinkSupport", EnableSymlinkSupport ? 1 : 0); + PlayerPrefs.SetInt("AST_UseLegacyExporting", UseLegacyExporting ? 1 : 0); + PlayerPrefs.Save(); + + if (triggerSettingsChange) + OnSettingsChange?.Invoke(); + } + + /// + /// Periodically check if an update for the Asset Store Publishing Tools is available + /// + public bool CheckForUpdates; + + /// + /// Check if legacy Asset Store Tools are in the Project + /// + public bool LegacyVersionCheck; + + /// + /// Enables a DisplayDialog when hidden folders are found to be missing meta files + /// + public bool DisplayHiddenMetaDialog; + + /// + /// Check if the package has been uploaded from a correct Unity version at least once + /// + public bool UploadVersionCheck; + + /// + /// Enables Junction symlink support + /// + public bool EnableSymlinkSupport; + + /// + /// Enables legacy exporting for Folder Upload workflow + /// + public bool UseLegacyExporting; + } + + internal class ASToolsPreferencesProvider : SettingsProvider + { + private const string SettingsPath = "Project/Asset Store Tools"; + + private class Styles + { + public static readonly GUIContent CheckForUpdatesLabel = EditorGUIUtility.TrTextContent("Check for Updates", "Periodically check if an update for the Asset Store Publishing Tools is available."); + public static readonly GUIContent LegacyVersionCheckLabel = EditorGUIUtility.TrTextContent("Legacy ASTools Check", "Enable Legacy Asset Store Tools version checking."); + public static readonly GUIContent UploadVersionCheckLabel = EditorGUIUtility.TrTextContent("Upload Version Check", "Check if the package has been uploader from a correct Unity version at least once."); + public static readonly GUIContent DisplayHiddenMetaDialogLabel = EditorGUIUtility.TrTextContent("Display Hidden Folder Meta Dialog", "Show a DisplayDialog when hidden folders are found to be missing meta files.\nNote: this only affects hidden folders ending with a '~' character"); + public static readonly GUIContent EnableSymlinkSupportLabel = EditorGUIUtility.TrTextContent("Enable Symlink Support", "Enable Junction Symlink support. Note: folder selection validation will take longer."); + public static readonly GUIContent UseLegacyExportingLabel = EditorGUIUtility.TrTextContent("Use Legacy Exporting", "Enabling this option uses native Unity methods when exporting packages for the Folder Upload workflow.\nNote: individual package dependency selection when choosing to 'Include Package Manifest' is unavailable when this option is enabled."); + public static readonly GUIContent UseCustomPreviewsLabel = EditorGUIUtility.TrTextContent("Enable High Quality Previews (experimental)", "Override native asset preview retrieval with higher-quality preview generation"); + } + + public static void OpenSettings() + { + SettingsService.OpenProjectSettings(SettingsPath); + } + + private ASToolsPreferencesProvider(string path, SettingsScope scopes, IEnumerable keywords = null) + : base(path, scopes, keywords) { } + + public override void OnGUI(string searchContext) + { + var preferences = ASToolsPreferences.Instance; + + EditorGUI.BeginChangeCheck(); + using (CreateSettingsWindowGUIScope()) + { + preferences.CheckForUpdates = EditorGUILayout.Toggle(Styles.CheckForUpdatesLabel, preferences.CheckForUpdates); + preferences.LegacyVersionCheck = EditorGUILayout.Toggle(Styles.LegacyVersionCheckLabel, preferences.LegacyVersionCheck); + preferences.UploadVersionCheck = EditorGUILayout.Toggle(Styles.UploadVersionCheckLabel, preferences.UploadVersionCheck); + preferences.DisplayHiddenMetaDialog = EditorGUILayout.Toggle(Styles.DisplayHiddenMetaDialogLabel, preferences.DisplayHiddenMetaDialog); + preferences.EnableSymlinkSupport = EditorGUILayout.Toggle(Styles.EnableSymlinkSupportLabel, preferences.EnableSymlinkSupport); + preferences.UseLegacyExporting = EditorGUILayout.Toggle(Styles.UseLegacyExportingLabel, preferences.UseLegacyExporting); + } + + if (EditorGUI.EndChangeCheck()) + { + ASToolsPreferences.Instance.Save(true); + } + } + + [SettingsProvider] + public static SettingsProvider CreateAssetStoreToolsSettingProvider() + { + var provider = new ASToolsPreferencesProvider(SettingsPath, SettingsScope.Project, GetSearchKeywordsFromGUIContentProperties()); + return provider; + } + + private IDisposable CreateSettingsWindowGUIScope() + { + var unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow)); + var type = unityEditorAssembly.GetType("UnityEditor.SettingsWindow+GUIScope"); + return Activator.CreateInstance(type) as IDisposable; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta new file mode 100644 index 00000000..de831827 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b75179c8d22a35b42a543d6fa7857ce0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsPreferences.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs new file mode 100644 index 00000000..698b9748 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs @@ -0,0 +1,250 @@ +using AssetStoreTools.Api; +using System; +using System.Linq; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Utility +{ + [InitializeOnLoad] + internal class ASToolsUpdater : AssetStoreToolsWindow + { + protected override string WindowTitle => "Asset Store Tools Update Check"; + + private static IAssetStoreApi _api; + + private VisualElement _loadingContainer; + private VisualElement _versionInfoContainer; + + private Image _loadingImage; + private double _lastTimeSinceStartup; + private double _timeSinceLoadingImageChange; + private int _loadingImageIndex; + + private static bool _updateCheckPerformed + { + get + { + return SessionState.GetBool("AST_UpdateChecked", false); + } + set + { + SessionState.SetBool("AST_UpdateChecked", value); + } + } + + static ASToolsUpdater() + { + _api = new AssetStoreApi(new AssetStoreClient()); + // Retrieving cached SessionState/PlayerPrefs values is not allowed from an instance field initializer + EditorApplication.update += CheckForUpdatesAfterEditorUpdate; + } + + private static async void CheckForUpdatesAfterEditorUpdate() + { + EditorApplication.update -= CheckForUpdatesAfterEditorUpdate; + + if (!ShouldCheckForUpdates()) + return; + + await CheckForUpdates((success, currentVersion, latestVersion) => + { + if (success && currentVersion < latestVersion) + { + AssetStoreTools.OpenUpdateChecker(); + } + }); + } + + private static bool ShouldCheckForUpdates() + { + if (!ASToolsPreferences.Instance.CheckForUpdates) + return false; + + return _updateCheckPerformed == false; + } + + private static async Task CheckForUpdates(Action OnUpdatesChecked) + { + _updateCheckPerformed = true; + var latestVersionResult = await _api.GetLatestAssetStoreToolsVersion(); + if (!latestVersionResult.Success) + { + OnUpdatesChecked?.Invoke(false, null, null); + return; + } + + Version currentVersion = null; + Version latestVersion = null; + + try + { + var latestVersionStr = latestVersionResult.Version; + var currentVersionStr = PackageUtility.GetAllPackages().FirstOrDefault(x => x.name == "com.unity.asset-store-tools").version; + + currentVersion = new Version(currentVersionStr); + latestVersion = new Version(latestVersionStr); + } + catch + { + OnUpdatesChecked?.Invoke(false, null, null); + } + + OnUpdatesChecked?.Invoke(true, currentVersion, latestVersion); + } + + protected override void Init() + { + rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowStyle); + rootVisualElement.styleSheets.Add(StyleSelector.UpdaterWindow.UpdaterWindowTheme); + + SetupLoadingSpinner(); + _ = CheckForUpdates(OnVersionsRetrieved); + } + + private void OnVersionsRetrieved(bool success, Version currentVersion, Version latestVersion) + { + if (_loadingContainer != null) + _loadingContainer.style.display = DisplayStyle.None; + + if (success) + { + SetupVersionInfo(currentVersion, latestVersion); + } + else + { + SetupFailInfo(); + } + } + + private void SetupLoadingSpinner() + { + _loadingContainer = new VisualElement(); + _loadingContainer.AddToClassList("updater-loading-container"); + _loadingImage = new Image(); + EditorApplication.update += LoadingSpinLoop; + + _loadingContainer.Add(_loadingImage); + rootVisualElement.Add(_loadingContainer); + } + + private void SetupVersionInfo(Version currentVersion, Version latestVersion) + { + _versionInfoContainer = new VisualElement(); + _versionInfoContainer.AddToClassList("updater-info-container"); + + AddDescriptionLabels(currentVersion, latestVersion); + AddUpdateButtons(currentVersion, latestVersion); + AddCheckForUpdatesToggle(); + + rootVisualElement.Add(_versionInfoContainer); + } + + private void AddDescriptionLabels(Version currentVersion, Version latestVersion) + { + var descriptionText = currentVersion < latestVersion ? + "An update to the Asset Store Publishing Tools is available. Updating to the latest version is highly recommended." : + "Asset Store Publishing Tools are up to date!"; + + var labelContainer = new VisualElement(); + labelContainer.AddToClassList("updater-info-container-labels"); + var descriptionLabel = new Label(descriptionText); + descriptionLabel.AddToClassList("updater-info-container-labels-description"); + + var currentVersionRow = new VisualElement(); + currentVersionRow.AddToClassList("updater-info-container-labels-row"); + var latestVersionRow = new VisualElement(); + latestVersionRow.AddToClassList("updater-info-container-labels-row"); + + var currentVersionLabel = new Label("Current version:"); + currentVersionLabel.AddToClassList("updater-info-container-labels-row-identifier"); + var latestVersionLabel = new Label("Latest version:"); + latestVersionLabel.AddToClassList("updater-info-container-labels-row-identifier"); + + var currentVersionLabelValue = new Label(currentVersion.ToString()); + var latestVersionLabelValue = new Label(latestVersion.ToString()); + + currentVersionRow.Add(currentVersionLabel); + currentVersionRow.Add(currentVersionLabelValue); + latestVersionRow.Add(latestVersionLabel); + latestVersionRow.Add(latestVersionLabelValue); + + labelContainer.Add(descriptionLabel); + labelContainer.Add(currentVersionRow); + labelContainer.Add(latestVersionRow); + + _versionInfoContainer.Add(labelContainer); + } + + private void AddUpdateButtons(Version currentVersion, Version latestVersion) + { + if (currentVersion >= latestVersion) + return; + + var buttonContainer = new VisualElement(); + buttonContainer.AddToClassList("updater-info-container-buttons"); + var latestVersionButton = new Button(() => Application.OpenURL(Constants.Updater.AssetStoreToolsUrl)) { text = "Get the latest version" }; + var skipVersionButton = new Button(Close) { text = "Skip for now" }; + + buttonContainer.Add(latestVersionButton); + buttonContainer.Add(skipVersionButton); + + _versionInfoContainer.Add(buttonContainer); + } + + private void AddCheckForUpdatesToggle() + { + var toggleContainer = new VisualElement(); + toggleContainer.AddToClassList("updater-info-container-toggle"); + var checkForUpdatesToggle = new Toggle() { text = "Check for Updates", value = ASToolsPreferences.Instance.CheckForUpdates }; + checkForUpdatesToggle.RegisterValueChangedCallback(OnCheckForUpdatesToggleChanged); + + toggleContainer.Add(checkForUpdatesToggle); + _versionInfoContainer.Add(toggleContainer); + } + + private void OnCheckForUpdatesToggleChanged(ChangeEvent evt) + { + ASToolsPreferences.Instance.CheckForUpdates = evt.newValue; + ASToolsPreferences.Instance.Save(); + } + + private void SetupFailInfo() + { + var failContainer = new VisualElement(); + failContainer.AddToClassList("updater-fail-container"); + + var failImage = new Image(); + var failDescription = new Label("Asset Store Publishing Tools could not retrieve information about the latest version."); + + failContainer.Add(failImage); + failContainer.Add(failDescription); + + rootVisualElement.Add(failContainer); + } + + private void LoadingSpinLoop() + { + var currentTimeSinceStartup = EditorApplication.timeSinceStartup; + var deltaTime = EditorApplication.timeSinceStartup - _lastTimeSinceStartup; + _lastTimeSinceStartup = currentTimeSinceStartup; + + _timeSinceLoadingImageChange += deltaTime; + if (_timeSinceLoadingImageChange < 0.075) + return; + + _timeSinceLoadingImageChange = 0; + + _loadingImage.image = EditorGUIUtility.IconContent($"WaitSpin{_loadingImageIndex++:00}").image; + if (_loadingImageIndex > 11) + _loadingImageIndex = 0; + } + + private void OnDestroy() + { + EditorApplication.update -= LoadingSpinLoop; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs.meta new file mode 100644 index 00000000..38afc154 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2ac370b9d2279ed4c9faec7134ba2759 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ASToolsUpdater.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs new file mode 100644 index 00000000..a596352d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs @@ -0,0 +1,266 @@ +ο»Ώusing System.IO; +using CacheConstants = AssetStoreTools.Constants.Cache; + +namespace AssetStoreTools.Utility +{ + internal static class CacheUtil + { + public static bool GetFileFromTempCache(string fileName, out string filePath) + { + return GetCacheFile(CacheConstants.TempCachePath, fileName, out filePath); + } + + public static bool GetFileFromPersistentCache(string fileName, out string filePath) + { + return GetCacheFile(CacheConstants.PersistentCachePath, fileName, out filePath); + } + + public static bool GetFileFromProjectPersistentCache(string projectPath, string fileName, out string filePath) + { + return GetCacheFile(Path.Combine(projectPath, CacheConstants.PersistentCachePath), fileName, out filePath); + } + + private static bool GetCacheFile(string rootPath, string fileName, out string filePath) + { + filePath = Path.Combine(rootPath, fileName); + return File.Exists(filePath); + } + + public static void CreateFileInTempCache(string fileName, object content, bool overwrite) + { + CreateCacheFile(CacheConstants.TempCachePath, fileName, content, overwrite); + } + + public static void CreateFileInPersistentCache(string fileName, object content, bool overwrite) + { + CreateCacheFile(CacheConstants.PersistentCachePath, fileName, content, overwrite); + } + + private static void CreateCacheFile(string rootPath, string fileName, object content, bool overwrite) + { + if (!Directory.Exists(rootPath)) + Directory.CreateDirectory(rootPath); + + var fullPath = Path.Combine(rootPath, fileName); + + bool willUpdate = false; + if (File.Exists(fullPath)) + { + if (overwrite) + { + File.Delete(fullPath); + willUpdate = true; + } + else + return; + } + + switch (content) + { + case byte[] bytes: + File.WriteAllBytes(fullPath, bytes); + break; + default: + File.WriteAllText(fullPath, content.ToString()); + break; + } + + var keyword = willUpdate ? "Updating" : "Creating"; + ASDebug.Log($"{keyword} cache file: '{fullPath}'"); + } + + public static void DeleteFileFromTempCache(string fileName) + { + DeleteFileFromCache(CacheConstants.TempCachePath, fileName); + } + + public static void DeleteFileFromPersistentCache(string fileName) + { + DeleteFileFromCache(CacheConstants.PersistentCachePath, fileName); + } + + private static void DeleteFileFromCache(string rootPath, string fileName) + { + var path = Path.Combine(rootPath, fileName); + if (File.Exists(path)) + File.Delete(path); + } + + //private static void CreateFileInPersistentCache(string fileName, object content, bool overwrite) + //{ + // CreateCacheFile(CacheConstants.PersistentCachePath, fileName, content, overwrite); + //} + + //private static void CreateCacheFile(string rootPath, string fileName, object content, bool overwrite) + //{ + // if (!Directory.Exists(rootPath)) + // Directory.CreateDirectory(rootPath); + + // var fullPath = Path.Combine(rootPath, fileName); + + // if (File.Exists(fullPath)) + // { + // if (overwrite) + // File.Delete(fullPath); + // else + // return; + // } + + // switch (content) + // { + // case byte[] bytes: + // File.WriteAllBytes(fullPath, bytes); + // break; + // default: + // File.WriteAllText(fullPath, content.ToString()); + // break; + // } + // ASDebug.Log($"Creating cached file: '{fullPath}'"); + //} + + //public static void ClearTempCache() + //{ + // if (!File.Exists(Path.Combine(CacheConstants.TempCachePath, CacheConstants.PackageDataFile))) + // return; + + + // // Cache consists of package data and package texture thumbnails. We don't clear + // // texture thumbnails here since they are less likely to change. They are still + // // deleted and redownloaded every project restart (because of being stored in the 'Temp' folder) + // var fullPath = Path.Combine(CacheConstants.TempCachePath, CacheConstants.PackageDataFile); + // ASDebug.Log($"Deleting cached file '{fullPath}'"); + // File.Delete(fullPath); + //} + + //public static void CachePackageMetadata(List data) + //{ + // var serializerSettings = new JsonSerializerSettings() + // { + // ContractResolver = Package.CachedPackageResolver.Instance, + // Formatting = Formatting.Indented + // }; + + // CreateFileInTempCache(CacheConstants.PackageDataFile, JsonConvert.SerializeObject(data, serializerSettings), true); + //} + + //public static void UpdatePackageMetadata(Package data) + //{ + // if (!GetCachedPackageMetadata(out var cachedData)) + // return; + + // var index = cachedData.FindIndex(x => x.PackageId.Equals(data.PackageId)); + // if (index == -1) + // { + // cachedData.Add(data); + // } + // else + // { + // cachedData.RemoveAt(index); + // cachedData.Insert(index, data); + // } + + // CachePackageMetadata(cachedData); + //} + + //public static bool GetCachedPackageMetadata(out List data) + //{ + // data = new List(); + // var path = Path.Combine(CacheConstants.TempCachePath, CacheConstants.PackageDataFile); + // if (!File.Exists(path)) + // return false; + + // try + // { + // var serializerSettings = new JsonSerializerSettings() + // { + // ContractResolver = Package.CachedPackageResolver.Instance + // }; + + // data = JsonConvert.DeserializeObject>(File.ReadAllText(path, Encoding.UTF8), serializerSettings); + // return true; + // } + // catch + // { + // return false; + // } + //} + + //public static void CacheTexture(string packageId, Texture2D texture) + //{ + // CreateFileInTempCache($"{packageId}.png", texture.EncodeToPNG(), true); + //} + + //public static bool GetCachedTexture(string packageId, out Texture2D texture) + //{ + // texture = new Texture2D(1, 1); + // var path = Path.Combine(CacheConstants.TempCachePath, $"{packageId}.png"); + // if (!File.Exists(path)) + // return false; + + // texture.LoadImage(File.ReadAllBytes(path)); + // return true; + //} + + //public static void CacheWorkflowStateData(string packageId, WorkflowStateData data) + //{ + // var fileName = $"{packageId}-workflowStateData.asset"; + // CreateFileInPersistentCache(fileName, JsonConvert.SerializeObject(data, Formatting.Indented), true); + //} + + //public static bool GetCachedWorkflowStateData(string packageId, out WorkflowStateData data) + //{ + // data = null; + // var path = Path.Combine(CacheConstants.PersistentCachePath, $"{packageId}-workflowStateData.asset"); + // if (!File.Exists(path)) + // return false; + + // data = JsonConvert.DeserializeObject(File.ReadAllText(path, Encoding.UTF8)); + // return true; + //} + + //public static void CacheValidationStateData(ValidationStateData data) + //{ + // var serializerSettings = new JsonSerializerSettings() + // { + // ContractResolver = ValidationStateDataContractResolver.Instance, + // Formatting = Formatting.Indented, + // TypeNameHandling = TypeNameHandling.Auto, + // Converters = new List() { new StringEnumConverter() } + // }; + + // CreateFileInPersistentCache(CacheConstants.ValidationResultFile, JsonConvert.SerializeObject(data, serializerSettings), true); + //} + + //public static bool GetCachedValidationStateData(out ValidationStateData data) + //{ + // return GetCachedValidationStateData(Constants.RootProjectPath, out data); + //} + + //public static bool GetCachedValidationStateData(string projectPath, out ValidationStateData data) + //{ + // data = null; + // var path = Path.Combine(projectPath, CacheConstants.PersistentCachePath, CacheConstants.ValidationResultFile); + // if (!File.Exists(path)) + // return false; + + // try + // { + // var serializerSettings = new JsonSerializerSettings() + // { + // ContractResolver = ValidationStateDataContractResolver.Instance, + // Formatting = Formatting.Indented, + // TypeNameHandling = TypeNameHandling.Auto, + // Converters = new List() { new StringEnumConverter() } + // }; + + // data = JsonConvert.DeserializeObject(File.ReadAllText(path, Encoding.UTF8), serializerSettings); + // return true; + // } + // catch (System.Exception e) + // { + // UnityEngine.Debug.LogException(e); + // return false; + // } + //} + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs.meta new file mode 100644 index 00000000..ab8d31b3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2e5fee0cad7655f458d9b600f4ae6d02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/CacheUtil.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs new file mode 100644 index 00000000..5e545f81 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs @@ -0,0 +1,207 @@ +ο»Ώusing System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; + +namespace AssetStoreTools.Utility +{ + internal static class FileUtility + { + private class RenameInfo + { + public string OriginalName; + public string CurrentName; + } + + public static string AbsolutePathToRelativePath(string path, bool allowSymlinks) + { + if (!File.Exists(path) && !Directory.Exists(path)) + return path; + + string convertedPath = path.Replace("\\", "/"); + + var allPackages = PackageUtility.GetAllPackages(); + foreach (var package in allPackages) + { + if (Path.GetFullPath(package.resolvedPath) != Path.GetFullPath(convertedPath) + && !Path.GetFullPath(convertedPath).StartsWith(Path.GetFullPath(package.resolvedPath) + Path.DirectorySeparatorChar)) + continue; + + convertedPath = Path.GetFullPath(convertedPath) + .Replace(Path.GetFullPath(package.resolvedPath), package.assetPath) + .Replace("\\", "/"); + + return convertedPath; + } + + if (convertedPath.StartsWith(Constants.RootProjectPath)) + { + convertedPath = convertedPath.Substring(Constants.RootProjectPath.Length); + } + else + { + if (allowSymlinks && SymlinkUtil.FindSymlinkFolderRelative(convertedPath, out var symlinkPath)) + convertedPath = symlinkPath; + } + + return convertedPath; + } + + public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive) + { + // Get information about the source directory + var dir = new DirectoryInfo(sourceDir); + + // Check if the source directory exists + if (!dir.Exists) + throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); + + // Cache directories before we start copying + DirectoryInfo[] dirs = dir.GetDirectories(); + + // Create the destination directory + Directory.CreateDirectory(destinationDir); + + // Get the files in the source directory and copy to the destination directory + foreach (FileInfo file in dir.GetFiles()) + { + string targetFilePath = Path.Combine(destinationDir, file.Name); + file.CopyTo(targetFilePath); + } + + // If recursive and copying subdirectories, recursively call this method + if (recursive) + { + foreach (DirectoryInfo subDir in dirs) + { + string newDestinationDir = Path.Combine(destinationDir, subDir.Name); + CopyDirectory(subDir.FullName, newDestinationDir, true); + } + } + } + + public static bool ShouldHaveMeta(string assetPath) + { + if (string.IsNullOrEmpty(assetPath)) + return false; + + // Meta files never have other metas + if (assetPath.EndsWith(".meta", System.StringComparison.OrdinalIgnoreCase)) + return false; + + // File System entries ending with '~' are hidden in the context of ADB + if (assetPath.EndsWith("~")) + return false; + + // File System entries whose names start with '.' are hidden in the context of ADB + var assetName = assetPath.Replace("\\", "/").Split('/').Last(); + if (assetName.StartsWith(".")) + return false; + + return true; + } + + public static bool IsMissingMetaFiles(IEnumerable sourcePaths) + { + foreach (var sourcePath in sourcePaths) + { + if (!Directory.Exists(sourcePath)) + continue; + + var allDirectories = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories); + foreach (var dir in allDirectories) + { + var dirInfo = new DirectoryInfo(dir); + if (!dirInfo.Name.EndsWith("~")) + continue; + + var nestedContent = dirInfo.GetFileSystemInfos("*", SearchOption.AllDirectories); + foreach (var nested in nestedContent) + { + if (!ShouldHaveMeta(nested.FullName)) + continue; + + if (!File.Exists(nested.FullName + ".meta")) + return true; + } + } + } + + return false; + } + + public static void GenerateMetaFiles(IEnumerable sourcePaths) + { + var renameInfos = new List(); + + foreach (var sourcePath in sourcePaths) + { + if (!Directory.Exists(sourcePath)) + continue; + + var hiddenDirectoriesInPath = Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories).Where(x => x.EndsWith("~")); + foreach (var hiddenDir in hiddenDirectoriesInPath) + { + var hiddenDirRelative = AbsolutePathToRelativePath(hiddenDir, ASToolsPreferences.Instance.EnableSymlinkSupport); + if (!hiddenDirRelative.StartsWith("Assets/") && !hiddenDirRelative.StartsWith("Packages/")) + { + ASDebug.LogWarning($"Path {sourcePath} is not part of the Asset Database and will be skipped"); + continue; + } + + renameInfos.Add(new RenameInfo() { CurrentName = hiddenDirRelative, OriginalName = hiddenDirRelative }); + } + } + + if (renameInfos.Count == 0) + return; + + try + { + EditorApplication.LockReloadAssemblies(); + + // Order paths from longest to shortest to avoid having to rename them multiple times + renameInfos = renameInfos.OrderByDescending(x => x.OriginalName.Length).ToList(); + + try + { + AssetDatabase.StartAssetEditing(); + foreach (var renameInfo in renameInfos) + { + renameInfo.CurrentName = renameInfo.OriginalName.TrimEnd('~'); + Directory.Move(renameInfo.OriginalName, renameInfo.CurrentName); + } + } + finally + { + AssetDatabase.StopAssetEditing(); + AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); + AssetDatabase.ReleaseCachedFileHandles(); + } + + // Restore the original path names in reverse order + renameInfos = renameInfos.OrderBy(x => x.OriginalName.Length).ToList(); + + try + { + AssetDatabase.StartAssetEditing(); + foreach (var renameInfo in renameInfos) + { + Directory.Move(renameInfo.CurrentName, renameInfo.OriginalName); + if (File.Exists($"{renameInfo.CurrentName}.meta")) + File.Delete($"{renameInfo.CurrentName}.meta"); + } + } + finally + { + AssetDatabase.StopAssetEditing(); + AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); + } + } + finally + { + EditorApplication.UnlockReloadAssemblies(); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta new file mode 100644 index 00000000..fe6eb7ce --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 80819cf6868374d478a8a38ebaba8e27 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/FileUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs new file mode 100644 index 00000000..c9df7c21 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs @@ -0,0 +1,86 @@ +ο»Ώusing System; +using System.IO; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Utility +{ + [InitializeOnLoad] + internal class LegacyToolsRemover + { + private const string MessagePart1 = "A legacy version of Asset Store Tools " + + "was detected at the following path:\n"; + private const string MessagePart2 = "\n\nHaving both the legacy and the latest version installed at the same time is not supported " + + "and might prevent the latest version from functioning properly.\n\nWould you like the legacy version to be removed automatically?"; + + static LegacyToolsRemover() + { + try + { + if (Application.isBatchMode) + return; + + CheckAndRemoveLegacyTools(); + } + catch { } + } + + private static void CheckAndRemoveLegacyTools() + { + if (!ASToolsPreferences.Instance.LegacyVersionCheck || !ProjectContainsLegacyTools(out string path)) + return; + + var relativePath = path.Substring(Application.dataPath.Length - "Assets".Length).Replace("\\", "/"); + var result = EditorUtility.DisplayDialog("Asset Store Tools", MessagePart1 + relativePath + MessagePart2, "Yes", "No"); + + // If "No" - do nothing + if (!result) + return; + + // If "Yes" - remove legacy tools + File.Delete(path); + File.Delete(path + ".meta"); + RemoveEmptyFolders(Path.GetDirectoryName(path)?.Replace("\\", "/")); + AssetDatabase.Refresh(); + + // We could also optionally prevent future execution here + // but the ProjectContainsLegacyTools() function runs in less + // than a milisecond on an empty project + } + + private static bool ProjectContainsLegacyTools(out string path) + { + path = null; + + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + if (assembly.ManifestModule.Name == "AssetStoreTools.dll") + { + path = assembly.Location; + break; + } + } + + if (string.IsNullOrEmpty(path)) + return false; + return true; + } + + private static void RemoveEmptyFolders(string directory) + { + if (directory.EndsWith(Application.dataPath)) + return; + + if (Directory.GetFiles(directory).Length == 0 && Directory.GetDirectories(directory).Length == 0) + { + var parentPath = Path.GetDirectoryName(directory).Replace("\\", "/"); + + Directory.Delete(directory); + File.Delete(directory + ".meta"); + + RemoveEmptyFolders(parentPath); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta new file mode 100644 index 00000000..aa03ddfb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 46ead42026b1f0b4e94153e1a7e10d12 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/LegacyToolsRemover.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs new file mode 100644 index 00000000..a384f7ae --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs @@ -0,0 +1,170 @@ +ο»Ώ#if !UNITY_2021_1_OR_NEWER +using System; +using System.Reflection; +#endif +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.PackageManager; +using UnityEngine; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; + +namespace AssetStoreTools.Utility +{ + internal static class PackageUtility + { + public class PackageInfoSampleMetadata + { + public string DisplayName; + public string Description; + public string Path; + } + + public class PackageInfoUnityVersionMetadata + { + /// + /// Major bit of the Unity version, e.g. 2021.3 + /// + public string Version; + /// + /// Minor bit of the Unity version, e.g. 0f1 + /// + public string Release; + + public override string ToString() + { + if (string.IsNullOrEmpty(Version)) + return Release; + + if (string.IsNullOrEmpty(Release)) + return Release; + + return $"{Version}.{Release}"; + } + } + + /// + /// Returns a package identifier, consisting of package name and package version + /// + /// + /// + public static string GetPackageIdentifier(this PackageInfo package) + { + return $"{package.name}-{package.version}"; + } + + public static PackageInfo[] GetAllPackages() + { +#if !UNITY_2021_1_OR_NEWER + var method = typeof(PackageInfo).GetMethod("GetAll", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[0], null); + var packages = method?.Invoke(null, null) as PackageInfo[]; +#else + var packages = PackageInfo.GetAllRegisteredPackages(); +#endif + return packages; + } + + public static PackageInfo[] GetAllLocalPackages() + { + var packages = GetAllPackages(); + var localPackages = packages.Where(x => x.source == PackageSource.Embedded || x.source == PackageSource.Local) + .Where(x => x.isDirectDependency).ToArray(); + return localPackages; + } + + public static PackageInfo[] GetAllRegistryPackages() + { + var packages = GetAllPackages(); + var registryPackages = packages.Where(x => x.source == PackageSource.Registry || x.source == PackageSource.BuiltIn) + .OrderBy(x => string.Compare(x.type, "module", System.StringComparison.OrdinalIgnoreCase) == 0) + .ThenBy(x => x.name).ToArray(); + + return registryPackages; + } + + public static bool GetPackageByManifestPath(string packageManifestPath, out PackageInfo package) + { + package = null; + + if (string.IsNullOrEmpty(packageManifestPath)) + return false; + + var fileInfo = new FileInfo(packageManifestPath); + if (!fileInfo.Exists) + return false; + + var allPackages = GetAllPackages(); + + package = allPackages.FirstOrDefault(x => Path.GetFullPath(x.resolvedPath).Equals(fileInfo.Directory.FullName)); + return package != null; + } + + public static bool GetPackageByPackageName(string packageName, out PackageInfo package) + { + package = null; + + if (string.IsNullOrEmpty(packageName)) + return false; + + return GetPackageByManifestPath($"Packages/{packageName}/package.json", out package); + } + + public static TextAsset GetManifestAsset(this PackageInfo packageInfo) + { + return AssetDatabase.LoadAssetAtPath($"{packageInfo.assetPath}/package.json"); + } + + public static List GetSamples(this PackageInfo packageInfo) + { + var samples = new List(); + + var packageManifest = packageInfo.GetManifestAsset(); + var json = JObject.Parse(packageManifest.text); + + if (!json.ContainsKey("samples") || json["samples"].Type != JTokenType.Array) + return samples; + + var sampleList = json["samples"].ToList(); + foreach (JObject sample in sampleList) + { + var displayName = string.Empty; + var description = string.Empty; + var path = string.Empty; + + if (sample.ContainsKey("displayName")) + displayName = sample["displayName"].ToString(); + if (sample.ContainsKey("description")) + description = sample["description"].ToString(); + if (sample.ContainsKey("path")) + path = sample["path"].ToString(); + + if (!string.IsNullOrEmpty(displayName) || !string.IsNullOrEmpty(description) || !string.IsNullOrEmpty(path)) + samples.Add(new PackageInfoSampleMetadata() { DisplayName = displayName, Description = description, Path = path }); + } + + return samples; + } + + public static PackageInfoUnityVersionMetadata GetUnityVersion(this PackageInfo packageInfo) + { + var packageManifest = packageInfo.GetManifestAsset(); + var json = JObject.Parse(packageManifest.text); + + var unityVersion = string.Empty; + var unityRelease = string.Empty; + + if (json.ContainsKey("unity")) + unityVersion = json["unity"].ToString(); + if (json.ContainsKey("unityRelease")) + unityRelease = json["unityRelease"].ToString(); + + return new PackageInfoUnityVersionMetadata() + { + Version = unityVersion, + Release = unityRelease + }; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta new file mode 100644 index 00000000..af0b5112 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 605ea62f8b11d674a95a53f895df4c67 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/PackageUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs new file mode 100644 index 00000000..97510817 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Utility +{ + internal abstract class ServiceProvider + { + private Dictionary _services = new Dictionary(); + private Dictionary> _queuedServices = new Dictionary>(); + + protected class MissingServiceDependencyException : Exception + { + public Type ServiceType { get; private set; } + public Type MissingDependencyType { get; private set; } + + public MissingServiceDependencyException(Type serviceType, Type missingDependencyType) + { + ServiceType = serviceType; + MissingDependencyType = missingDependencyType; + } + } + + protected ServiceProvider() + { + RegisterServices(); + CreateRegisteredServices(); + } + + protected abstract void RegisterServices(); + + protected void Register() where TService : Service where TInstance : TService + { + Register(() => CreateServiceInstance(typeof(TInstance))); + } + + protected void Register(Func initializer) where TService : Service + { + _queuedServices.Add(typeof(TService), initializer); + } + + private void CreateRegisteredServices() + { + if (_queuedServices.Count == 0) + return; + + var createdAnyService = false; + var missingServices = new List(); + + foreach (var service in _queuedServices) + { + try + { + var instance = service.Value.Invoke(); + _services.Add(service.Key, instance); + createdAnyService = true; + } + catch (MissingServiceDependencyException e) + { + missingServices.Add(e); + } + } + + foreach (var createdService in _services) + { + _queuedServices.Remove(createdService.Key); + } + + if (!createdAnyService) + { + var message = string.Join(", ", missingServices.Select(x => $"{x.ServiceType} depends on {x.MissingDependencyType}")); + throw new Exception("Could not create the following services due to missing dependencies: " + message); + } + + // Recursively register remaining queued services that may have failed + // due to missing depenedencies that are now registered + CreateRegisteredServices(); + } + + private Service CreateServiceInstance(Type concreteType) + { + if (concreteType.IsAbstract) + throw new Exception($"Cannot create an instance of an abstract class {concreteType}"); + + var constructor = concreteType.GetConstructors().First(); + var expectedParameters = constructor.GetParameters(); + var parametersToUse = new List(); + + foreach (var parameter in expectedParameters) + { + if (!_services.ContainsKey(parameter.ParameterType)) + throw new MissingServiceDependencyException(concreteType, parameter.ParameterType); + + parametersToUse.Add(_services[parameter.ParameterType]); + } + + return (Service)constructor.Invoke(parametersToUse.ToArray()); + } + + public T GetService() where T : Service + { + return (T)GetService(typeof(T)); + } + + public object GetService(Type type) + { + if (!_services.ContainsKey(type)) + throw new Exception($"Service of type {type} is not registered"); + + return _services[type]; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs.meta new file mode 100644 index 00000000..a35f4c80 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2fcadafa6431d1647a82d35e6e4a13c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/ServiceProvider.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs new file mode 100644 index 00000000..1076bca3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs @@ -0,0 +1,55 @@ +ο»Ώusing System; +using UnityEditor; +using UnityEngine.UIElements; +using WindowStyles = AssetStoreTools.Constants.WindowStyles; + +namespace AssetStoreTools.Utility +{ + internal static class StyleSelector + { + private static StyleSheet GetStylesheet(string rootPath, string filePath) + { + var path = $"{rootPath}/{filePath}.uss"; + var sheet = AssetDatabase.LoadAssetAtPath(path); + if (sheet == null) + throw new Exception($"Stylesheet '{path}' was not found"); + return sheet; + } + + private static StyleSheet GetStylesheetTheme(string rootPath, string filePath) + { + var suffix = !EditorGUIUtility.isProSkin ? "Light" : "Dark"; + return GetStylesheet(rootPath, filePath + suffix); + } + + public static class UploaderWindow + { + public static StyleSheet UploaderWindowStyle => GetStylesheet(WindowStyles.UploaderStylesPath, "Style"); + public static StyleSheet UploaderWindowTheme => GetStylesheetTheme(WindowStyles.UploaderStylesPath, "Theme"); + + public static StyleSheet LoginViewStyle => GetStylesheet(WindowStyles.UploaderStylesPath, "LoginView/Style"); + public static StyleSheet LoginViewTheme => GetStylesheetTheme(WindowStyles.UploaderStylesPath, "LoginView/Theme"); + + public static StyleSheet PackageListViewStyle => GetStylesheet(WindowStyles.UploaderStylesPath, "PackageListView/Style"); + public static StyleSheet PackageListViewTheme => GetStylesheetTheme(WindowStyles.UploaderStylesPath, "PackageListView/Theme"); + } + + public static class ValidatorWindow + { + public static StyleSheet ValidatorWindowStyle => GetStylesheet(WindowStyles.ValidatorStylesPath, "Style"); + public static StyleSheet ValidatorWindowTheme => GetStylesheetTheme(WindowStyles.ValidatorStylesPath, "Theme"); + } + + public static class PreviewGeneratorWindow + { + public static StyleSheet PreviewGeneratorWindowStyle => GetStylesheet(WindowStyles.PreviewGeneratorStylesPath, "Style"); + public static StyleSheet PreviewGeneratorWindowTheme => GetStylesheetTheme(WindowStyles.PreviewGeneratorStylesPath, "Theme"); + } + + public static class UpdaterWindow + { + public static StyleSheet UpdaterWindowStyle => GetStylesheet(WindowStyles.UpdaterStylesPath, "Style"); + public static StyleSheet UpdaterWindowTheme => GetStylesheetTheme(WindowStyles.UpdaterStylesPath, "Theme"); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta new file mode 100644 index 00000000..b7a9bb24 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8b066ce502a289a4ca311a86fbf83f45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/StyleSelector.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles.meta new file mode 100644 index 00000000..0175b81a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f730eb0b8c48c434d93cc60a0b8aff40 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater.meta new file mode 100644 index 00000000..315b99b2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5367435d9abe935438f4d7b588a55488 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss new file mode 100644 index 00000000..1ee89cd5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss @@ -0,0 +1,76 @@ +ο»Ώ.updater-loading-container { + flex-grow: 1; + align-items: center; + justify-content: center; +} + +.updater-loading-container > Image { + width: 16px; + height: 16px; +} + +.updater-info-container { + flex-grow: 1; + margin: 0 5px 5px 5px; +} + +.updater-info-container-labels { + flex-grow: 1; + margin-bottom: 10px; + margin-top: 5px; +} + +.updater-info-container-labels-description { + flex-grow: 0.5; + margin-bottom: 5px; + white-space: normal; + -unity-text-align: middle-left; +} + +.updater-info-container-labels-row { + flex-direction: row; +} + +.updater-info-container-labels-row-identifier { + -unity-font-style: bold; +} + +.updater-info-container-buttons { + flex-direction: row; + margin-bottom: 5px; +} + +.updater-info-container-buttons > Button { + flex-grow: 1; + flex-shrink: 1; + flex-basis: 100%; + height: 25px; +} + +.updater-info-container-toggle { + align-self: flex-end; +} + +.updater-info-container-toggle > Toggle > VisualElement > Label { + margin-left: 5px; +} + +.updater-fail-container { + flex-grow: 1; + flex-direction: row; + margin: 0 5px 5px 5px; + justify-content: center; + align-items: center; +} + +.updater-fail-container > Image { + flex-shrink: 0; + width: 36px; + height: 36px; + margin-right: 5px; +} + +.updater-fail-container > Label { + flex-shrink: 1; + white-space: normal; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss.meta new file mode 100644 index 00000000..a2dbb90f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 23112eed1f211274c94028490f81007c +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss new file mode 100644 index 00000000..3510f8ac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss @@ -0,0 +1,3 @@ +ο»Ώ.updater-fail-container > Image { + --unity-image: resource("console.erroricon@2x"); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss.meta new file mode 100644 index 00000000..82e770e1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0cbf43b8dabcd1242b32ed3ed2167a54 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss new file mode 100644 index 00000000..3510f8ac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss @@ -0,0 +1,3 @@ +ο»Ώ.updater-fail-container > Image { + --unity-image: resource("console.erroricon@2x"); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss.meta new file mode 100644 index 00000000..cdd5b1af --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d453bb92cd1f35943b1c5f652837ada9 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs new file mode 100644 index 00000000..93da1ee2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs @@ -0,0 +1,67 @@ +ο»Ώusing System.IO; + +namespace AssetStoreTools.Utility +{ + internal static class SymlinkUtil + { + private const FileAttributes FolderSymlinkAttributes = FileAttributes.Directory | FileAttributes.ReparsePoint; + + public static bool FindSymlinkFolderRelative(string folderPathAbsolute, out string relativePath) + { + // Get directory info for path outside of the project + var absoluteInfo = new DirectoryInfo(folderPathAbsolute); + + // Get all directories within the project + var allFolderPaths = Directory.GetDirectories("Assets", "*", SearchOption.AllDirectories); + foreach (var path in allFolderPaths) + { + var fullPath = path.Replace("\\", "/"); + + // Get directory info for one of the paths within the project + var relativeInfo = new DirectoryInfo(fullPath); + + // Check if project's directory is a symlink + if (!relativeInfo.Attributes.HasFlag(FolderSymlinkAttributes)) + continue; + + // Compare metadata of outside directory with a directories within the project + if (!CompareDirectories(absoluteInfo, relativeInfo)) + continue; + + // Found symlink within the project, assign it + relativePath = fullPath; + return true; + } + + relativePath = string.Empty; + return false; + } + + private static bool CompareDirectories(DirectoryInfo directory, DirectoryInfo directory2) + { + var contents = directory.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator(); + var contents2 = directory2.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator(); + + while (true) + { + var firstNext = contents.MoveNext(); + var secondNext = contents2.MoveNext(); + + if (firstNext != secondNext) + return false; + + if (!firstNext && !secondNext) + break; + + var equals = contents.Current?.Name == contents2.Current?.Name + && contents.Current?.LastWriteTime == contents2.Current?.LastWriteTime; + + if (!equals) + return false; + } + + return true; + } + + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta new file mode 100644 index 00000000..827d9ceb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs.meta @@ -0,0 +1,10 @@ +ο»ΏfileFormatVersion: 2 +guid: 92092535fd064bb1843017f98db213e1 +timeCreated: 1659013521 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Utility/SymlinkUtil.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator.meta b/Packages/com.unity.asset-store-tools/Editor/Validator.meta new file mode 100644 index 00000000..e27c1efd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 980c7bb65c02d464684c2220c57fcd75 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta new file mode 100644 index 00000000..7f4c321d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8490c57c02b441e4dab99565da835c99 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png new file mode 100644 index 0000000000000000000000000000000000000000..8d294bc199d18c75542a22f1a5872e3c9276b863 GIT binary patch literal 1057 zcmV++1m63JP)@~0drDELIAGL9O(c600d`2O+f$vv5yP|(KsZ6^2^#hdO&5KnE9eQDBXEOeMR{%G zspMeu0=BHg(nxvv-U~RfVtf9~NFI5FUUvkOEga=U@SZ znozvE32Pf?@=))96QVOnexKstdJHwFB|vJtXkN*qw7>^MBPqgO9T655z`ODJh13&a zApwFhKBI;Ra|;lh@fiz>FqZ(q8lSO%2*v^gZ+ym_A{Ys*$#KcCtbW4o)+#pXrBOz zF4&~P6AA@z_{-nm#pSlP$>Hl?)^iDs2v0)5afdgkY(bVoL7@qU83Ek)_GmCPQLW^r z{M5xFG5Ypn0mlkv&(XmV`Lmg;2I^uTJwY2 z6m+oPk^kQV2Lus>Lx+yqyF#kLIFn-%-xL8CgeNKl`0nq~$OBB;SOQzZ-2`Sax?59< zW7cbtYzp8;G+&hOyyF%C_ytJ*Zk6t9G$LSzUjP&@As{@2K%?BvlOzIW_yr*CFvsp4 z`~ql49bADXj&!x z+e{okt9(>1G*cv%=H%j!yFv+)?w#DeDy!I-17j!;G5STvQND>M-}m(Atp z3`GPV3n%k)`xe2%(%D*bf)BX^o&h^audeZm+N;Mirt^8K?iiIfxXS6rY8nd?=;D{l bA7Fw1SKskfA=so700000NkvXXu0mjfJ)q0> literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta new file mode 100644 index 00000000..38311469 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png.meta @@ -0,0 +1,135 @@ +fileFormatVersion: 2 +guid: 0cc0ccdb7de3e964ab553ce3c299d83c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 0 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/error_d.png new file mode 100644 index 0000000000000000000000000000000000000000..451f64037adef0edb0178cc7a335c513faa0f444 GIT binary patch literal 1024 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 literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta new file mode 100644 index 00000000..e883152d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png.meta @@ -0,0 +1,135 @@ +fileFormatVersion: 2 +guid: 832e106a677623145b3d8dbe015e31a0 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 0 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png new file mode 100644 index 0000000000000000000000000000000000000000..094a810f9ec5788ff713a0780fd3010c81151c37 GIT binary patch literal 1617 zcmV-X2Cn&uP)@~0drDELIAGL9O(c600d`2O+f$vv5yPJwrV6PtsY1GBCgamFnMqO^cj*jON|Q1bQs)l2 z^8g8#KfsJ!2GDKZ+eMLN-Rbu3_LLL;%m^LQo}_*E_U-$10%hZ`N%~ud=&r*P5(@Oc zm;;m?9w!x?5QZobfim#dc*2h%yzSA6W+sGEO{m%-g4azr#+?9s zIR|fcmyW)n#~jKbq(=kMRm+uT6c@l`CjKrR(uxD9>t{s;Q9}{-R(Bz4FX-qIJ?>$0 z+=CFG(syrT>wX8#H?NSBd>X)p%~Q{5eb-S9$Z%e5<6wUI4+$0e#6=s6KT(T#z`v{M}}- zoec<1 z8j&mjw)VhJn0DA-*qncxv^&Jx0KLygwC*S7*_8|hS<&@_I6ooY26)ji?#$#Fiax!W zSbH$K1pMV4QkxyzIfRT`3d2jls6JnPi93m23X8N9I=xqhmw?x0!zWR7I6nZfs~-Xf z_9xO(5VJ$OT3-XE#_)A_;Qx6z^pd~4LD?otyEUu@0~*k+qw14aQDbECOmNnQhyqwK ztOb1mc)~}u3DG!Do@Dpt0GueXL8#r{p%DP*@T$J{Io=HX*k8$-6yKqPjG!u6`}bYQrRcT>O|c zAgXSt%b8#Q^e}ZCd#?&R$Vzvn?vW?3j%q@w@9XrfP5Uo7cQBYpyAjxvGU1sw1Jio#cH*hderx3ml8Jwuns;$SGFn(M%cUQs{3LQ`P*%JDxUqg0iyRj02daVX@Mr65X_!mUXq4`t^wa;I2v@T1xz*}l;iFWGE!q0 z765C3b&=5;J0XRc`bhJ-M4 zLe9-_9gCee^#a+bd&y*<8Dlshc9?sJxQ3R`7i++F|t+p$AnL$JcVL+@#`G?SFgsVe%) zr%#@-zh9vF=IAz&QAd^GZW90eYun-3?ik^0&cpe)Bn38%Rl941t5V;MZKR69&IY_o z)jCS`jg^#K&Cy4cPXImGcQ@{<#Q#G__Yv5X(i13l-(c&qjm?iJn-sBa;Je5swJa!d zjee%9{y7?dwNQX!8Zd}XVRh>zYeYvIIgaQC8lH>bP5^@hOPl&WKGS|DQ4GF$`iQo+ zqh1=zCFKZU5ObI5IyWT2I8%~4GcYQckZX1N8C0#Jq6KQ#P5f~2H%jDRfoMCn-b@k~ P00000NkvXXu0mjfDn|lL literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta new file mode 100644 index 00000000..f2240b95 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png.meta @@ -0,0 +1,135 @@ +fileFormatVersion: 2 +guid: 3dc139a2b2a28a54a8f39e266fc0af9c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 0 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Icons/success_d.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/undefined.png new file mode 100644 index 0000000000000000000000000000000000000000..a587baa45ab11888902d103b690a2f579aeb55c6 GIT binary patch literal 1561 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 Hu0mjf^t1iH literal 0 HcmV?d00001 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta new file mode 100644 index 00000000..efc2077e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png.meta @@ -0,0 +1,135 @@ +fileFormatVersion: 2 +guid: 83d0e58aa5f608a4b8232fbacca5ca89 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 0 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning.png + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png b/Packages/com.unity.asset-store-tools/Editor/Validator/Icons/warning_d.png new file mode 100644 index 0000000000000000000000000000000000000000..553bb16d81ff583b4f190471c02e74418503bd29 GIT binary patch literal 1185 zcmV;S1YY}zP)@~0drDELIAGL9O(c600d`2O+f$vv5yP_5f**n>aBm==3+_%^ zy}N_MGSk!3UDd1d63Aw{hoN4*s;-*uRfvq!JuF=I@sd8S(NAiwDd0>ibTf^e2OH=i zA`~Lx%UiTt3P<$Rg^DS?L54>UpWzIV5RHK2U8IS|sm1s)G|mSaE3rsO5DE04qgvw) zXwF=MZA3y80?7O8n8dpaG|)MIgAO7f3IX(xS7?Ykt>*XmK%9W4-p>(B1>ywwct1xB z6^Ihx>-`)tR3J(~i1%|yt3Zr^Q19oER)H7+9Ny0%sR9uKxV)c3QUxstpw|0T?o#vf z3E8;ZO%k-p$aUK-6BTs94EA2Yc%KN^vrOq_z{+&jH|iBkxolBRHlX{S^OC?G0(IUm zGv2^lGh?=UC2|2P0d=uYGT*oL`=c=v8rAo+=K@v&YGZ#`ZCs9Qh(p^rw+h$@aLN2C zacGBYz^wu{0=U+FS`qHm&EZr53jxmSzH*vVs}fEXun^$teeFP!)^1_KrGj7rxU0Uz z@o#adAeexLv7b83aZZ#RDhMK=srQvj2s9voLj^$uaCUqJq)jG=s=%87&)83GgJ#zV z4H2pWZvuS1|LtS-I^Xa66-ps0@FIXa^B0i910gE#A|NF82ba}GCfdJL_EkY+0vO)( zrd4BE00F)#XiR`m<{$rUhd#gt9~CqrfF<^A{eTMV7JXFEhyV`n+d@F=@OHVW3Y-ZL z%=}kKX0VUoOaNo-r8U#?Mg38U&lU@9Pp#04?nI7OExq}6z@WT9~5CR$5UD_z$cPu5qVTbph zL)Ff5X$VAI_oJaI7u--l6z^-C)01B(YJ5NjPK9g#pdE; zBH<4XiTE8_3ASm%DuhsW%H)~?B6z>Iyn*{wgQgn%)yEMf#5RO5t%7SgK-~MAD~(e2~ukJ(o#Sxj_U)6^saoRP(1U9iKTZ z24NIckW79>S@$n4oXXt}A|O|Ridyy2`kyH*R-F`cIV;Esvm#I_F4KgRf?j(Y1IwBd zGQJbjcmtyXb@C2BL*K{yzUfwJu_^lvk{MLsPYDX^00000NkvXXu0mjf String.Compare(x, category, StringComparison.OrdinalIgnoreCase) == 0); + + if (IsInclusiveFilter) + { + if (isCategoryInFilter) + return IsFailFilter ? TestResultStatus.Fail : TestResultStatus.Warning; + else + return IsFailFilter ? TestResultStatus.Warning : TestResultStatus.Fail; + } + else + { + if (isCategoryInFilter) + return IsFailFilter ? TestResultStatus.Warning : TestResultStatus.Fail; + else + return IsFailFilter ? TestResultStatus.Fail : TestResultStatus.Warning; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta new file mode 100644 index 00000000..84e5678d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs.meta @@ -0,0 +1,10 @@ +ο»ΏfileFormatVersion: 2 +guid: a5e60d3639f24063a4eabc21ea1a04a9 +timeCreated: 1657617578 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Categories/ValidatorCategory.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs new file mode 100644 index 00000000..79ef18c4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs @@ -0,0 +1,71 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; +using System; +using System.IO; + +namespace AssetStoreTools.Validator +{ + internal class CurrentProjectValidator : ValidatorBase + { + private CurrentProjectValidationSettings _settings; + + public CurrentProjectValidator(CurrentProjectValidationSettings settings) : base(settings) + { + _settings = settings; + } + + protected override void ValidateSettings() + { + if (_settings == null) + throw new Exception("Validation Settings is null"); + + if (_settings.ValidationPaths == null + || _settings.ValidationPaths.Count == 0) + throw new Exception("No validation paths were set"); + + switch (_settings.ValidationType) + { + case ValidationType.Generic: + case ValidationType.UnityPackage: + ValidateUnityPackageSettings(); + break; + default: + throw new NotImplementedException("Undefined validation type"); + } + } + + private void ValidateUnityPackageSettings() + { + var invalidPaths = string.Empty; + foreach (var path in _settings.ValidationPaths) + { + if (!Directory.Exists(path)) + invalidPaths += $"\n{path}"; + } + + if (!string.IsNullOrEmpty(invalidPaths)) + throw new Exception("The following directories do not exist:" + invalidPaths); + } + + protected override ValidationResult GenerateValidationResult() + { + ITestConfig config; + var applicableTests = GetApplicableTests(ValidationType.Generic); + switch (_settings.ValidationType) + { + case ValidationType.Generic: + config = new GenericTestConfig() { ValidationPaths = _settings.ValidationPaths.ToArray() }; + break; + case ValidationType.UnityPackage: + applicableTests.AddRange(GetApplicableTests(ValidationType.UnityPackage)); + config = new GenericTestConfig() { ValidationPaths = _settings.ValidationPaths.ToArray() }; + break; + default: + return new ValidationResult() { Status = ValidationStatus.Failed, Exception = new Exception("Undefined validation type") }; + } + + var validationResult = RunTests(applicableTests, config); + return validationResult; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs.meta new file mode 100644 index 00000000..16fe73b4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3a6371dcfa8545c478545b4a43433599 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/CurrentProjectValidator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta new file mode 100644 index 00000000..3b400636 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c2a38ded8e054c4088aff1db7224f66 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs new file mode 100644 index 00000000..6b83057f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Validator.Data +{ + internal class CurrentProjectValidationSettings : ValidationSettings + { + public List ValidationPaths; + public ValidationType ValidationType; + + public CurrentProjectValidationSettings() + { + Category = string.Empty; + ValidationPaths = new List(); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj == null || obj.GetType() != typeof(CurrentProjectValidationSettings)) + return false; + + var other = (CurrentProjectValidationSettings)obj; + return Category == other.Category + && ValidationType == other.ValidationType + && ValidationPaths.OrderBy(x => x).SequenceEqual(other.ValidationPaths.OrderBy(x => x)); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs.meta new file mode 100644 index 00000000..a1a99356 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9e4a4a4aa3f501847b1abb1e08505f9b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/CurrentProjectValidationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs new file mode 100644 index 00000000..f770cd4c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs @@ -0,0 +1,7 @@ +namespace AssetStoreTools.Validator.Data +{ + internal class ExternalProjectValidationSettings : ValidationSettings + { + public string PackagePath; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs.meta new file mode 100644 index 00000000..4b1d4fcb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f79c895f4bb099b4983dd20eef72a7bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ExternalProjectValidationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.meta new file mode 100644 index 00000000..7f0bd9aa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d51c5c866dcd449488caa10a40dd3301 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs new file mode 100644 index 00000000..e642904a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs @@ -0,0 +1,31 @@ +using Newtonsoft.Json; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.Data.MessageActions +{ + internal class HighlightObjectAction : IMessageAction + { + public string Tooltip => "Click to highlight the associated object in Hierarchy/Project view"; + public Object Target => _target?.GetObject(); + + [JsonProperty] + private TestResultObject _target; + + public HighlightObjectAction() { } + + public HighlightObjectAction(Object target) + { + _target = new TestResultObject(target); + } + + public void Execute() + { + var targetObject = _target.GetObject(); + if (targetObject == null) + return; + + EditorGUIUtility.PingObject(targetObject); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs.meta new file mode 100644 index 00000000..7df75cac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: de24c0a7f8a22c142a224e6abd0ddc68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/HighlightObjectAction.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs new file mode 100644 index 00000000..ec48b5b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; +using UnityEngine; + +namespace AssetStoreTools.Validator.Data.MessageActions +{ + internal interface IMessageAction + { + [JsonIgnore] + string Tooltip { get; } + + [JsonIgnore] + Object Target { get; } + + void Execute(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs.meta new file mode 100644 index 00000000..a1c2bfa3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f1636d7241abdf1498368f841aa818a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/IMessageAction.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs new file mode 100644 index 00000000..fb5dfa54 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs @@ -0,0 +1,38 @@ +using Newtonsoft.Json; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.Data.MessageActions +{ + internal class OpenAssetAction : IMessageAction + { + public string Tooltip => "Click to open the associated asset"; + public Object Target => _target?.GetObject(); + + [JsonProperty] + private TestResultObject _target; + [JsonProperty] + private int _lineNumber; + + public OpenAssetAction() { } + + public OpenAssetAction(Object target) + { + _target = new TestResultObject(target); + } + + public OpenAssetAction(Object target, int lineNumber) : this(target) + { + _lineNumber = lineNumber; + } + + public void Execute() + { + var targetObject = _target.GetObject(); + if (targetObject == null) + return; + + AssetDatabase.OpenAsset(targetObject, _lineNumber); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs.meta new file mode 100644 index 00000000..257d7589 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9fb4fec293bf73f4a8f870c535750613 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/MessageActions/OpenAssetAction.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs new file mode 100644 index 00000000..21d1dd04 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs @@ -0,0 +1,52 @@ +ο»Ώusing AssetStoreTools.Validator.Data.MessageActions; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.Data +{ + internal struct TestResult + { + public TestResultStatus Status; + + [JsonProperty] + private List _messages; + + [JsonIgnore] + public int MessageCount => _messages != null ? _messages.Count : 0; + + public TestResultMessage GetMessage(int index) + { + return _messages[index]; + } + + public void AddMessage(string msg) + { + AddMessage(msg, null, null); + } + + public void AddMessage(string msg, IMessageAction clickAction) + { + AddMessage(msg, clickAction, null); + } + + public void AddMessage(string msg, IMessageAction clickAction, params UnityEngine.Object[] messageObjects) + { + if (_messages == null) + _messages = new List(); + + var message = new TestResultMessage(msg, clickAction); + _messages.Add(message); + + if (messageObjects == null) + return; + + foreach (var obj in messageObjects) + { + if (obj == null) + continue; + + message.AddMessageObject(obj); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs.meta new file mode 100644 index 00000000..6aea0106 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 05d7d92bbda6bf44f8ed5fbd0cde57e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResult.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs new file mode 100644 index 00000000..7ebe0f5d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs @@ -0,0 +1,53 @@ +using AssetStoreTools.Validator.Data.MessageActions; +using Newtonsoft.Json; +using System.Collections.Generic; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Data +{ + internal class TestResultMessage + { + [JsonIgnore] + public int MessageObjectCount => _messageObjects.Count; + + [JsonProperty] + private string _text; + [JsonProperty] + private List _messageObjects; + [JsonProperty] + private IMessageAction _clickAction; + + public TestResultMessage() { } + + public TestResultMessage(string text) + { + _text = text; + _messageObjects = new List(); + } + + public TestResultMessage(string text, IMessageAction clickAction) : this(text) + { + _clickAction = clickAction; + } + + public string GetText() + { + return _text; + } + + public IMessageAction GetClickAction() + { + return _clickAction; + } + + public void AddMessageObject(Object obj) + { + _messageObjects.Add(new TestResultObject(obj)); + } + + public TestResultObject GetMessageObject(int index) + { + return _messageObjects[index]; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs.meta new file mode 100644 index 00000000..eaab5193 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0761356c44140ca49917f93b42926471 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultMessage.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs new file mode 100644 index 00000000..8b601d54 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs @@ -0,0 +1,35 @@ +using Newtonsoft.Json; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.Data +{ + internal class TestResultObject + { + [JsonIgnore] + private Object _object; + [JsonProperty] + private string _objectGlobalId; + + public TestResultObject(Object obj) + { + _object = obj; + _objectGlobalId = GlobalObjectId.GetGlobalObjectIdSlow(obj).ToString(); + } + + public Object GetObject() + { + if (_object != null) + return _object; + + if (string.IsNullOrEmpty(_objectGlobalId)) + return null; + + if (!GlobalObjectId.TryParse(_objectGlobalId, out var globalObject)) + return null; + + _object = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(globalObject); + return _object; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs.meta new file mode 100644 index 00000000..414f1e24 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: acce8e477b7fe2c4aa430ebdd65ea7d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultObject.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs new file mode 100644 index 00000000..ccda879b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs @@ -0,0 +1,11 @@ +namespace AssetStoreTools.Validator.Data +{ + internal enum TestResultStatus + { + Undefined = 0, + Pass = 1, + Fail = 2, + Warning = 3, + VariableSeverityIssue = 4 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs.meta new file mode 100644 index 00000000..118669eb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: eef1ba0cf35f1304d8929e23b94e7c23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/TestResultStatus.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs new file mode 100644 index 00000000..89ae6337 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs @@ -0,0 +1,24 @@ +ο»Ώusing AssetStoreTools.Validator.TestDefinitions; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.Data +{ + internal class ValidationResult + { + public ValidationStatus Status; + public bool HadCompilationErrors; + public string ProjectPath; + public List Tests; + public Exception Exception; + + public ValidationResult() + { + Status = ValidationStatus.NotRun; + HadCompilationErrors = false; + ProjectPath = string.Empty; + Tests = new List(); + Exception = null; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs.meta new file mode 100644 index 00000000..cb5e9c31 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b15525b8dcf3e654ca2f895472ab7cb1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationResult.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs new file mode 100644 index 00000000..5b51134a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs @@ -0,0 +1,7 @@ +namespace AssetStoreTools.Validator.Data +{ + internal abstract class ValidationSettings + { + public string Category; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs.meta new file mode 100644 index 00000000..4afa08fa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 33e99d6b6e1e7ef4abd6cd2c0137741a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs new file mode 100644 index 00000000..f0fb66c6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs @@ -0,0 +1,10 @@ +namespace AssetStoreTools.Validator.Data +{ + internal enum ValidationStatus + { + NotRun, + RanToCompletion, + Failed, + Cancelled + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs.meta new file mode 100644 index 00000000..dbb0e8c3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a1f1e1e94faa6284f8d71804ba2bbd24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationStatus.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs new file mode 100644 index 00000000..dd3b51cc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs @@ -0,0 +1,8 @@ +namespace AssetStoreTools.Validator.Data +{ + internal enum ValidationType + { + Generic = 0, + UnityPackage = 1 + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs.meta new file mode 100644 index 00000000..88f9f2ae --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 079f8963464230145853d86eff935e04 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Data/ValidationType.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs new file mode 100644 index 00000000..3556d1a3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs @@ -0,0 +1,259 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator +{ + internal class ExternalProjectValidator : ValidatorBase + { + private ExternalProjectValidationSettings _settings; + + public ExternalProjectValidator(ExternalProjectValidationSettings settings) : base(settings) + { + _settings = settings; + } + + protected override void ValidateSettings() + { + if (_settings == null) + throw new Exception("Validation Settings is null"); + + if (string.IsNullOrEmpty(_settings.PackagePath) + || !File.Exists(_settings.PackagePath)) + throw new Exception("Package was not found"); + } + + protected override ValidationResult GenerateValidationResult() + { + bool interactiveMode = false; + try + { + // Step 1 - prepare a temporary project + var result = PrepareTemporaryValidationProject(interactiveMode); + + // If preparation was cancelled or setting up project failed - return immediately + if (result.Status == ValidationStatus.Cancelled || result.Status == ValidationStatus.Failed) + return result; + + // Step 2 - load the temporary project and validate the package + result = ValidateTemporaryValidationProject(result, interactiveMode); + + // Step 3 - copy validation results + result = ParseValidationResult(result.ProjectPath); + + return result; + } + catch (Exception e) + { + return new ValidationResult() { Status = ValidationStatus.Failed, Exception = e }; + } + finally + { + EditorUtility.ClearProgressBar(); + } + } + + private ValidationResult PrepareTemporaryValidationProject(bool interactiveMode) + { + EditorUtility.DisplayProgressBar("Validating...", "Preparing the validation project. This may take a while.", 0.3f); + + var result = new ValidationResult(); + var tempProjectPath = Path.Combine(Constants.RootProjectPath, "Temp", GUID.Generate().ToString()).Replace("\\", "/"); + result.ProjectPath = tempProjectPath; + + if (!Directory.Exists(tempProjectPath)) + Directory.CreateDirectory(tempProjectPath); + + // Cannot edit a package.json file that does not yet exist - copy over AST instead + var tempPackagesPath = $"{tempProjectPath}/Packages"; + if (!Directory.Exists(tempPackagesPath)) + Directory.CreateDirectory(tempPackagesPath); + var assetStoreToolsPath = PackageUtility.GetAllPackages().FirstOrDefault(x => x.name == "com.unity.asset-store-tools").resolvedPath.Replace("\\", "/"); + FileUtility.CopyDirectory(assetStoreToolsPath, $"{tempPackagesPath}/com.unity.asset-store-tools", true); + + var logFilePath = $"{tempProjectPath}/preparation.log"; + + // Create the temporary project + var processInfo = new System.Diagnostics.ProcessStartInfo() + { + FileName = Constants.UnityPath, + Arguments = $"-createProject \"{tempProjectPath}\" -logFile \"{logFilePath}\" -importpackage \"{Path.GetFullPath(_settings.PackagePath)}\" -quit" + }; + + if (!interactiveMode) + processInfo.Arguments += " -batchmode"; + + var exitCode = 0; + + using (var process = System.Diagnostics.Process.Start(processInfo)) + { + while (!process.HasExited) + { + if (EditorUtility.DisplayCancelableProgressBar("Validating...", "Preparing the validation project. This may take a while.", 0.3f)) + process.Kill(); + + Thread.Sleep(10); + } + + exitCode = process.ExitCode; + + // Windows and MacOS exit codes + if (exitCode == -1 || exitCode == 137) + { + result.Status = ValidationStatus.Cancelled; + return result; + } + } + + if (exitCode != 0) + { + result.Status = ValidationStatus.Failed; + result.Exception = new Exception($"Setting up the temporary project failed (exit code {exitCode})\n\nMore information can be found in the log file: {logFilePath}"); + } + else + { + result.Status = ValidationStatus.RanToCompletion; + } + + return result; + } + + private ValidationResult ValidateTemporaryValidationProject(ValidationResult result, bool interactiveMode) + { + EditorUtility.DisplayProgressBar("Validating...", "Performing validation...", 0.6f); + + var logFilePath = $"{result.ProjectPath}/validation.log"; + var processInfo = new System.Diagnostics.ProcessStartInfo() + { + FileName = Constants.UnityPath, + Arguments = $"-projectPath \"{result.ProjectPath}\" -logFile \"{logFilePath}\" -executeMethod AssetStoreTools.Validator.ExternalProjectValidator.ValidateProject -category \"{_settings.Category}\"" + }; + + if (!interactiveMode) + processInfo.Arguments += " -batchmode -ignorecompilererrors"; + + var exitCode = 0; + + using (var process = System.Diagnostics.Process.Start(processInfo)) + { + process.WaitForExit(); + exitCode = process.ExitCode; + } + + if (exitCode != 0) + { + result.Status = ValidationStatus.Failed; + result.Exception = new Exception($"Validating the temporary project failed (exit code {exitCode})\n\nMore information can be found in the log file: {logFilePath}"); + } + else + { + result.Status = ValidationStatus.RanToCompletion; + } + + return result; + } + + private ValidationResult ParseValidationResult(string externalProjectPath) + { + if (!CachingService.GetCachedValidatorStateData(externalProjectPath, out var validationStateData)) + throw new Exception("Could not find external project's validation results"); + + var cachedResult = validationStateData.GetResults(); + var cachedTestResults = cachedResult.GetResults(); + var tests = GetApplicableTests(ValidationType.Generic, ValidationType.UnityPackage); + + foreach (var test in tests) + { + if (!cachedTestResults.Any(x => x.Key == test.Id)) + continue; + + var matchingTest = cachedTestResults.First(x => x.Key == test.Id); + test.Result = matchingTest.Value; + } + + var result = new ValidationResult() + { + Status = cachedResult.GetStatus(), + HadCompilationErrors = cachedResult.GetHadCompilationErrors(), + ProjectPath = cachedResult.GetProjectPath(), + Tests = tests + }; + + return result; + } + + public static void OpenExternalValidationProject(string projectPath) + { + var unityPath = Constants.UnityPath; + var logFilePath = $"{projectPath}/editor.log"; + + var processInfo = new System.Diagnostics.ProcessStartInfo() + { + FileName = unityPath, + Arguments = $"-projectPath \"{projectPath}\" -logFile \"{logFilePath}\" -executeMethod AssetStoreTools.AssetStoreTools.ShowAssetStoreToolsValidator" + }; + + using (var process = System.Diagnostics.Process.Start(processInfo)) + { + process.WaitForExit(); + } + } + + // Invoked via Command Line Arguments + private static void ValidateProject() + { + var exitCode = 0; + try + { + // Determine whether to validate Assets folder or Packages folders + var validationPaths = new List(); + var packageDirectories = Directory.GetDirectories("Packages", "*", SearchOption.TopDirectoryOnly) + .Select(x => x.Replace("\\", "/")) + .Where(x => x != "Packages/com.unity.asset-store-tools").ToArray(); + + if (packageDirectories.Length > 0) + validationPaths.AddRange(packageDirectories); + else + validationPaths.Add("Assets"); + + // Parse category + var category = string.Empty; + var args = Environment.GetCommandLineArgs().ToList(); + var categoryIndex = args.IndexOf("-category"); + if (categoryIndex != -1 && categoryIndex + 1 < args.Count) + category = args[categoryIndex + 1]; + + // Run validation + var validationSettings = new CurrentProjectValidationSettings() + { + Category = category, + ValidationPaths = validationPaths, + ValidationType = ValidationType.UnityPackage + }; + + var validator = new CurrentProjectValidator(validationSettings); + var result = validator.Validate(); + + // Display results + AssetStoreTools.ShowAssetStoreToolsValidator(validationSettings, result); + EditorUtility.DisplayDialog("Validation complete", "Package validation complete.\n\nTo resume work in the original project, close this Editor instance", "OK"); + } + catch + { + exitCode = 1; + throw; + } + finally + { + if (Application.isBatchMode) + EditorApplication.Exit(exitCode); + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs.meta new file mode 100644 index 00000000..09ea3715 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2664bbca63a2444498f13beb7e4fa731 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ExternalProjectValidator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs new file mode 100644 index 00000000..bd16b586 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Validator.Data; + +namespace AssetStoreTools.Validator +{ + internal interface IValidator + { + ValidationSettings Settings { get; } + + ValidationResult Validate(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs.meta new file mode 100644 index 00000000..e6d257e4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d49e9393288e0ed418c546e57c4cb425 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/IValidator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services.meta new file mode 100644 index 00000000..03e42344 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9315c4052243ab2488208604c11c53c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService.meta new file mode 100644 index 00000000..5d9a1cb4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a52c1c4a2b7caa458af5b9a212b80a5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs new file mode 100644 index 00000000..cff8d95f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs @@ -0,0 +1,55 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.UI.Data.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace AssetStoreTools.Validator.Services +{ + internal class CachingService : ICachingService + { + public bool GetCachedValidatorStateData(out ValidatorStateData stateData) + { + return GetCachedValidatorStateData(Constants.RootProjectPath, out stateData); + } + + public bool GetCachedValidatorStateData(string projectPath, out ValidatorStateData stateData) + { + stateData = null; + if (!CacheUtil.GetFileFromProjectPersistentCache(projectPath, Constants.Cache.ValidationResultFile, out var filePath)) + return false; + + try + { + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = ValidatorStateDataContractResolver.Instance, + TypeNameHandling = TypeNameHandling.Auto, + Converters = new List() { new StringEnumConverter() } + }; + + stateData = JsonConvert.DeserializeObject(File.ReadAllText(filePath, Encoding.UTF8), serializerSettings); + return true; + } + catch + { + return false; + } + } + + public void CacheValidatorStateData(ValidatorStateData stateData) + { + var serializerSettings = new JsonSerializerSettings() + { + ContractResolver = ValidatorStateDataContractResolver.Instance, + Formatting = Formatting.Indented, + TypeNameHandling = TypeNameHandling.Auto, + Converters = new List() { new StringEnumConverter() } + }; + + CacheUtil.CreateFileInPersistentCache(Constants.Cache.ValidationResultFile, JsonConvert.SerializeObject(stateData, serializerSettings), true); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs.meta new file mode 100644 index 00000000..9a7597ac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b2d545f659acb4343bf485ffb20ecf72 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/CachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs new file mode 100644 index 00000000..bee25d59 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs @@ -0,0 +1,11 @@ +using AssetStoreTools.Validator.UI.Data.Serialization; + +namespace AssetStoreTools.Validator.Services +{ + internal interface ICachingService : IValidatorService + { + void CacheValidatorStateData(ValidatorStateData stateData); + bool GetCachedValidatorStateData(out ValidatorStateData stateData); + bool GetCachedValidatorStateData(string projectPath, out ValidatorStateData stateData); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs.meta new file mode 100644 index 00000000..6abd7bfa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a8a3e36c133848447b043a91e709c63e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/ICachingService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs new file mode 100644 index 00000000..aa495ee2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json.Serialization; + +namespace AssetStoreTools.Previews.Services +{ + internal class PreviewDatabaseContractResolver : DefaultContractResolver + { + private static PreviewDatabaseContractResolver _instance; + public static PreviewDatabaseContractResolver Instance => _instance ?? (_instance = new PreviewDatabaseContractResolver()); + + private NamingStrategy _namingStrategy; + + private PreviewDatabaseContractResolver() + { + _namingStrategy = new SnakeCaseNamingStrategy(); + } + + protected override string ResolvePropertyName(string propertyName) + { + var resolvedName = _namingStrategy.GetPropertyName(propertyName, false); + if (resolvedName.StartsWith("_")) + return resolvedName.Substring(1); + + return resolvedName; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs.meta new file mode 100644 index 00000000..e423e2a7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: aee615e9aaf50fb4f989cd4698e8947e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/CachingService/PreviewDatabaseContractResolver.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs new file mode 100644 index 00000000..3ff09b82 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs @@ -0,0 +1,4 @@ +namespace AssetStoreTools.Validator.Services +{ + internal interface IValidatorService { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs.meta new file mode 100644 index 00000000..0623f405 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 075953f4ab4a65d4fae6e891360df0d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/IValidatorService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation.meta new file mode 100644 index 00000000..bf10d70d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 184dcfbfe1d21454fa8cf49f1c637871 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions.meta new file mode 100644 index 00000000..d6c2cf03 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed0af5acc22551645ae4cb7d75bd1c36 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs new file mode 100644 index 00000000..a73e3ce1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface IAssetUtilityService : IValidatorService + { + IEnumerable GetAssetPathsFromAssets(string[] searchPaths, AssetType type); + IEnumerable GetObjectsFromAssets(string[] searchPaths, AssetType type) where T : Object; + IEnumerable GetObjectsFromAssets(string[] searchPaths, AssetType type); + string ObjectToAssetPath(Object obj); + T AssetPathToObject(string assetPath) where T : Object; + Object AssetPathToObject(string assetPath); + AssetImporter GetAssetImporter(string assetPath); + AssetImporter GetAssetImporter(Object asset); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs.meta new file mode 100644 index 00000000..85142f31 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d28c5ea40f4c9954bae02804e416b898 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IAssetUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs new file mode 100644 index 00000000..7633ffdf --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs @@ -0,0 +1,7 @@ +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface IFileSignatureUtilityService : IValidatorService + { + ArchiveType GetArchiveType(string filePath); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs.meta new file mode 100644 index 00000000..9b6cbb82 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 609c423482ecf8844a71166b4ef49cb6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IFileSignatureUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs new file mode 100644 index 00000000..ba4959e8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface IMeshUtilityService : IValidatorService + { + IEnumerable GetCustomMeshesInObject(GameObject obj); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs.meta new file mode 100644 index 00000000..28ce709f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: acde6f9b97c9cac4b88a84aa9001a0fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IMeshUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs new file mode 100644 index 00000000..fa29424f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface IModelUtilityService : IValidatorService + { + Dictionary> GetImportLogs(params Object[] models); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs.meta new file mode 100644 index 00000000..e710e854 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 91f6bacccdfecb84fb5ab0ba384353b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IModelUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs new file mode 100644 index 00000000..d80f1841 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs @@ -0,0 +1,13 @@ +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface ISceneUtilityService : IValidatorService + { + string CurrentScenePath { get; } + + Scene OpenScene(string scenePath); + GameObject[] GetRootGameObjects(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs.meta new file mode 100644 index 00000000..ac0e61d0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cf5ef331063e5aa4e95dfe3eadedf9af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/ISceneUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs new file mode 100644 index 00000000..04214c3c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal interface IScriptUtilityService : IValidatorService + { + IReadOnlyDictionary> GetTypeNamespacesFromScriptAssets(IList monoScripts); + IReadOnlyDictionary> GetTypesFromAssemblies(IList assemblies); + IReadOnlyDictionary> GetTypesFromScriptAssets(IList monoScripts); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs.meta new file mode 100644 index 00000000..cf09904e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e0a9f88d37222e4428853b6d3d00b1bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Abstractions/IScriptUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs new file mode 100644 index 00000000..fb51d8a4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs @@ -0,0 +1,216 @@ +using AssetStoreTools.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class AssetUtilityService : IAssetUtilityService + { + public IEnumerable GetAssetPathsFromAssets(string[] searchPaths, AssetType type) + { + string filter = string.Empty; + string[] extensions = null; + + switch (type) + { + // General Types + case AssetType.All: + filter = ""; + break; + case AssetType.Prefab: + filter = "t:prefab"; + break; + case AssetType.Material: + filter = "t:material"; + break; + case AssetType.Model: + filter = "t:model"; + break; + case AssetType.Scene: + filter = "t:scene"; + break; + case AssetType.Texture: + filter = "t:texture"; + break; + case AssetType.Video: + filter = "t:VideoClip"; + break; + // Specific Types + case AssetType.LossyAudio: + filter = "t:AudioClip"; + extensions = new[] { ".mp3", ".ogg" }; + break; + case AssetType.NonLossyAudio: + filter = "t:AudioClip"; + extensions = new[] { ".wav", ".aif", ".aiff" }; + break; + case AssetType.JavaScript: + filter = "t:TextAsset"; + extensions = new[] { ".js" }; + break; + case AssetType.Mixamo: + filter = "t:model"; + extensions = new[] { ".fbx" }; + break; + case AssetType.JPG: + filter = "t:texture"; + extensions = new[] { ".jpg", "jpeg" }; + break; + case AssetType.Executable: + filter = string.Empty; + extensions = new[] { ".exe", ".bat", ".msi", ".apk" }; + break; + case AssetType.Documentation: + filter = string.Empty; + extensions = new[] { ".txt", ".pdf", ".html", ".rtf", ".md" }; + break; + case AssetType.SpeedTree: + filter = string.Empty; + extensions = new[] { ".spm", ".srt", ".stm", ".scs", ".sfc", ".sme", ".st" }; + break; + case AssetType.Shader: + filter = string.Empty; + extensions = new[] { ".shader", ".shadergraph", ".raytrace", ".compute" }; + break; + case AssetType.MonoScript: + filter = "t:script"; + extensions = new[] { ".cs" }; + break; + case AssetType.UnityPackage: + filter = string.Empty; + extensions = new[] { ".unitypackage" }; + break; + case AssetType.PrecompiledAssembly: + var assemblyPaths = GetPrecompiledAssemblies(searchPaths); + return assemblyPaths; + default: + return Array.Empty(); + } + + var guids = AssetDatabase.FindAssets(filter, searchPaths); + var paths = guids.Select(AssetDatabase.GUIDToAssetPath); + + if (extensions != null) + paths = paths.Where(x => extensions.Any(x.ToLower().EndsWith)); + + if (type == AssetType.Mixamo) + paths = paths.Where(IsMixamoFbx); + + paths = paths.Distinct(); + return paths; + } + + public IEnumerable GetObjectsFromAssets(string[] searchPaths, AssetType type) where T : Object + { + var paths = GetAssetPathsFromAssets(searchPaths, type); +#if !AB_BUILDER + var objects = paths.Select(AssetDatabase.LoadAssetAtPath).Where(x => x != null); +#else + var objects = new AssetEnumerator(paths); +#endif + return objects; + } + + public IEnumerable GetObjectsFromAssets(string[] searchPaths, AssetType type) + { + return GetObjectsFromAssets(searchPaths, type); + } + + private IEnumerable GetPrecompiledAssemblies(string[] searchPaths) + { + // Note - for packages, Compilation Pipeline returns full paths, as they appear on disk, not Asset Database + var allDllPaths = CompilationPipeline.GetPrecompiledAssemblyPaths(CompilationPipeline.PrecompiledAssemblySources.UserAssembly); + var rootProjectPath = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length); + var packages = PackageUtility.GetAllLocalPackages(); + + var result = new List(); + foreach (var dllPath in allDllPaths) + { + var absoluteDllPath = Path.GetFullPath(dllPath).Replace("\\", "/"); + foreach (var validationPath in searchPaths) + { + var absoluteValidationPath = Path.GetFullPath(validationPath).Replace("\\", "/"); + if (absoluteDllPath.StartsWith(absoluteValidationPath)) + { + int pathSeparatorLength = 1; + if (absoluteDllPath.StartsWith(Application.dataPath)) + { + var adbPath = $"Assets/{absoluteDllPath.Remove(0, Application.dataPath.Length + pathSeparatorLength)}"; + result.Add(adbPath); + } + else + { + // For non-Asset folder paths (i.e. local and embedded packages), convert disk path to ADB path + var package = packages.FirstOrDefault(x => dllPath.StartsWith(x.resolvedPath.Replace('\\', '/'))); + + if (package == null) + continue; + + var dllPathInPackage = absoluteDllPath.Remove(0, Path.GetFullPath(package.resolvedPath).Length + pathSeparatorLength); + var adbPath = $"Packages/{package.name}/{dllPathInPackage}"; + + result.Add(adbPath); + } + } + } + } + + return result; + } + + private bool IsMixamoFbx(string fbxPath) + { + // Location of Mixamo Header, this is located in every mixamo fbx file exported + //const int mixamoHeader = 0x4c0 + 2; // < this is the original location from A$ Tools, unsure if Mixamo file headers were changed since then + const int mixamoHeader = 1622; + // Length of Mixamo header + const int length = 0xa; + + var fs = new FileStream(fbxPath, FileMode.Open); + // Check if length is further than + if (fs.Length < mixamoHeader) + return false; + + byte[] buffer = new byte[length]; + using (BinaryReader reader = new BinaryReader(fs)) + { + reader.BaseStream.Seek(mixamoHeader, SeekOrigin.Begin); + reader.Read(buffer, 0, length); + } + + string result = System.Text.Encoding.ASCII.GetString(buffer); + return result.Contains("Mixamo"); + } + + public string ObjectToAssetPath(Object obj) + { + return AssetDatabase.GetAssetPath(obj); + } + + public T AssetPathToObject(string assetPath) where T : Object + { + return AssetDatabase.LoadAssetAtPath(assetPath); + } + + public Object AssetPathToObject(string assetPath) + { + return AssetPathToObject(assetPath); + } + + public AssetImporter GetAssetImporter(string assetPath) + { + return AssetImporter.GetAtPath(assetPath); + } + + public AssetImporter GetAssetImporter(Object asset) + { + return GetAssetImporter(ObjectToAssetPath(asset)); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs.meta new file mode 100644 index 00000000..f28cb1cd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9634968648d355c47b7cb12aead7abab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/AssetUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data.meta new file mode 100644 index 00000000..32569358 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8dcc2f4da0b6cea4ab4733ebf32edab4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs new file mode 100644 index 00000000..d225180e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs @@ -0,0 +1,19 @@ +ο»Ώnamespace AssetStoreTools.Validator.Services.Validation +{ + internal enum ArchiveType + { + None, + TarGz, + Zip, + Rar, + Tar, + TarZip, + Bz2, + LZip, + SevenZip, + GZip, + QuickZip, + Xz, + Wim + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs.meta new file mode 100644 index 00000000..dcf4f0c6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 4061cb7aed3883346a66494c23e2e77b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/ArchiveType.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs new file mode 100644 index 00000000..0df889a8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs @@ -0,0 +1,84 @@ +ο»Ώusing System; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class AssetEnumerator : IEnumerator, IEnumerable where T : Object + { + public const int Capacity = 32; + + private Queue _pathQueue; + private Queue _loadedAssetQueue; + + private T _currentElement; + + public AssetEnumerator(IEnumerable paths) + { + _pathQueue = new Queue(paths); + _loadedAssetQueue = new Queue(); + } + + public bool MoveNext() + { + bool hasPathsButHasNoAssets = _pathQueue.Count != 0 && _loadedAssetQueue.Count == 0; + if (hasPathsButHasNoAssets) + { + LoadMore(); + } + + bool dequeued = false; + if (_loadedAssetQueue.Count != 0) + { + _currentElement = _loadedAssetQueue.Dequeue(); + dequeued = true; + } + + return dequeued; + } + + private void LoadMore() + { + int limit = Capacity; + while (limit > 0 && _pathQueue.Count != 0) + { + string path = _pathQueue.Dequeue(); + T asset = AssetDatabase.LoadAssetAtPath(path); + if (asset != null) + { + _loadedAssetQueue.Enqueue(asset); + limit--; + } + } + + // Unload other loose asset references + EditorUtility.UnloadUnusedAssetsImmediate(); + } + + public void Reset() + { + throw new NotSupportedException("Asset Enumerator cannot be reset."); + } + + public T Current => _currentElement; + + object IEnumerator.Current => Current; + + public void Dispose() + { + // No need to dispose + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this; + } + + public IEnumerator GetEnumerator() + { + return this; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs.meta new file mode 100644 index 00000000..01ead66d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 0859579889cc56f4aa26eb863a1487b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetEnumerator.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs new file mode 100644 index 00000000..2fc188d0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs @@ -0,0 +1,25 @@ +ο»Ώnamespace AssetStoreTools.Validator.Services.Validation +{ + internal enum AssetType + { + All, + Documentation, + Executable, + JPG, + JavaScript, + LossyAudio, + Material, + Mixamo, + Model, + MonoScript, + NonLossyAudio, + PrecompiledAssembly, + Prefab, + Scene, + Shader, + SpeedTree, + Texture, + UnityPackage, + Video + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs.meta new file mode 100644 index 00000000..5519b783 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b81d00d4ed0a7da4289d4d6248ef9d34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/AssetType.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs new file mode 100644 index 00000000..67663be5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs @@ -0,0 +1,10 @@ +ο»Ώusing UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class LogEntry + { + public string Message; + public LogType Severity; + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs.meta new file mode 100644 index 00000000..e4d2006d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a1e81104d6b0f4c449ee57503c3b6669 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/Data/LogEntry.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs new file mode 100644 index 00000000..2a140f45 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class FileSignatureUtilityService : IFileSignatureUtilityService + { + private class FileSignature + { + public byte[] SignatureBytes; + public int Offset; + + public FileSignature(byte[] signatureBytes, int offset) + { + SignatureBytes = signatureBytes; + Offset = offset; + } + } + + private static readonly Dictionary ArchiveSignatures = new Dictionary + { + { new FileSignature(new byte[] { 0x1f, 0x8b }, 0), ArchiveType.TarGz }, + { new FileSignature(new byte[] { 0x50, 0x4b, 0x03, 0x04 }, 0), ArchiveType.Zip }, + { new FileSignature(new byte[] { 0x50, 0x4b, 0x05, 0x06 }, 0), ArchiveType.Zip }, // Empty Zip Archive + { new FileSignature(new byte[] { 0x50, 0x4b, 0x07, 0x08 }, 0), ArchiveType.Zip }, // Spanned Zip Archive + + { new FileSignature(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }, 0), ArchiveType.Rar }, // RaR v1.50+ + { new FileSignature(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 }, 0), ArchiveType.Rar }, // RaR v5.00+ + { new FileSignature(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 }, 257), ArchiveType.Tar }, + { new FileSignature(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 }, 257), ArchiveType.Tar }, + { new FileSignature(new byte[] { 0x1f, 0x9d }, 0), ArchiveType.TarZip }, // TarZip LZW algorithm + { new FileSignature(new byte[] { 0x1f, 0xa0 }, 0), ArchiveType.TarZip }, // TarZip LZH algorithm + { new FileSignature(new byte[] { 0x42, 0x5a, 0x68 }, 0), ArchiveType.Bz2 }, + { new FileSignature(new byte[] { 0x4c, 0x5a, 0x49, 0x50 }, 0), ArchiveType.LZip }, + { new FileSignature(new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }, 0), ArchiveType.SevenZip }, + { new FileSignature(new byte[] { 0x1f, 0x8b }, 0), ArchiveType.GZip }, + { new FileSignature(new byte[] { 0x52, 0x53, 0x56, 0x4b, 0x44, 0x41, 0x54, 0x41 }, 0), ArchiveType.QuickZip }, + { new FileSignature(new byte[] { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00 }, 0), ArchiveType.Xz }, + { new FileSignature(new byte[] { 0x4D, 0x53, 0x57, 0x49, 0x4D, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00 }, 0), ArchiveType.Wim } + }; + + public ArchiveType GetArchiveType(string filePath) + { + if (!File.Exists(filePath)) + return ArchiveType.None; + + try + { + using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + foreach (var kvp in ArchiveSignatures) + { + var fileSignature = kvp.Key; + var archiveType = kvp.Value; + + if (stream.Length < fileSignature.SignatureBytes.Length) + continue; + + var bytes = new byte[fileSignature.SignatureBytes.Length]; + stream.Seek(fileSignature.Offset, SeekOrigin.Begin); + stream.Read(bytes, 0, bytes.Length); + + if (fileSignature.SignatureBytes.SequenceEqual(bytes.Take(fileSignature.SignatureBytes.Length))) + return archiveType; + } + } + } + catch (DirectoryNotFoundException) + { + Debug.LogWarning($"File '{filePath}' exists, but could not be opened for reading. Please make sure the project path lengths are not too long for the Operating System"); + } + + return ArchiveType.None; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs.meta new file mode 100644 index 00000000..744f983f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 695ed79ad88c3b44b8ae41b650ebe16c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/FileSignatureUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs new file mode 100644 index 00000000..fba268ce --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class MeshUtilityService : IMeshUtilityService + { + public IEnumerable GetCustomMeshesInObject(GameObject obj) + { + var meshes = new List(); + + var meshFilters = obj.GetComponentsInChildren(true); + var skinnedMeshes = obj.GetComponentsInChildren(true); + + meshes.AddRange(meshFilters.Select(m => m.sharedMesh)); + meshes.AddRange(skinnedMeshes.Select(m => m.sharedMesh)); + + meshes = meshes.Where(m => AssetDatabase.GetAssetPath(m).StartsWith("Assets/") || + AssetDatabase.GetAssetPath(m).StartsWith("Packages/")).ToList(); + + return meshes; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs.meta new file mode 100644 index 00000000..5f404712 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 307f5dd7be983e246adbda52ac50ecf3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/MeshUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs new file mode 100644 index 00000000..b0189914 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs @@ -0,0 +1,147 @@ +#if !UNITY_2022_2_OR_NEWER +using System; +using System.Reflection; +#endif +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +#if UNITY_2022_2_OR_NEWER +using UnityEditor.AssetImporters; +#endif +using UnityEngine; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class ModelUtilityService : IModelUtilityService + { + private IAssetUtilityService _assetUtility; + +#if !UNITY_2022_2_OR_NEWER + // Rig fields + private const string RigImportWarningsField = "m_RigImportWarnings"; + private const string RigImportErrorsField = "m_RigImportErrors"; + + // Animation fields + private const string AnimationImportWarningsField = "m_AnimationImportWarnings"; + private const string AnimationImportErrorsField = "m_AnimationImportErrors"; + + private static Editor _modelImporterEditor = null; +#endif + + public ModelUtilityService(IAssetUtilityService assetUtility) + { + _assetUtility = assetUtility; + } + + public Dictionary> GetImportLogs(params Object[] models) + { +#if UNITY_2022_2_OR_NEWER + return GetImportLogsDefault(models); +#else + return GetImportLogsLegacy(models); +#endif + } + +#if UNITY_2022_2_OR_NEWER + private Dictionary> GetImportLogsDefault(params Object[] models) + { + var modelsWithLogs = new Dictionary>(); + + foreach (var model in models) + { + var modelLogs = new List(); + + var importLog = AssetImporter.GetImportLog(_assetUtility.ObjectToAssetPath(model)); + + if (importLog == null) + continue; + + var entries = importLog.logEntries.Where(x => x.flags.HasFlag(ImportLogFlags.Warning) || x.flags.HasFlag(ImportLogFlags.Error)); + foreach (var entry in entries) + { + var severity = entry.flags.HasFlag(ImportLogFlags.Error) ? LogType.Error : LogType.Warning; + modelLogs.Add(new LogEntry() { Message = entry.message, Severity = severity }); + } + + if (modelLogs.Count > 0) + modelsWithLogs.Add(model, modelLogs); + } + + return modelsWithLogs; + } +#endif + +#if !UNITY_2022_2_OR_NEWER + private Dictionary> GetImportLogsLegacy(params Object[] models) + { + var modelsWithLogs = new Dictionary>(); + + foreach (var model in models) + { + var modelLogs = new List(); + + // Load the Model Importer + var modelImporter = _assetUtility.GetAssetImporter(model) as ModelImporter; + + var editorAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.GetName().Name.Equals("UnityEditor")); + + var modelImporterEditorType = editorAssembly.GetType("UnityEditor.ModelImporterEditor"); + + // Load its Model Importer Editor + Editor.CreateCachedEditorWithContext(new Object[] { modelImporter }, model, modelImporterEditorType, ref _modelImporterEditor); + + // Find the base type + var modelImporterEditorTypeBase = _modelImporterEditor.GetType().BaseType; + + // Get the tabs value + var tabsArrayType = modelImporterEditorTypeBase.GetRuntimeProperties().FirstOrDefault(x => x.Name == "tabs"); + var tabsArray = (Array)tabsArrayType.GetValue(_modelImporterEditor); + + // Get the tabs (Model | Rig | Animation | Materials) + var rigTab = tabsArray.GetValue(1); + var animationTab = tabsArray.GetValue(2); + + var rigErrorsCheckSuccess = CheckFieldForSerializedProperty(rigTab, RigImportErrorsField, out var rigErrors); + var rigWarningsCheckSuccess = CheckFieldForSerializedProperty(rigTab, RigImportWarningsField, out var rigWarnings); + var animationErrorsCheckSuccess = CheckFieldForSerializedProperty(animationTab, AnimationImportErrorsField, out var animationErrors); + var animationWarningsCheckSuccess = CheckFieldForSerializedProperty(animationTab, AnimationImportWarningsField, out var animationWarnings); + + if (!rigErrorsCheckSuccess || !rigWarningsCheckSuccess || !animationErrorsCheckSuccess || !animationWarningsCheckSuccess) + UnityEngine.Debug.LogWarning($"An error was encountered when checking import logs for model '{model.name}'"); + + if (!string.IsNullOrEmpty(rigWarnings)) + modelLogs.Add(new LogEntry() { Message = rigWarnings, Severity = LogType.Warning }); + if (!string.IsNullOrEmpty(rigErrors)) + modelLogs.Add(new LogEntry() { Message = rigErrors, Severity = LogType.Error }); + if (!string.IsNullOrEmpty(animationWarnings)) + modelLogs.Add(new LogEntry() { Message = animationWarnings, Severity = LogType.Warning }); + if (!string.IsNullOrEmpty(animationErrors)) + modelLogs.Add(new LogEntry() { Message = animationErrors, Severity = LogType.Error }); + + if (modelLogs.Count > 0) + modelsWithLogs.Add(model, modelLogs); + } + + return modelsWithLogs; + } + + private static bool CheckFieldForSerializedProperty(object source, string propertyName, out string message) + { + message = string.Empty; + + try + { + var propertyType = source.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); + var propertyValue = propertyType.GetValue(source) as SerializedProperty; + message = propertyValue.stringValue; + return true; + } + catch + { + return false; + } + } +#endif + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs.meta new file mode 100644 index 00000000..2db45203 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c50ca4c87e66f1b478279e5d1db4a08e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ModelUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs new file mode 100644 index 00000000..ec7a43b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs @@ -0,0 +1,26 @@ +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class SceneUtilityService : ISceneUtilityService + { + public string CurrentScenePath => SceneManager.GetActiveScene().path; + + public Scene OpenScene(string scenePath) + { + EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); + if (string.IsNullOrEmpty(scenePath) || AssetDatabase.LoadAssetAtPath(scenePath) == null) + return EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + else + return EditorSceneManager.OpenScene(scenePath); + } + + public GameObject[] GetRootGameObjects() + { + return SceneManager.GetSceneByPath(CurrentScenePath).GetRootGameObjects(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs.meta new file mode 100644 index 00000000..e88be26f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 53e8deb0ebfb7ea47956f3a859580cd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/SceneUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs new file mode 100644 index 00000000..2e85c2a4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs @@ -0,0 +1,658 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using UnityEditor; +using Object = UnityEngine.Object; + +namespace AssetStoreTools.Validator.Services.Validation +{ + internal class ScriptUtilityService : IScriptUtilityService + { + private const int ScriptTimeoutMs = 10000; + private const string IgnoredAssemblyCharacters = "!@#$%^*&()-+=[]{}\\|;:'\",.<>/?"; + + /// + /// For a given list of script assets, retrieves a list of types and their namespaces + /// + /// + /// A dictionary mapping each script asset with a list of its types. + /// The type tuple contains a name (e.g. class MyClass) and its namespace (e.g. MyNamespace) + /// + public IReadOnlyDictionary> GetTypeNamespacesFromScriptAssets(IList monoScripts) + { + var typesAndNamespaces = new Dictionary>(); + var typeInfos = GetTypeInfosFromScriptAssets(monoScripts); + + foreach (var kvp in typeInfos) + { + var namespacesInScript = new List<(string Name, string Namespace)>(); + foreach (var typeInfo in kvp.Value) + { + bool isValidType = typeInfo.TypeName == ScriptParser.TypeName.Class || typeInfo.TypeName == ScriptParser.TypeName.Struct || + typeInfo.TypeName == ScriptParser.TypeName.Interface || typeInfo.TypeName == ScriptParser.TypeName.Enum; + + if (isValidType) + namespacesInScript.Add(($"{typeInfo.TypeName.ToString().ToLower()} {typeInfo.Name}", typeInfo.Namespace)); + } + + typesAndNamespaces.Add(kvp.Key, namespacesInScript); + } + + return typesAndNamespaces; + } + + /// + /// Scans the given precompiled assembly assets to retrieve a list of their contained types + /// + /// + /// A dictionary mapping each precompiled assembly asset with a list of System.Type objects. + public IReadOnlyDictionary> GetTypesFromAssemblies(IList assemblies) + { + var dllPaths = assemblies.ToDictionary(t => AssetDatabase.GetAssetPath(t), t => t); + var types = new ConcurrentDictionary>(); + var failedDllPaths = new ConcurrentBag(); + + var allAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + + Parallel.ForEach(dllPaths.Keys, + (assemblyPath) => + { + try + { + var assembly = allAssemblies.FirstOrDefault(x => Path.GetFullPath(x.Location).Equals(Path.GetFullPath(assemblyPath), StringComparison.OrdinalIgnoreCase)); + if (assembly == null) + return; + + var assemblyTypes = assembly.GetTypes().Where(x => !IgnoredAssemblyCharacters.Any(c => x.Name.Contains(c))).ToList(); + types.TryAdd(dllPaths[assemblyPath], assemblyTypes); + } + catch + { + failedDllPaths.Add(assemblyPath); + } + }); + + if (failedDllPaths.Count > 0) + { + var message = new StringBuilder("The following precompiled assemblies could not be checked:"); + foreach (var path in failedDllPaths) + message.Append($"\n{path}"); + UnityEngine.Debug.LogWarning(message); + } + + // Types are sorted randomly due to parallelism, therefore need to be sorted before returning + var sortedTypes = dllPaths.Where(x => types.ContainsKey(x.Value)) + .Select(x => new KeyValuePair>(x.Value, types[x.Value])) + .ToDictionary(t => t.Key, t => t.Value); + + return sortedTypes; + } + + /// + /// Scans the given script assets to retrieve a list of their contained types + /// + /// + /// A dictionary mapping each precompiled assembly asset with a list of System.Type objects. + public IReadOnlyDictionary> GetTypesFromScriptAssets(IList monoScripts) + { + var realTypes = new Dictionary>(); + var typeInfos = GetTypeInfosFromScriptAssets(monoScripts); + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var kvp in typeInfos) + { + var realTypesInScript = new List(); + foreach (var typeInfo in kvp.Value) + { + bool isValidType = typeInfo.TypeName == ScriptParser.TypeName.Class || typeInfo.TypeName == ScriptParser.TypeName.Struct || + typeInfo.TypeName == ScriptParser.TypeName.Interface || typeInfo.TypeName == ScriptParser.TypeName.Enum; + + if (isValidType) + { + var realType = assemblies.Where(a => a.GetType(typeInfo.GetReflectionFriendlyFullName()) != null) + .Select(a => a.GetType(typeInfo.GetReflectionFriendlyFullName())).FirstOrDefault(); + if (realType != null) + realTypesInScript.Add(realType); + } + } + + realTypes.Add(kvp.Key, realTypesInScript); + } + + return realTypes; + } + + /// + /// Scans the given MonoScript assets to retrieve a list of their contained types + /// + /// + /// A dictionary mapping each script asset with a list of TypeInfo objects. + private IReadOnlyDictionary> GetTypeInfosFromScriptAssets(IList monoScripts) + { + var types = new ConcurrentDictionary>(); + var monoScriptContents = new Dictionary(); + var failedScripts = new ConcurrentBag(); + + // A separate dictionary is needed because MonoScript contents cannot be accessed outside of the main thread + foreach (var kvp in monoScripts) + monoScriptContents.Add(kvp, kvp.text); + + var tasks = new List>(); + + try + { + foreach (var kvp in monoScriptContents) + { + var cancellationTokenSource = new CancellationTokenSource(ScriptTimeoutMs); + + var task = Task.Run(() => + { + var parsingTask = new ScriptParser(cancellationTokenSource.Token); + var parsed = parsingTask.GetTypesInScript(kvp.Value, out IList parsedTypes); + if (parsed) + types.TryAdd(kvp.Key, parsedTypes); + else + failedScripts.Add(kvp.Key); + }); + + tasks.Add(new Tuple(task, cancellationTokenSource)); + } + + foreach (var t in tasks) + t.Item1.Wait(); + } + finally + { + foreach (var t in tasks) + t.Item2.Dispose(); + } + + if (failedScripts.Count > 0) + { + var message = new StringBuilder("The following scripts could not be checked:"); + foreach (var s in failedScripts) + message.Append($"\n{AssetDatabase.GetAssetPath(s)}"); + UnityEngine.Debug.LogWarning(message); + } + + // Types are sorted randomly due to parallelism, therefore need to be sorted before returning + var sortedTypes = monoScriptContents.Where(x => types.ContainsKey(x.Key)) + .Select(x => new KeyValuePair>(x.Key, types[x.Key])) + .ToDictionary(t => t.Key, t => t.Value); + + return sortedTypes; + } + + /// + /// A simple script parser class to detect types declared within a script + /// + private class ScriptParser + { + /// + /// Types that can be identified by the script parser + /// + public enum TypeName + { + Undefined, + Namespace, + Class, + Struct, + Interface, + Enum, + IdentationStart, + IdentationEnd + } + + /// + /// A class containing information about each block of a C# script + /// + /// A block in this context is defined as script text that is contained within curly brackets. + /// If it's a type, it may have a preceding name and a namespace + /// + public class BlockInfo + { + public TypeName TypeName = TypeName.Undefined; + public string Name = string.Empty; + public string FullName = string.Empty; + public string Namespace = string.Empty; + public int FoundIndex; + public int StartIndex; + + public BlockInfo ParentBlock; + + public string GetReflectionFriendlyFullName() + { + StringBuilder sb = new StringBuilder(FullName); + for (int i = sb.Length - 1; i >= Namespace.Length + 1; i--) + if (sb[i] == '.') + sb[i] = '+'; + + return sb.ToString(); + } + } + + private CancellationToken _token; + + public ScriptParser(CancellationToken token) + { + _token = token; + } + + public bool GetTypesInScript(string text, out IList types) + { + types = null; + + try + { + var sanitized = SanitizeScript(text); + types = ScanForTypes(sanitized); + return true; + } + catch + { + return false; + } + } + + private string SanitizeScript(string source) + { + var sb = new StringBuilder(source); + + // Remove comments and strings + sb = RemoveStringsAndComments(sb); + + // Replace newlines with spaces + sb.Replace("\r", " ").Replace("\n", " "); + + // Space out the brackets + sb.Replace("{", " { ").Replace("}", " } "); + + // Insert a space at the start for more convenient parsing + sb.Insert(0, " "); + + // Remove repeating spaces + var sanitized = Regex.Replace(sb.ToString(), @"\s{2,}", " "); + + return sanitized; + } + + private StringBuilder RemoveStringsAndComments(StringBuilder sb) + { + void CheckStringIdentifiers(int index, out bool isVerbatim, out bool isInterpolated) + { + isVerbatim = false; + isInterpolated = false; + + string precedingChars = string.Empty; + for (int i = index - 1; i >= 0; i--) + { + if (sb[i] == ' ') + break; + precedingChars += sb[i]; + } + + if (precedingChars.Contains("@")) + isVerbatim = true; + if (precedingChars.Contains("$")) + isInterpolated = true; + } + + bool IsRegion(int index) + { + if (sb.Length - index < "#region".Length) + return false; + if (sb[index] == '#' && sb[index + 1] == 'r' && sb[index + 2] == 'e' && sb[index + 3] == 'g' && sb[index + 4] == 'i' && + sb[index + 5] == 'o' && sb[index + 6] == 'n') + return true; + return false; + } + + var removeRanges = new List>(); + + for (int i = 0; i < sb.Length; i++) + { + _token.ThrowIfCancellationRequested(); + + // Comment code + if (sb[i] == '/') + { + if (sb[i + 1] == '/') + { + for (int j = i + 1; j < sb.Length; j++) + { + _token.ThrowIfCancellationRequested(); + if (sb[j] == '\n' || j == sb.Length - 1) + { + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j; + break; + } + } + } + else if (sb[i + 1] == '*') + { + for (int j = i + 2; j < sb.Length; j++) + { + _token.ThrowIfCancellationRequested(); + if (sb[j] == '/' && sb[j - 1] == '*') + { + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j + 1; + break; + } + } + } + } + // Char code + else if (sb[i] == '\'') + { + for (int j = i + 1; j < sb.Length; j++) + { + _token.ThrowIfCancellationRequested(); + if (sb[j] == '\'') + { + if (sb[j - 1] == '\\') + { + int slashCount = 0; + int k = j - 1; + while (sb[k--] == '\\') + slashCount++; + if (slashCount % 2 != 0) + continue; + } + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j; + break; + } + } + } + // String code + else if (sb[i] == '"') + { + if (sb[i - 1] == '\'' && sb[i + 1] == '\'' || (sb[i - 2] == '\'' && sb[i - 1] == '\\' && sb[i + 1] == '\'')) + continue; + + CheckStringIdentifiers(i, out bool isVerbatim, out bool isInterpolated); + + var bracketCount = 0; + bool interpolationEnd = true; + for (int j = i + 1; j < sb.Length; j++) + { + _token.ThrowIfCancellationRequested(); + if (isInterpolated && (sb[j] == '{' || sb[j] == '}')) + { + if (sb[j] == '{') + { + if (sb[j + 1] != '{') + bracketCount++; + else + j += 1; + } + else if (sb[j] == '}') + { + if (sb[j + 1] != '}') + bracketCount--; + else + j += 1; + } + + if (bracketCount == 0) + interpolationEnd = true; + else + interpolationEnd = false; + + continue; + } + + if (sb[j] == '\"') + { + if (isVerbatim) + { + if (sb[j + 1] != '\"') + { + if (!isInterpolated || isInterpolated && interpolationEnd == true) + { + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j + 1; + break; + } + } + else + j += 1; + } + else + { + bool endOfComment = false; + if (sb[j - 1] != '\\') + endOfComment = true; + else + { + int slashCount = 0; + int k = j - 1; + while (sb[k--] == '\\') + slashCount++; + if (slashCount % 2 == 0) + endOfComment = true; + } + + if (!isInterpolated && endOfComment || (isInterpolated && interpolationEnd && endOfComment)) + { + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j + 1; + break; + } + } + } + } + } + // Region code + else if (IsRegion(i)) + { + i += "#region".Length; + for (int j = i; j < sb.Length; j++) + { + _token.ThrowIfCancellationRequested(); + if (sb[j] == '\n') + { + removeRanges.Add(new Tuple(i, j - i + 1)); + i = j; + break; + } + } + } + } + + for (int i = removeRanges.Count - 1; i >= 0; i--) + sb = sb.Remove(removeRanges[i].Item1, removeRanges[i].Item2); + + return sb; + } + + private IList ScanForTypes(string script) + { + var typeList = new SortedList(); + BlockInfo currentActiveBlock = new BlockInfo(); + + int i = 0; + + BlockInfo nextNamespace = null; + BlockInfo nextClass = null; + BlockInfo nextStruct = null; + BlockInfo nextInterface = null; + BlockInfo nextEnum = null; + + while (i < script.Length) + { + _token.ThrowIfCancellationRequested(); + if (nextNamespace == null) + nextNamespace = FindNextTypeBlock(script, i, TypeName.Namespace); + if (nextClass == null) + nextClass = FindNextTypeBlock(script, i, TypeName.Class); + if (nextStruct == null) + nextStruct = FindNextTypeBlock(script, i, TypeName.Struct); + if (nextInterface == null) + nextInterface = FindNextTypeBlock(script, i, TypeName.Interface); + if (nextEnum == null) + nextEnum = FindNextTypeBlock(script, i, TypeName.Enum); + + var nextIdentationIncrease = FindNextTypeBlock(script, i, TypeName.IdentationStart); + var nextIdentationDecrease = FindNextTypeBlock(script, i, TypeName.IdentationEnd); + + if (!TryFindClosestBlock(out var closestBlock, nextNamespace, nextClass, + nextStruct, nextInterface, nextEnum, nextIdentationIncrease, nextIdentationDecrease)) + break; + + switch (closestBlock) + { + case var _ when closestBlock == nextIdentationIncrease: + closestBlock.ParentBlock = currentActiveBlock; + currentActiveBlock = closestBlock; + break; + case var _ when closestBlock == nextIdentationDecrease: + if (currentActiveBlock.TypeName != TypeName.Undefined) + typeList.Add(currentActiveBlock.StartIndex, currentActiveBlock); + currentActiveBlock = currentActiveBlock.ParentBlock; + break; + case var _ when closestBlock == nextNamespace: + closestBlock.Namespace = currentActiveBlock.TypeName == TypeName.Namespace ? currentActiveBlock.FullName : currentActiveBlock.Namespace; + closestBlock.FullName = string.IsNullOrEmpty(currentActiveBlock.FullName) ? closestBlock.Name : $"{currentActiveBlock.FullName}.{closestBlock.Name}"; + closestBlock.ParentBlock = currentActiveBlock; + currentActiveBlock = closestBlock; + nextNamespace = null; + break; + case var _ when closestBlock == nextClass: + case var _ when closestBlock == nextStruct: + case var _ when closestBlock == nextInterface: + case var _ when closestBlock == nextEnum: + closestBlock.FullName = string.IsNullOrEmpty(currentActiveBlock.FullName) ? closestBlock.Name : $"{currentActiveBlock.FullName}.{closestBlock.Name}"; + closestBlock.Namespace = currentActiveBlock.TypeName == TypeName.Namespace ? currentActiveBlock.FullName : currentActiveBlock.Namespace; + closestBlock.ParentBlock = currentActiveBlock; + currentActiveBlock = closestBlock; + switch (closestBlock) + { + case var _ when closestBlock == nextClass: + nextClass = null; + break; + case var _ when closestBlock == nextStruct: + nextStruct = null; + break; + case var _ when closestBlock == nextInterface: + nextInterface = null; + break; + case var _ when closestBlock == nextEnum: + nextEnum = null; + break; + } + break; + } + + i = closestBlock.StartIndex; + } + + return typeList.Select(x => x.Value).ToList(); + } + + private bool TryFindClosestBlock(out BlockInfo closestBlock, params BlockInfo[] blocks) + { + closestBlock = null; + for (int i = 0; i < blocks.Length; i++) + { + if (blocks[i].FoundIndex == -1) + continue; + + if (closestBlock == null || closestBlock.FoundIndex > blocks[i].FoundIndex) + closestBlock = blocks[i]; + } + + return closestBlock != null; + } + + private BlockInfo FindNextTypeBlock(string text, int startIndex, TypeName blockType) + { + string typeKeyword; + switch (blockType) + { + case TypeName.Namespace: + typeKeyword = "namespace"; + break; + case TypeName.Class: + typeKeyword = "class"; + break; + case TypeName.Struct: + typeKeyword = "struct"; + break; + case TypeName.Interface: + typeKeyword = "interface"; + break; + case TypeName.Enum: + typeKeyword = "enum"; + break; + case TypeName.IdentationStart: + var identationStart = text.IndexOf("{", startIndex); + return new BlockInfo() { FoundIndex = identationStart, StartIndex = identationStart + 1, TypeName = TypeName.Undefined }; + case TypeName.IdentationEnd: + var identationEnd = text.IndexOf("}", startIndex); + return new BlockInfo() { FoundIndex = identationEnd, StartIndex = identationEnd + 1, TypeName = TypeName.Undefined }; + default: + throw new ArgumentException("Invalid block type provided"); + } + + int start = -1; + int blockStart = -1; + string name = string.Empty; + while (startIndex < text.Length) + { + _token.ThrowIfCancellationRequested(); + start = text.IndexOf($" {typeKeyword} ", startIndex); + if (start == -1) + return new BlockInfo { FoundIndex = -1 }; + + // Check if the caught type keyword matches the type definition + var openingBracket = text.IndexOf("{", start); + if (openingBracket == -1) + return new BlockInfo { FoundIndex = -1 }; + + var declaration = text.Substring(start, openingBracket - start); + var split = declaration.Split(' '); + + // Namespace detection + if (typeKeyword == "namespace") + { + // Expected result: [null] [namespace] [null] + if (split.Length == 4) + { + name = split[2]; + blockStart = openingBracket + 1; + break; + } + else + startIndex = openingBracket + 1; + } + // Class, Interface, Struct, Enum detection + else + { + // Expected result: [null] [keywordName] [typeName] ... [null] + // Skip any keywords that only contains [null] [keywordName] [null] + if (split.Length != 3) + { + name = split[2]; + blockStart = openingBracket + 1; + break; + } + else + startIndex = openingBracket + 1; + } + } + + var info = new BlockInfo() { FoundIndex = start, StartIndex = blockStart, Name = name, TypeName = blockType }; + return info; + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs.meta new file mode 100644 index 00000000..d89e8d7c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9db4298044e2add44bc3aa6ba898d7c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/Validation/ScriptUtilityService.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs new file mode 100644 index 00000000..0407f8ff --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs @@ -0,0 +1,24 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.Services.Validation; + +namespace AssetStoreTools.Validator.Services +{ + internal class ValidatorServiceProvider : ServiceProvider + { + public static ValidatorServiceProvider Instance => _instance ?? (_instance = new ValidatorServiceProvider()); + private static ValidatorServiceProvider _instance; + + private ValidatorServiceProvider() { } + + protected override void RegisterServices() + { + Register(); + Register(); + Register(); + Register(); + Register(); + Register(); + Register(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs.meta new file mode 100644 index 00000000..888d94f7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 47ac495c61171824abb2b72b1b7ef676 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Services/ValidatorServiceProvider.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions.meta new file mode 100644 index 00000000..7b3ebc2b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 462cf5f916fad974a831f6a44aadcc82 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs new file mode 100644 index 00000000..fa49d8c5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs @@ -0,0 +1,121 @@ +ο»Ώusing AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal class AutomatedTest : ValidationTest + { + public AutomatedTest(ValidationTestScriptableObject source) : base(source) { } + + public override void Run(ITestConfig config) + { + Type testClass = null; + MethodInfo testMethod = null; + + try + { + ValidateTestMethod(ref testClass, ref testMethod); + ValidateConfig(config); + } + catch (Exception e) + { + Debug.LogError(e.Message); + return; + } + + object testClassInstance; + try + { + testClassInstance = CreateInstance(testClass, config); + } + catch (Exception e) + { + Debug.LogError($"Could not create an instance of class {testClass}:\n{e}"); + return; + } + + try + { + Result = (TestResult)testMethod.Invoke(testClassInstance, new object[0]); + } + catch (Exception e) + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + result.AddMessage("An exception was caught when running this test case. See Console for more details"); + Debug.LogError($"An exception was caught when running validation for test case '{Title}'\n{e}"); + Result = result; + } + } + + private void ValidateTestMethod(ref Type testClass, ref MethodInfo testMethod) + { + if (TestScript == null || (testClass = TestScript.GetClass()) == null) + throw new Exception($"Cannot run test {Title} - Test Script class was not found"); + + var interfaces = testClass.GetInterfaces(); + if (!interfaces.Contains(typeof(ITestScript))) + throw new Exception($"Cannot run test {Title} - Test Script class is not derived from {nameof(ITestScript)}"); + + testMethod = testClass.GetMethod("Run"); + if (testMethod == null) + throw new Exception($"Cannot run test {Title} - Run() method was not found"); + } + + private void ValidateConfig(ITestConfig config) + { + switch (ValidationType) + { + case ValidationType.Generic: + case ValidationType.UnityPackage: + if (config is GenericTestConfig) + return; + break; + default: + throw new NotImplementedException("Undefined validation type"); + } + + throw new Exception("Config does not match the validation type"); + } + + private object CreateInstance(Type testClass, ITestConfig testConfig) + { + var constructors = testClass.GetConstructors(); + if (constructors.Length != 1) + throw new Exception($"Test class {testClass} should only contain a single constructor"); + + var constructor = constructors[0]; + var expectedParameters = constructor.GetParameters(); + var parametersToUse = new List(); + foreach (var expectedParam in expectedParameters) + { + var paramType = expectedParam.ParameterType; + + if (paramType == testConfig.GetType()) + { + parametersToUse.Add(testConfig); + continue; + } + + if (typeof(IValidatorService).IsAssignableFrom(paramType)) + { + var matchingService = ValidatorServiceProvider.Instance.GetService(paramType); + if (matchingService == null) + throw new Exception($"Service {paramType} is not registered and could not be retrieved"); + + parametersToUse.Add(matchingService); + continue; + } + + throw new Exception($"Invalid parameter type: {paramType}"); + } + + var instance = constructor.Invoke(parametersToUse.ToArray()); + return instance; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs.meta new file mode 100644 index 00000000..c3fca08a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b284048af6fef0d49b8c3a37f7083d04 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/AutomatedTest.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs new file mode 100644 index 00000000..22dfedfd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs @@ -0,0 +1,7 @@ +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal class GenericTestConfig : ITestConfig + { + public string[] ValidationPaths { get; set; } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs.meta new file mode 100644 index 00000000..00f3efac --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ba1ae4e7b45a6c84ca8ad0eb391bf95d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/GenericTestConfig.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs new file mode 100644 index 00000000..5db2e328 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs @@ -0,0 +1,4 @@ +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal interface ITestConfig { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs.meta new file mode 100644 index 00000000..9bfe992d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c7e57766d04022c4dac58caf8ebe339a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestConfig.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs new file mode 100644 index 00000000..e705ab8b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs @@ -0,0 +1,9 @@ +ο»Ώusing AssetStoreTools.Validator.Data; + +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal interface ITestScript + { + TestResult Run(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs.meta new file mode 100644 index 00000000..e2246b18 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 839ef1f3e773ab347b66932d3f810aec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ITestScript.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects.meta new file mode 100644 index 00000000..1dfe2af7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d62652f91f698904ea662c6ab252ea59 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs new file mode 100644 index 00000000..31e64989 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs @@ -0,0 +1,11 @@ +ο»Ώ#if UNITY_ASTOOLS_DEVELOPMENT +using UnityEngine; +#endif + +namespace AssetStoreTools.Validator.TestDefinitions +{ +#if UNITY_ASTOOLS_DEVELOPMENT + [CreateAssetMenu(fileName = "AutomatedTest", menuName = "Asset Store Validator/Automated Test")] +#endif + internal class AutomatedTestScriptableObject : ValidationTestScriptableObject { } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs.meta new file mode 100644 index 00000000..bd737f4d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/AutomatedTestScriptableObject.cs.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: d813ff809ae82f643bf975031305d541 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable + Objects/AutomatedTestScriptableObject.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor.meta new file mode 100644 index 00000000..eebb8673 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7cd52466a2239344d90c3043b7afc1e4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs new file mode 100644 index 00000000..5b283899 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs @@ -0,0 +1,196 @@ +ο»Ώusing AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Utility; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestDefinitions +{ + [CustomEditor(typeof(ValidationTestScriptableObject), true)] + internal class ValidationTestScriptableObjectInspector : UnityEditor.Editor + { + private enum FilterSeverity + { + Warning, + Fail + } + + private enum FilterType + { + UseFilter, + ExcludeFilter + } + + private ValidationTestScriptableObject _data; + private ValidationTestScriptableObject[] _allObjects; + + private SerializedProperty _script; + private SerializedProperty _validationType; + + private SerializedProperty _testScript; + private SerializedProperty _category; + private SerializedProperty _failFilterProperty; + private SerializedProperty _isInclusiveProperty; + private SerializedProperty _appliesToSubCategories; + private SerializedProperty _categoryFilter; + + private bool _hadChanges; + + private void OnEnable() + { + if (target == null) return; + + _data = target as ValidationTestScriptableObject; + + _script = serializedObject.FindProperty("m_Script"); + + _validationType = serializedObject.FindProperty(nameof(ValidationTestScriptableObject.ValidationType)); + + _testScript = serializedObject.FindProperty(nameof(ValidationTestScriptableObject.TestScript)); + _category = serializedObject.FindProperty(nameof(ValidationTestScriptableObject.CategoryInfo)); + _failFilterProperty = _category.FindPropertyRelative(nameof(ValidationTestScriptableObject.CategoryInfo.IsFailFilter)); + _isInclusiveProperty = _category.FindPropertyRelative(nameof(ValidationTestScriptableObject.CategoryInfo.IsInclusiveFilter)); + _appliesToSubCategories = _category.FindPropertyRelative(nameof(ValidationTestScriptableObject.CategoryInfo.AppliesToSubCategories)); + _categoryFilter = _category.FindPropertyRelative(nameof(ValidationTestScriptableObject.CategoryInfo.Filter)); + + _allObjects = ValidatorUtility.GetAutomatedTestCases(ValidatorUtility.SortType.Id); + _hadChanges = false; + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUILayout.LabelField(GetInspectorTitle(), new GUIStyle(EditorStyles.centeredGreyMiniLabel) { fontSize = 24 }, GUILayout.MinHeight(50)); + + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.PropertyField(_script); + + EditorGUI.BeginChangeCheck(); + // ID field + EditorGUILayout.IntField("Test Id", _data.Id); + if (!ValidateID()) + EditorGUILayout.HelpBox("ID is already in use", MessageType.Warning); + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.Space(8); + EditorGUILayout.LabelField("Test Data", new GUIStyle(EditorStyles.centeredGreyMiniLabel) { alignment = TextAnchor.MiddleLeft, fontSize = 14, padding = new RectOffset(0, 0, 0, 0) }); + + // Validation Type + var validationType = (ValidationType)EditorGUILayout.EnumPopup("Validation Type", (ValidationType)_validationType.enumValueIndex); + _validationType.enumValueIndex = (int)validationType; + + // Other fields + _data.Title = EditorGUILayout.TextField("Title", _data.Title); + if (string.IsNullOrEmpty(_data.Title)) + EditorGUILayout.HelpBox("Title cannot be empty", MessageType.Warning); + + EditorGUILayout.LabelField("Description"); + GUIStyle myTextAreaStyle = new GUIStyle(EditorStyles.textArea) { wordWrap = true }; + _data.Description = EditorGUILayout.TextArea(_data.Description, myTextAreaStyle); + + // Test script + EditorGUILayout.Space(8); + EditorGUILayout.LabelField("Test Script", new GUIStyle(EditorStyles.centeredGreyMiniLabel) { alignment = TextAnchor.MiddleLeft, fontSize = 14, padding = new RectOffset(0, 0, 0, 0) }); + + EditorGUILayout.PropertyField(_testScript); + if (_testScript.objectReferenceValue != null) + { + var generatedScriptType = (_testScript.objectReferenceValue as MonoScript).GetClass(); + if (generatedScriptType == null || !generatedScriptType.GetInterfaces().Contains(typeof(ITestScript))) + EditorGUILayout.HelpBox($"Test Script does not derive from {nameof(ITestScript)}. Test execution will fail", MessageType.Warning); + } + else if (!string.IsNullOrEmpty(_data.Title)) + { + var generatedScriptName = GenerateTestScriptName(); + EditorGUILayout.LabelField($"Proposed script name: {generatedScriptName}.cs", new GUIStyle("Label") { richText = true }); + EditorGUILayout.Space(); + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Generate Test Method Script", GUILayout.MaxWidth(200f))) + { + var generatedScript = ValidatorUtility.GenerateTestScript(generatedScriptName, (ValidationType)_validationType.enumValueIndex); + _testScript.objectReferenceValue = generatedScript; + } + EditorGUILayout.EndHorizontal(); + } + + // Variable Sevetity Options + EditorGUILayout.Space(8); + EditorGUILayout.LabelField("Variable Severity Status Filtering", new GUIStyle(EditorStyles.centeredGreyMiniLabel) { alignment = TextAnchor.MiddleLeft, fontSize = 14, padding = new RectOffset(0, 0, 0, 0) }); + + var filterSeverity = (FilterSeverity)EditorGUILayout.EnumPopup("Fail Type", _failFilterProperty.boolValue ? FilterSeverity.Fail : FilterSeverity.Warning); + _failFilterProperty.boolValue = filterSeverity == FilterSeverity.Fail ? true : false; + var filterType = (FilterType)EditorGUILayout.EnumPopup("Filtering rule", _isInclusiveProperty.boolValue ? FilterType.UseFilter : FilterType.ExcludeFilter); + _isInclusiveProperty.boolValue = filterType == FilterType.UseFilter ? true : false; + + EditorGUILayout.PropertyField(_appliesToSubCategories); + + EditorGUILayout.Space(10); + + EditorGUILayout.BeginHorizontal(GUI.skin.FindStyle("HelpBox")); + EditorGUILayout.LabelField(GetFilterDescription(_failFilterProperty.boolValue, _isInclusiveProperty.boolValue), new GUIStyle(GUI.skin.label) { wordWrap = true, richText = true }); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(10); + + EditorGUILayout.PropertyField(_categoryFilter); + + if (EditorGUI.EndChangeCheck()) + { + EditorUtility.SetDirty(target); + _hadChanges = true; + } + + _hadChanges = serializedObject.ApplyModifiedProperties() || _hadChanges; + } + + private string GetInspectorTitle() + { + switch (_data) + { + case AutomatedTestScriptableObject _: + return "Automated Test"; + default: + return "Miscellaneous Test"; + } + } + + private string GenerateTestScriptName() + { + var name = _data.Title.Replace(" ", ""); + return name; + } + + private string GetFilterDescription(bool isFailFilter, bool isInclusive) + { + string text = $"When a {TestResultStatus.VariableSeverityIssue} result type is returned from the test method:\n\n"; + if (isFailFilter) + { + if (isInclusive) + return text + "β€’ Categories IN the filter will result in a FAIL.\nβ€’ Categories NOT in the filter will result in a WARNING"; + else + return text + "β€’ Categories NOT in the filter will result in a FAIL.\nβ€’ Categories IN the filter will result in a WARNING"; + } + else + { + if (isInclusive) + return text + "β€’ Categories IN the filter will result in a WARNING.\nβ€’ Categories NOT in the filter will result in a FAIL"; + else + return text + "β€’ Categories NOT in the filter will result in a WARNING.\nβ€’ Categories IN the filter will result in a FAIL"; + } + } + + private bool ValidateID() + { + return !_allObjects.Any(x => x.Id == _data.Id && x != _data); + } + + private void OnDisable() + { + if (!_hadChanges) return; + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs.meta new file mode 100644 index 00000000..ad96ec9d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/Editor/ValidationTestScriptableObjectInspector.cs.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: 06d76b0e6df91eb43ac956f883c4a2da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable + Objects/Editor/ValidationTestScriptableObjectInspector.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs new file mode 100644 index 00000000..9c2a29f9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs @@ -0,0 +1,35 @@ +using AssetStoreTools.Validator.Categories; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Utility; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal abstract class ValidationTestScriptableObject : ScriptableObject + { + [SerializeField, HideInInspector] + private bool HasBeenInitialized; + + public int Id; + public string Title; + public string Description; + public ValidatorCategory CategoryInfo; + public ValidationType ValidationType; + public MonoScript TestScript; + + private void OnEnable() + { + // To do: maybe replace with Custom Inspector + if (HasBeenInitialized) + return; + + var existingTestCases = ValidatorUtility.GetAutomatedTestCases(ValidatorUtility.SortType.Id); + if (existingTestCases.Length > 0) + Id = existingTestCases[existingTestCases.Length - 1].Id + 1; + else + Id = 1; + HasBeenInitialized = true; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs.meta new file mode 100644 index 00000000..943d5d8e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable Objects/ValidationTestScriptableObject.cs.meta @@ -0,0 +1,19 @@ +fileFormatVersion: 2 +guid: 11c2422f057b75a458e184d169a00eb6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/Scriptable + Objects/ValidationTestScriptableObject.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs new file mode 100644 index 00000000..abb77f69 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs @@ -0,0 +1,38 @@ +ο»Ώusing AssetStoreTools.Validator.Categories; +using AssetStoreTools.Validator.Data; +using UnityEditor; + +namespace AssetStoreTools.Validator.TestDefinitions +{ + internal abstract class ValidationTest + { + public int Id; + public string Title; + public string Description; + public MonoScript TestScript; + + public ValidationType ValidationType; + public ValidatorCategory CategoryInfo; + + public TestResult Result; + + protected ValidationTest(ValidationTestScriptableObject source) + { + Id = source.Id; + Title = source.Title; + Description = source.Description; + TestScript = source.TestScript; + CategoryInfo = source.CategoryInfo; + ValidationType = source.ValidationType; + Result = new TestResult(); + } + + public abstract void Run(ITestConfig config); + + public string Slugify(string value) + { + string newValue = value.Replace(' ', '-').ToLower(); + return newValue; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs.meta new file mode 100644 index 00000000..a5cadef5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 095d629656748914bb6202598876fdf4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Definitions/ValidationTest.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods.meta new file mode 100644 index 00000000..5a3363e9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: daedaf78228b5184297e7ca334ea2a12 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic.meta new file mode 100644 index 00000000..a9b691ed --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ecfb23f95f16d2347a4063411aad8063 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs new file mode 100644 index 00000000..e7543b04 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs @@ -0,0 +1,64 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckAnimationClips : ITestScript + { + private static readonly string[] InvalidNames = new[] { "Take 001" }; + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckAnimationClips(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + var badModels = new Dictionary>(); + var models = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Model); + + foreach (var model in models) + { + var badClips = new List(); + var clips = AssetDatabase.LoadAllAssetsAtPath(_assetUtility.ObjectToAssetPath(model)); + foreach (var clip in clips) + { + if (InvalidNames.Any(x => x.ToLower().Equals(clip.name.ToLower()))) + { + badClips.Add(clip); + } + } + + if (badClips.Count > 0) + badModels.Add(model, badClips); + } + + if (badModels.Count > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following models have animation clips with invalid names. Animation clip names should be unique and reflective of the animation itself"); + foreach (var kvp in badModels) + { + result.AddMessage(_assetUtility.ObjectToAssetPath(kvp.Key), null, kvp.Value.ToArray()); + } + } + else + { + result.AddMessage("No animation clips with invalid names were found!"); + result.Status = TestResultStatus.Pass; + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs.meta new file mode 100644 index 00000000..3e273b61 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7a28985886f182c4bacc89a44777c742 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAnimationClips.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs new file mode 100644 index 00000000..6f960e92 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs @@ -0,0 +1,128 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckAudioClipping : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckAudioClipping(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + // How many peaks above threshold are required for Audio Clips to be considered clipping + const int TOLERANCE = 2; + // Min. amount of consecutive samples above threshold required for peak detection + const int PEAK_STEPS = 1; + // Clipping threshold. More lenient here than Submission Guidelines (-0.3db) due to the problematic nature of + // correctly determining how sensitive the audio clipping flagging should be, as well as to account for any + // distortion introduced when AudioClips are compresssed after importing to Unity. + const float THRESHOLD = -0.05f; + // Samples for 16-bit audio files + const float S16b = 32767f; + float clippingThreshold = (S16b - (S16b / (2 * Mathf.Log10(1 / S16b)) * THRESHOLD)) / S16b; + TestResult result = new TestResult(); + var clippingAudioClips = new Dictionary(); + + var losslessAudioClips = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.NonLossyAudio).Select(x => x as AudioClip).ToList(); + foreach (var clip in losslessAudioClips) + { + var path = AssetDatabase.GetAssetPath(clip.GetInstanceID()); + + if (IsClipping(clip, TOLERANCE, PEAK_STEPS, clippingThreshold)) + clippingAudioClips.Add(clip, path); + } + + var lossyAudioClips = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.LossyAudio).Select(x => x as AudioClip).ToList(); + foreach (var clip in lossyAudioClips) + { + var path = AssetDatabase.GetAssetPath(clip.GetInstanceID()); + + if (IsClipping(clip, TOLERANCE, PEAK_STEPS, clippingThreshold)) + clippingAudioClips.Add(clip, path); + } + + if (clippingAudioClips.Count > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following AudioClips are clipping or are very close to 0db ceiling. Please ensure your exported audio files have at least 0.3db of headroom (should peak at no more than -0.3db):", null, clippingAudioClips.Select(x => x.Key).ToArray()); + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No clipping audio files were detected."); + } + + return result; + } + + private bool IsClipping(AudioClip clip, int tolerance, int peakTolerance, float clippingThreshold) + { + if (DetectNumPeaksAboveThreshold(clip, peakTolerance, clippingThreshold) >= tolerance) + return true; + + return false; + } + + private int DetectNumPeaksAboveThreshold(AudioClip clip, int peakTolerance, float clippingThreshold) + { + float[] samples = new float[clip.samples * clip.channels]; + var data = clip.GetData(samples, 0); + + float[] samplesLeft = samples.Where((s, i) => i % 2 == 0).ToArray(); + float[] samplesRight = samples.Where((s, i) => i % 2 == 1).ToArray(); + + int peaks = 0; + + peaks = GetPeaksInChannel(samplesLeft, peakTolerance, clippingThreshold) + + GetPeaksInChannel(samplesRight, peakTolerance, clippingThreshold); + + return peaks; + } + + private int GetPeaksInChannel(float[] samples, int peakTolerance, float clippingThreshold) + { + int peaks = 0; + bool evalPeak = false; + int peakSteps = 0; + int step = 0; + + while (step < samples.Length) + { + if (Mathf.Abs(samples[step]) >= clippingThreshold && evalPeak) + { + peakSteps++; + } + + if (Mathf.Abs(samples[step]) >= clippingThreshold && !evalPeak) + { + evalPeak = true; + peakSteps++; + } + + if (Mathf.Abs(samples[step]) < clippingThreshold && evalPeak) + { + evalPeak = false; + if (peakSteps >= peakTolerance) + peaks++; + peakSteps = 0; + } + + step++; + } + + return peaks; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs.meta new file mode 100644 index 00000000..3d306388 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f604db0353da0cb46bb048f5cd37186f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckAudioClipping.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs new file mode 100644 index 00000000..5f4499b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs @@ -0,0 +1,55 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckColliders : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IMeshUtilityService _meshUtility; + + public CheckColliders(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility) + { + _config = config; + _assetUtility = assetUtility; + _meshUtility = meshUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var prefabs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Prefab); + var badPrefabs = new List(); + + foreach (var p in prefabs) + { + var meshes = _meshUtility.GetCustomMeshesInObject(p); + + if (!p.isStatic || !meshes.Any()) + continue; + + var colliders = p.GetComponentsInChildren(true); + if (!colliders.Any()) + badPrefabs.Add(p); + } + + if (badPrefabs.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found prefabs have colliders!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following prefabs contain meshes, but colliders were not found", null, badPrefabs.ToArray()); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs.meta new file mode 100644 index 00000000..f5f4edf4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 308b3d7b7a883b949a14f47cfd5c7ebe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckColliders.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs new file mode 100644 index 00000000..330c0175 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs @@ -0,0 +1,121 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckCompressedFiles : ITestScript + { + private enum ArchiveResult + { + Allowed, + NotAllowed, + TarGzWithIssues, + ZipWithIssues + } + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IFileSignatureUtilityService _fileSignatureUtility; + + public CheckCompressedFiles(GenericTestConfig config, IAssetUtilityService assetUtility, IFileSignatureUtilityService fileSignatureUtility) + { + _config = config; + _assetUtility = assetUtility; + _fileSignatureUtility = fileSignatureUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var checkedArchives = new Dictionary(); + + // Retrieving assets via GetObjectsFromAssets() is insufficient because + // archives might be renamed and not use the expected extension + var allAssetPaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.All); + + foreach (var assetPath in allAssetPaths) + { + ArchiveType archiveType; + if ((archiveType = _fileSignatureUtility.GetArchiveType(assetPath)) == ArchiveType.None) + continue; + + var archiveObj = _assetUtility.AssetPathToObject(assetPath); + + switch (archiveType) + { + case ArchiveType.TarGz: + if (assetPath.ToLower().EndsWith(".unitypackage")) + checkedArchives.Add(archiveObj, ArchiveResult.Allowed); + else + checkedArchives.Add(archiveObj, ArchiveResult.TarGzWithIssues); + break; + case ArchiveType.Zip: + if (FileNameContainsKeyword(assetPath, "source") && assetPath.ToLower().EndsWith(".zip")) + checkedArchives.Add(archiveObj, ArchiveResult.Allowed); + else + checkedArchives.Add(archiveObj, ArchiveResult.ZipWithIssues); + break; + default: + checkedArchives.Add(archiveObj, ArchiveResult.NotAllowed); + break; + } + } + + if (checkedArchives.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No archives were found in the package content!"); + return result; + } + + if (checkedArchives.Any(x => x.Value == ArchiveResult.Allowed)) + { + result.Status = TestResultStatus.Warning; + result.AddMessage("The following archives of allowed format were found in the package content.\n" + + "Please make sure they adhere to the nested archive guidelines:", null, + checkedArchives.Where(x => x.Value == ArchiveResult.Allowed).Select(x => x.Key).ToArray()); + } + + if (checkedArchives.Any(x => x.Value == ArchiveResult.TarGzWithIssues)) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following .gz archives were found in the package content.\n" + + "• Gz archives are only allowed in form of '.unitypackage' files", null, + checkedArchives.Where(x => x.Value == ArchiveResult.TarGzWithIssues).Select(x => x.Key).ToArray()); + } + + if (checkedArchives.Any(x => x.Value == ArchiveResult.ZipWithIssues)) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following .zip archives were found in the package content.\n" + + "• Zip archives should contain the keyword 'source' in the file name", null, + checkedArchives.Where(x => x.Value == ArchiveResult.ZipWithIssues).Select(x => x.Key).ToArray()); + } + + if (checkedArchives.Any(x => x.Value == ArchiveResult.NotAllowed)) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following archives are using formats that are not allowed:", null, + checkedArchives.Where(x => x.Value == ArchiveResult.NotAllowed).Select(x => x.Key).ToArray()); + } + + return result; + } + + private bool FileNameContainsKeyword(string filePath, string keyword) + { + var fileInfo = new FileInfo(filePath); + + if (!fileInfo.Exists) + return false; + + return fileInfo.Name.Remove(fileInfo.Name.Length - fileInfo.Extension.Length).ToLower().Contains(keyword.ToLower()); + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs.meta new file mode 100644 index 00000000..b9c85a69 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 84b23febe0d923842aef73b95da5f25b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckCompressedFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs new file mode 100644 index 00000000..8a87dad8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs @@ -0,0 +1,46 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckEmptyPrefabs : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckEmptyPrefabs(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var prefabs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Prefab); + var badPrefabs = new List(); + + foreach (var p in prefabs) + { + if (p.GetComponents().Length == 1 && p.transform.childCount == 0) + badPrefabs.Add(p); + } + + if (badPrefabs.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No empty prefabs were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following prefabs are empty", null, badPrefabs.ToArray()); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs.meta new file mode 100644 index 00000000..3ada9d5a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8055bed9373283e4793463b90b42f08f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckEmptyPrefabs.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs new file mode 100644 index 00000000..3f51144f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs @@ -0,0 +1,153 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckFileMenuNames : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IScriptUtilityService _scriptUtility; + + public CheckFileMenuNames(GenericTestConfig config, IAssetUtilityService assetUtility, IScriptUtilityService scriptUtility) + { + _config = config; + _assetUtility = assetUtility; + _scriptUtility = scriptUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; + + #region Scripts + + var scripts = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.MonoScript).ToArray(); + var scriptTypes = _scriptUtility.GetTypesFromScriptAssets(scripts); + var affectedScripts = new Dictionary>(); + + foreach (var kvp in scriptTypes) + { + var badMethods = new List(); + foreach (var type in kvp.Value) + { + foreach (var method in type.GetMethods(bindingFlags)) + { + var attributes = method.GetCustomAttributes().ToList(); + if (attributes.Count == 0) + continue; + + var badAttributes = attributes.Where(x => !IsValidMenuItem(x.menuItem)).ToList(); + if (badAttributes.Count > 0) + badMethods.Add($"{string.Join("\n", badAttributes.Select(x => $"\'{x.menuItem}\'"))}\n(for method '{method.Name}')\n"); + } + } + + if (badMethods.Count > 0) + affectedScripts.Add(kvp.Key, badMethods); + } + + #endregion + + #region Precompiled Assemblies + + var assemblies = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.PrecompiledAssembly).ToArray(); + var assemblyTypes = _scriptUtility.GetTypesFromAssemblies(assemblies); + var affectedAssemblies = new Dictionary>(); + + foreach (var kvp in assemblyTypes) + { + var badMethods = new List(); + foreach (var type in kvp.Value) + { + foreach (var method in type.GetMethods(bindingFlags)) + { + var attributes = method.GetCustomAttributes().ToList(); + if (attributes.Count == 0) + continue; + + var badAttributes = attributes.Where(x => !IsValidMenuItem(x.menuItem)).ToList(); + if (badAttributes.Count > 0) + badMethods.Add($"{string.Join("\n", badAttributes.Select(x => (x as MenuItem).menuItem))}\n(Method '{method.Name}')\n"); + } + } + + if (badMethods.Count > 0) + affectedAssemblies.Add(kvp.Key, badMethods); + } + + #endregion + + if (affectedScripts.Count > 0 || affectedAssemblies.Count > 0) + { + if (affectedScripts.Count > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following scripts contain invalid MenuItem names:"); + foreach (var kvp in affectedScripts) + { + var message = string.Empty; + foreach (var type in kvp.Value) + message += type + "\n"; + + message = message.Remove(message.Length - "\n".Length); + result.AddMessage(message, null, kvp.Key); + } + } + + if (affectedAssemblies.Count > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following assemblies contain invalid MenuItem names:"); + foreach (var kvp in affectedAssemblies) + { + var message = string.Empty; + foreach (var type in kvp.Value) + message += type + "\n"; + + message = message.Remove(message.Length - "\n".Length); + result.AddMessage(message, null, kvp.Key); + } + } + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No MenuItems with invalid names were found!"); + } + + return result; + } + + private bool IsValidMenuItem(string menuItemName) + { + var acceptableMenuItems = new string[] + { + "File", + "Edit", + "Assets", + "GameObject", + "Component", + "Window", + "Help", + "CONTEXT", + "Tools" + }; + + menuItemName = menuItemName.Replace("\\", "/"); + if (acceptableMenuItems.Any(x => menuItemName.ToLower().StartsWith($"{x.ToLower()}/"))) + return true; + + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs.meta new file mode 100644 index 00000000..2e594500 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d8e3b12ecc1fcd74d9a9f8d2b549fc63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckFileMenuNames.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs new file mode 100644 index 00000000..8b8975c5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs @@ -0,0 +1,79 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Data.MessageActions; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckLODs : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckLODs(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var prefabs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Prefab); + var badPrefabs = new Dictionary>(); + + foreach (var p in prefabs) + { + var meshFilters = p.GetComponentsInChildren(true); + var badMeshFilters = new List(); + var lodGroups = p.GetComponentsInChildren(true); + + foreach (var mf in meshFilters) + { + if (mf.name.Contains("LOD") && !IsPartOfLodGroup(mf, lodGroups)) + badMeshFilters.Add(mf); + } + + if (badMeshFilters.Count > 0) + badPrefabs.Add(p, badMeshFilters); + } + + if (badPrefabs.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found prefabs are meeting the LOD requirements!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following prefabs do not meet the LOD requirements"); + + foreach (var p in badPrefabs) + { + var resultList = new List(); + resultList.Add(p.Key); + resultList.AddRange(p.Value); + result.AddMessage($"{p.Key.name}.prefab", new OpenAssetAction(p.Key), resultList.ToArray()); + } + + return result; + } + + private bool IsPartOfLodGroup(MeshFilter mf, LODGroup[] lodGroups) + { + foreach (var lodGroup in lodGroups) + { + // If MeshFilter is a child/deep child of a LodGroup AND is referenced in this LOD group - it is valid + if (mf.transform.IsChildOf(lodGroup.transform) && + lodGroup.GetLODs().Any(lod => lod.renderers.Any(renderer => renderer != null && renderer.gameObject == mf.gameObject))) + return true; + } + + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs.meta new file mode 100644 index 00000000..e860a67d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 43b2158602f87704fa7b91561cfc8678 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLODs.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs new file mode 100644 index 00000000..adb381c7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs @@ -0,0 +1,77 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System; +using System.Collections.Concurrent; +using System.Threading.Tasks; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckLineEndings : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckLineEndings(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var scripts = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.MonoScript); + + var affectedScripts = new ConcurrentBag(); + var scriptContents = new ConcurrentDictionary(); + + // A separate dictionary is needed because MonoScript contents cannot be accessed outside of the main thread + foreach (var s in scripts) + if (s != null) + scriptContents.TryAdd(s, s.text); + + Parallel.ForEach(scriptContents, (s) => + { + if (HasInconsistentLineEndings(s.Value)) + affectedScripts.Add(s.Key); + }); + + if (affectedScripts.Count > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following scripts have inconsistent line endings:", null, affectedScripts.ToArray()); + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No scripts with inconsistent line endings were found!"); + } + + return result; + } + + private bool HasInconsistentLineEndings(string text) + { + int crlfEndings = 0; + int lfEndings = 0; + + var split = text.Split(new[] { "\n" }, StringSplitOptions.None); + for (int i = 0; i < split.Length; i++) + { + var line = split[i]; + if (line.EndsWith("\r")) + crlfEndings++; + else if (i != split.Length - 1) + lfEndings++; + } + + if (crlfEndings > 0 && lfEndings > 0) + return true; + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs.meta new file mode 100644 index 00000000..13dc5ad4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 85885005d1c594f42826de3555e98365 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckLineEndings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs new file mode 100644 index 00000000..2c378033 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs @@ -0,0 +1,106 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckMeshPrefabs : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IMeshUtilityService _meshUtility; + + public CheckMeshPrefabs(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility) + { + _config = config; + _assetUtility = assetUtility; + _meshUtility = meshUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var usedModelPaths = new List(); + var prefabs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Prefab); + var missingMeshReferencePrefabs = new List(); + + // Get all meshes in existing prefabs and check if prefab has missing mesh references + foreach (var p in prefabs) + { + var meshes = _meshUtility.GetCustomMeshesInObject(p); + foreach (var mesh in meshes) + { + string meshPath = _assetUtility.ObjectToAssetPath(mesh); + usedModelPaths.Add(meshPath); + } + + if (HasMissingMeshReferences(p)) + missingMeshReferencePrefabs.Add(p); + } + + // Get all meshes in existing models + var allModelPaths = GetAllModelMeshPaths(_config.ValidationPaths); + + // Get the list of meshes without prefabs + List unusedModels = allModelPaths.Except(usedModelPaths).ToList(); + + if (unusedModels.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found prefabs have meshes!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + var models = unusedModels.Select(_assetUtility.AssetPathToObject).ToArray(); + result.AddMessage("The following models do not have associated prefabs", null, models); + + if (missingMeshReferencePrefabs.Count > 0) + result.AddMessage("The following prefabs have missing mesh references", null, missingMeshReferencePrefabs.ToArray()); + + return result; + } + + private IEnumerable GetAllModelMeshPaths(string[] validationPaths) + { + var models = _assetUtility.GetObjectsFromAssets(validationPaths, AssetType.Model); + var paths = new List(); + + foreach (var o in models) + { + var m = (GameObject)o; + var modelPath = _assetUtility.ObjectToAssetPath(m); + var assetImporter = _assetUtility.GetAssetImporter(modelPath); + if (assetImporter is UnityEditor.ModelImporter modelImporter) + { + var clips = modelImporter.clipAnimations.Count(); + var meshes = _meshUtility.GetCustomMeshesInObject(m); + + // Only add if the model has meshes and no clips + if (meshes.Any() && clips == 0) + paths.Add(modelPath); + } + } + + return paths; + } + + private bool HasMissingMeshReferences(GameObject go) + { + var meshes = go.GetComponentsInChildren(true); + var skinnedMeshes = go.GetComponentsInChildren(true); + + if (meshes.Length == 0 && skinnedMeshes.Length == 0) + return false; + + if (meshes.Any(x => x.sharedMesh == null) || skinnedMeshes.Any(x => x.sharedMesh == null)) + return true; + + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs.meta new file mode 100644 index 00000000..ee337cfa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3c3d0d642ac6a6a48aa124a93dae3734 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMeshPrefabs.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs new file mode 100644 index 00000000..089d95ec --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs @@ -0,0 +1,66 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckMissingComponentsinAssets : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckMissingComponentsinAssets(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var assets = GetAllAssetsWithMissingComponents(_config.ValidationPaths); + + if (assets.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No assets have missing components!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following assets contain missing components", null, assets); + + return result; + } + + private GameObject[] GetAllAssetsWithMissingComponents(string[] validationPaths) + { + var missingReferenceAssets = new List(); + var prefabObjects = _assetUtility.GetObjectsFromAssets(validationPaths, AssetType.Prefab); + + foreach (var p in prefabObjects) + { + if (p != null && IsMissingReference(p)) + missingReferenceAssets.Add(p); + } + + return missingReferenceAssets.ToArray(); + } + + private bool IsMissingReference(GameObject asset) + { + var components = asset.GetComponentsInChildren(); + + foreach (var c in components) + { + if (!c) + return true; + } + + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs.meta new file mode 100644 index 00000000..965a2156 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 22d8f814e2363e34ea220736a4042728 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinAssets.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs new file mode 100644 index 00000000..3c0ee061 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs @@ -0,0 +1,93 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Data.MessageActions; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using SceneAsset = UnityEditor.SceneAsset; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckMissingComponentsinScenes : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private ISceneUtilityService _sceneUtility; + + public CheckMissingComponentsinScenes(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility) + { + _config = config; + _assetUtility = assetUtility; + _sceneUtility = sceneUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var originalScenePath = _sceneUtility.CurrentScenePath; + + var scenePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Scene); + foreach (var scenePath in scenePaths) + { + var missingComponentGOs = GetMissingComponentGOsInScene(scenePath); + + if (missingComponentGOs.Count == 0) + continue; + + result.Status = TestResultStatus.VariableSeverityIssue; + var message = $"GameObjects with missing components or prefab references found in {scenePath}.\n\nClick this message to open the Scene and see the affected GameObjects:"; + result.AddMessage(message, new OpenAssetAction(_assetUtility.AssetPathToObject(scenePath)), missingComponentGOs.ToArray()); + } + + _sceneUtility.OpenScene(originalScenePath); + + if (result.Status == TestResultStatus.Undefined) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No missing components were found!"); + } + + return result; + } + + private List GetMissingComponentGOsInScene(string path) + { + var missingComponentGOs = new List(); + + var scene = _sceneUtility.OpenScene(path); + + if (!scene.IsValid()) + { + Debug.LogWarning("Unable to get Scene in " + path); + return new List(); + } + + var rootObjects = scene.GetRootGameObjects(); + + foreach (var obj in rootObjects) + { + missingComponentGOs.AddRange(GetMissingComponentGOs(obj)); + } + + return missingComponentGOs; + } + + private List GetMissingComponentGOs(GameObject root) + { + var missingComponentGOs = new List(); + var rootComponents = root.GetComponents(); + + if (UnityEditor.PrefabUtility.GetPrefabInstanceStatus(root) == UnityEditor.PrefabInstanceStatus.MissingAsset || rootComponents.Any(c => !c)) + { + missingComponentGOs.Add(root); + } + + foreach (Transform child in root.transform) + missingComponentGOs.AddRange(GetMissingComponentGOs(child.gameObject)); + + return missingComponentGOs; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs.meta new file mode 100644 index 00000000..93b8efb1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 511e76d0ebcb23d40a7b49dda0e2980f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckMissingComponentsinScenes.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs new file mode 100644 index 00000000..b628aac8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs @@ -0,0 +1,64 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckModelImportLogs : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IModelUtilityService _modelUtility; + + public CheckModelImportLogs(GenericTestConfig config, IAssetUtilityService assetUtility, IModelUtilityService modelUtility) + { + _config = config; + _assetUtility = assetUtility; + _modelUtility = modelUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var models = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Model); + var importLogs = _modelUtility.GetImportLogs(models.ToArray()); + + var warningModels = new List(); + var errorModels = new List(); + + foreach (var kvp in importLogs) + { + if (kvp.Value.Any(x => x.Severity == UnityEngine.LogType.Error)) + errorModels.Add(kvp.Key); + if (kvp.Value.Any(x => x.Severity == UnityEngine.LogType.Warning)) + warningModels.Add(kvp.Key); + } + + if (warningModels.Count > 0 || errorModels.Count > 0) + { + if (warningModels.Count > 0) + { + result.Status = TestResultStatus.Warning; + result.AddMessage("The following models contain import warnings:", null, warningModels.ToArray()); + } + + if (errorModels.Count > 0) + { + result.Status = TestResultStatus.Warning; + result.AddMessage("The following models contain import errors:", null, errorModels.ToArray()); + } + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No issues were detected when importing your models!"); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs.meta new file mode 100644 index 00000000..a12e3951 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 98f3ec209166855408eaf4abe5bff591 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelImportLogs.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs new file mode 100644 index 00000000..82e9dd08 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs @@ -0,0 +1,71 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckModelOrientation : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IMeshUtilityService _meshUtility; + + public CheckModelOrientation(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility) + { + _config = config; + _assetUtility = assetUtility; + _meshUtility = meshUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var models = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Model); + var badModels = new List(); + + foreach (var m in models) + { + var meshes = _meshUtility.GetCustomMeshesInObject(m); + var assetImporter = _assetUtility.GetAssetImporter(m); + + if (!(assetImporter is UnityEditor.ModelImporter modelImporter)) + continue; + + var clips = modelImporter.clipAnimations.Length; + + // Only check if the model has meshes and no clips + if (!meshes.Any() || clips != 0) + continue; + + Transform[] transforms = m.GetComponentsInChildren(true); + + foreach (var t in transforms) + { + var hasMeshComponent = t.TryGetComponent(out _) || t.TryGetComponent(out _); + + if (t.localRotation == Quaternion.identity || !hasMeshComponent) + continue; + + badModels.Add(m); + break; + } + } + + if (badModels.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found models are facing the right way!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following models have incorrect rotation", null, badModels.ToArray()); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs.meta new file mode 100644 index 00000000..27e5a097 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 56cdcdc41a80fbc46b5b2b83ec8d66d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelOrientation.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs new file mode 100644 index 00000000..a434a0cb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs @@ -0,0 +1,58 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckModelTypes : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckModelTypes(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var allowedExtensions = new string[] { ".fbx", ".dae", ".abc", ".obj" }; + // Should retrieve All assets and not models here since ADB will not recognize certain + // types if appropriate software is not installed (e.g. .blend without Blender) + var allAssetPaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.All); + var badModels = new List(); + + foreach (var assetPath in allAssetPaths) + { + var importer = _assetUtility.GetAssetImporter(assetPath); + if (importer == null || !(importer is ModelImporter)) + continue; + + if (allowedExtensions.Any(x => importer.assetPath.ToLower().EndsWith(x))) + continue; + + badModels.Add(_assetUtility.AssetPathToObject(assetPath)); + } + + if (badModels.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All models are of allowed formats!"); + } + else + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following models are of formats that should not be used for Asset Store packages:", null, badModels.ToArray()); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs.meta new file mode 100644 index 00000000..b168b6e6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 428b1fb838e6f5a469bbfd26ca3fbfd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckModelTypes.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs new file mode 100644 index 00000000..d9113511 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs @@ -0,0 +1,94 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckNormalMapTextures : ITestScript + { + public const int TextureCacheLimit = 8; + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckNormalMapTextures(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var materials = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Material); + var badTextures = new List(); + var badPaths = new List(); + + foreach (var mat in materials) + { + for (int i = 0; i < mat.shader.GetPropertyCount(); i++) + { + if ((mat.shader.GetPropertyFlags(i) & UnityEngine.Rendering.ShaderPropertyFlags.Normal) != 0) + { + var propertyName = mat.shader.GetPropertyName(i); + var assignedTexture = mat.GetTexture(propertyName); + + if (assignedTexture == null) + continue; + + var texturePath = _assetUtility.ObjectToAssetPath(assignedTexture); + var textureImporter = _assetUtility.GetAssetImporter(texturePath) as TextureImporter; + if (textureImporter == null) + continue; + + if (textureImporter.textureType != TextureImporterType.NormalMap && !badTextures.Contains(assignedTexture)) + { + if (badTextures.Count < TextureCacheLimit) + { + badTextures.Add(assignedTexture); + } + else + { + string path = AssetDatabase.GetAssetPath(assignedTexture); + badPaths.Add(path); + } + } + } + } + + EditorUtility.UnloadUnusedAssetsImmediate(); + } + + if (badTextures.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All normal map textures have the correct texture type!"); + } + else if (badPaths.Count != 0) + { + foreach (Texture texture in badTextures) + { + string path = AssetDatabase.GetAssetPath(texture); + badPaths.Add(path); + } + + string paths = string.Join("\n", badPaths); + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following textures are not set to type 'Normal Map'", null); + result.AddMessage(paths); + } + else + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following textures are not set to type 'Normal Map'", null, badTextures.ToArray()); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs.meta new file mode 100644 index 00000000..8ca6ddbd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d55cea510248f814eb2194c2b53f88d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckNormalMapTextures.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs new file mode 100644 index 00000000..5b9bf466 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs @@ -0,0 +1,295 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckPackageNaming : ITestScript + { + private const string ForbiddenCharacters = "~`!@#$%^&*()-_=+[{]}\\|;:'\",<>?/"; + private readonly string[] PathsToCheckForForbiddenCharacters = new string[] + { + "Assets/", + "Assets/Editor/", + "Assets/Plugins/", + "Assets/Resources/", + "Assets/StreamingAssets/", + "Assets/WebGLTemplates/" + }; + + private class PathCheckResult + { + public Object[] InvalidMainPaths; + public Object[] InvalidMainPathContentPaths; + public Object[] InvalidMainPathLeadingUpPaths; + public Object[] InvalidHybridPackages; + public Object[] PotentiallyInvalidContent; + + public bool HasIssues => InvalidMainPaths.Length > 0 + || InvalidMainPathContentPaths.Length > 0 + || InvalidMainPathLeadingUpPaths.Length > 0 + || InvalidHybridPackages.Length > 0 + || PotentiallyInvalidContent.Length > 0; + } + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + // Constructor also accepts dependency injection of registered IValidatorService types + public CheckPackageNaming(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var checkResult = GetInvalidPathsInAssets(); + + if (checkResult.HasIssues) + { + result.Status = TestResultStatus.Warning; + + if (checkResult.InvalidMainPaths.Length > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following assets appear to be artificially bumped up in the project hierarchy within commonly used folders", null, checkResult.InvalidMainPaths); + } + + if (checkResult.InvalidMainPathContentPaths.Length > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following assets appear to be artificially bumped up in the project hierarchy within commonly used folders", null, checkResult.InvalidMainPathContentPaths); + } + + if (checkResult.InvalidMainPathLeadingUpPaths.Length > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("Despite not being directly validated, this path would be automatically created by the Unity Importer when importing your package", null, checkResult.InvalidMainPathLeadingUpPaths); + } + + if (checkResult.InvalidHybridPackages.Length > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following packages appear to be artificially bumped up in the Package hierarchy with their 'Display Name' configuration", null, checkResult.InvalidHybridPackages); + } + + if (checkResult.PotentiallyInvalidContent.Length > 0) + { + // Do not override previously set severities + result.AddMessage("It is recommended that nested package content refrains from starting with a special character", null, checkResult.PotentiallyInvalidContent); + } + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All package asset names are valid!"); + } + + return result; + } + + private PathCheckResult GetInvalidPathsInAssets() + { + var allInvalidMainPaths = new List(); + var allInvalidMainContentPaths = new List(); + var allInvalidMainLeadingUpPaths = new List(); + var allInvalidPackagePaths = new List(); + var allInvalidOtherContentPaths = new List(); + + foreach (var validationPath in _config.ValidationPaths) + { + // Is path itself not forbidden e.g.: when validating Assets/_Package, the folder _Package would be invalid + if (!IsDirectMainPathValid(validationPath)) + allInvalidMainPaths.Add(validationPath); + + // Are path contents not forbidden e.g.: when validating Assets/, the folder _Package would be invalid + if (!IsDirectMainPathContentValid(validationPath, out var invalidContentPaths)) + allInvalidMainContentPaths.AddRange(invalidContentPaths); + + // Is the path leading up to this path not forbidden e.g: when validating Assets/_WorkDir/Package, the folder _Workdir would be invalid + if (!IsPathLeadingUpToMainPathValid(validationPath, out var invalidLeadingUpPath)) + allInvalidMainLeadingUpPaths.Add(invalidLeadingUpPath); + + // Is the path pointing to a package valid, e.g.: when validating Packages/com.company.product its display name _Product would be invalid + if (!IsHybridPackageMainPathValid(validationPath, out string invalidPackagePath)) + allInvalidPackagePaths.Add(invalidPackagePath); + } + + var ignoredPaths = new List(); + ignoredPaths.AddRange(allInvalidMainPaths); + ignoredPaths.AddRange(allInvalidMainContentPaths); + ignoredPaths.AddRange(allInvalidMainLeadingUpPaths); + ignoredPaths.AddRange(allInvalidPackagePaths); + + // Mark any other paths that start with a forbidden character + if (!ArePackageContentsValid(ignoredPaths, out var invalidContents)) + allInvalidOtherContentPaths.AddRange(invalidContents); + + return new PathCheckResult() + { + InvalidMainPaths = PathsToObjects(allInvalidMainPaths), + InvalidMainPathContentPaths = PathsToObjects(allInvalidMainContentPaths), + InvalidMainPathLeadingUpPaths = PathsToObjects(allInvalidMainLeadingUpPaths), + InvalidHybridPackages = PathsToObjects(allInvalidPackagePaths), + PotentiallyInvalidContent = PathsToObjects(allInvalidOtherContentPaths) + }; + } + + private bool IsDirectMainPathValid(string validationPath) + { + foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters) + { + var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/"; + if (!validationPath.StartsWith(forbiddenPathWithSeparator)) + continue; + + var truncatedPath = validationPath.Remove(0, forbiddenPathWithSeparator.Length); + var truncatedPathSplit = truncatedPath.Split('/'); + + // It is not a direct main path if it has deeper paths + if (truncatedPathSplit.Length != 1) + continue; + + if (ForbiddenCharacters.Any(x => truncatedPath.StartsWith(x.ToString()))) + return false; + } + + return true; + } + + private bool IsDirectMainPathContentValid(string validationPath, out List invalidContentPaths) + { + invalidContentPaths = new List(); + + var contents = Directory.EnumerateFileSystemEntries(validationPath, "*", SearchOption.AllDirectories) + .Where(x => !x.EndsWith(".meta")) + .Select(GetAdbPath); + + foreach (var contentPath in contents) + { + foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters) + { + var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/"; + if (!contentPath.StartsWith(forbiddenPathWithSeparator)) + continue; + + var truncatedPath = contentPath.Remove(0, forbiddenPathWithSeparator.Length); + var truncatedPathSplit = truncatedPath.Split('/'); + + // Only check the first level of content relative to the forbidden path + if (truncatedPathSplit.Length > 1) + continue; + + if (ForbiddenCharacters.Any(x => truncatedPathSplit[0].StartsWith(x.ToString()))) + invalidContentPaths.Add(contentPath); + } + } + + return invalidContentPaths.Count == 0; + } + + private bool IsPathLeadingUpToMainPathValid(string validationPath, out string invalidLeadingUpPath) + { + invalidLeadingUpPath = string.Empty; + + foreach (var forbiddenPath in PathsToCheckForForbiddenCharacters) + { + var forbiddenPathWithSeparator = forbiddenPath.EndsWith("/") ? forbiddenPath : forbiddenPath + "/"; + if (!validationPath.StartsWith(forbiddenPathWithSeparator)) + continue; + + var truncatedPath = validationPath.Remove(0, forbiddenPathWithSeparator.Length); + var truncatedPathSplit = truncatedPath.Split('/'); + + // It is not a leading up path if it has no deeper path + if (truncatedPathSplit.Length == 1) + continue; + + if (ForbiddenCharacters.Any(x => truncatedPathSplit[0].StartsWith(x.ToString()))) + { + invalidLeadingUpPath = forbiddenPathWithSeparator + truncatedPathSplit[0]; + return false; + } + } + + return true; + } + + private bool IsHybridPackageMainPathValid(string validationPath, out string invalidPackagePath) + { + invalidPackagePath = string.Empty; + + if (!PackageUtility.GetPackageByManifestPath($"{validationPath}/package.json", out var package)) + return true; + + var packageName = package.displayName; + if (ForbiddenCharacters.Any(x => packageName.StartsWith(x.ToString()))) + { + invalidPackagePath = validationPath; + return false; + } + + return true; + } + + private bool ArePackageContentsValid(IEnumerable ignoredPaths, out List invalidContentPaths) + { + invalidContentPaths = new List(); + + foreach (var validationPath in _config.ValidationPaths) + { + var validationPathFolderName = validationPath.Split('/').Last(); + if (!ignoredPaths.Contains(validationPath) && ForbiddenCharacters.Any(x => validationPathFolderName.StartsWith(x.ToString()))) + invalidContentPaths.Add(validationPath); + + var contents = Directory.EnumerateFileSystemEntries(validationPath, "*", SearchOption.AllDirectories) + .Where(x => !x.EndsWith(".meta")) + .Select(GetAdbPath); + + foreach (var contentEntry in contents) + { + if (ignoredPaths.Contains(contentEntry)) + continue; + + var entryName = contentEntry.Split('/').Last(); + if (ForbiddenCharacters.Any(x => entryName.StartsWith(x.ToString()))) + invalidContentPaths.Add(contentEntry); + } + } + + return invalidContentPaths.Count == 0; + } + + private string GetAdbPath(string path) + { + path = path.Replace("\\", "/"); + if (path.StartsWith(Constants.RootProjectPath)) + path = path.Remove(Constants.RootProjectPath.Length); + + return path; + } + + private Object[] PathsToObjects(IEnumerable paths) + { + var objects = new List(); + + foreach (var path in paths) + { + var obj = _assetUtility.AssetPathToObject(path); + if (obj != null) + objects.Add(obj); + } + + return objects.ToArray(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs.meta new file mode 100644 index 00000000..6372a66c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: afe9e04825c7d904981a54404b222290 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPackageNaming.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs new file mode 100644 index 00000000..8e69b105 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs @@ -0,0 +1,76 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Data.MessageActions; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckParticleSystems : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private ISceneUtilityService _sceneUtility; + + public CheckParticleSystems(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility) + { + _config = config; + _assetUtility = assetUtility; + _sceneUtility = sceneUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var originalScenePath = _sceneUtility.CurrentScenePath; + + var scenePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Scene); + + foreach (var path in scenePaths) + { + var badParticleSystems = new List(); + + var scene = _sceneUtility.OpenScene(path); + + if (!scene.IsValid()) + { + Debug.LogWarning("Unable to get Scene in " + path); + continue; + } + +#if UNITY_2023_1_OR_NEWER + var particleSystems = GameObject.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); +#else + var particleSystems = GameObject.FindObjectsOfType(); +#endif + + foreach (var ps in particleSystems) + { + if (PrefabUtility.IsPartOfAnyPrefab(ps.gameObject)) + continue; + badParticleSystems.Add(ps); + } + + if (badParticleSystems.Count == 0) + continue; + + result.Status = TestResultStatus.VariableSeverityIssue; + var message = $"Particle Systems not belonging to any Prefab were found in {path}.\n\nClick this message to open the Scene and see the affected Particle Systems:"; + result.AddMessage(message, new OpenAssetAction(AssetDatabase.LoadAssetAtPath(path)), badParticleSystems.ToArray()); + } + + _sceneUtility.OpenScene(originalScenePath); + + if (result.Status == TestResultStatus.Undefined) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No Particle Systems without Prefabs were found!"); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs.meta new file mode 100644 index 00000000..36bce088 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6a623f7988c75884bb17b169ccd3e993 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckParticleSystems.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs new file mode 100644 index 00000000..27750c53 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs @@ -0,0 +1,98 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using AssetStoreTools.Validator.Utility; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckPathLengths : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckPathLengths(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + TestResult result = new TestResult(); + + int pathLengthLimit = 140; + // Get all project paths and sort by length so that folders always come before files + var allPaths = ValidatorUtility.GetProjectPaths(_config.ValidationPaths).OrderBy(x => x.Length); + + var filteredDirs = new Dictionary(); + var filteredFiles = new Dictionary(); + + foreach (var path in allPaths) + { + // Truncated path examples: + // Assets/[Scenes/SampleScene.unity] + // Packages/com.example.package/[Editor/EditorScript.cs] + var truncatedPath = path; + if (path.StartsWith("Assets/")) + truncatedPath = path.Remove(0, "Assets/".Length); + else if (path.StartsWith("Packages/")) + { + var splitPath = path.Split('/'); + truncatedPath = string.Join("/", splitPath.Skip(2)); + } + + // Skip paths under the character limit + if (truncatedPath.Length < pathLengthLimit) + continue; + + // Skip children of already added directories + if (filteredDirs.Keys.Any(x => truncatedPath.StartsWith(x))) + continue; + + if (AssetDatabase.IsValidFolder(path)) + { + filteredDirs.Add(truncatedPath, _assetUtility.AssetPathToObject(path)); + continue; + } + + if (!filteredFiles.ContainsKey(truncatedPath)) + filteredFiles.Add(truncatedPath, _assetUtility.AssetPathToObject(path)); + } + + if (filteredDirs.Count == 0 && filteredFiles.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All package content matches the path limit criteria!"); + return result; + } + + if (filteredDirs.Count > 0) + { + var maxDirLength = filteredDirs.Keys.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur); + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage($"The following folders exceed the path length limit:"); + foreach (var kvp in filteredDirs) + { + result.AddMessage($"Path length: {kvp.Key.Length} characters", null, kvp.Value); + } + } + + if (filteredFiles.Count > 0) + { + var maxFileLength = filteredFiles.Keys.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur); + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage($"The following files exceed the path length limit:"); + foreach (var kvp in filteredFiles) + { + result.AddMessage($"Path length: {kvp.Key.Length} characters", null, kvp.Value); + } + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs.meta new file mode 100644 index 00000000..8d56a291 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ae379305e9165e84584373a8272c09e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPathLengths.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs new file mode 100644 index 00000000..aa018814 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs @@ -0,0 +1,71 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckPrefabTransforms : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IMeshUtilityService _meshUtility; + + public CheckPrefabTransforms(GenericTestConfig config, IAssetUtilityService assetUtility, IMeshUtilityService meshUtility) + { + _config = config; + _assetUtility = assetUtility; + _meshUtility = meshUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var prefabs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Prefab); + var badPrefabs = new List(); + var badPrefabsLowOffset = new List(); + + foreach (var p in prefabs) + { + var hasRectTransform = p.TryGetComponent(out RectTransform _); + if (hasRectTransform || !_meshUtility.GetCustomMeshesInObject(p).Any()) + continue; + + var positionString = p.transform.position.ToString("F12"); + var rotationString = p.transform.rotation.eulerAngles.ToString("F12"); + var localScaleString = p.transform.localScale.ToString("F12"); + + var vectorZeroString = Vector3.zero.ToString("F12"); + var vectorOneString = Vector3.one.ToString("F12"); + + if (positionString != vectorZeroString || rotationString != vectorZeroString || localScaleString != vectorOneString) + { + if (p.transform.position == Vector3.zero && p.transform.rotation.eulerAngles == Vector3.zero && p.transform.localScale == Vector3.one) + badPrefabsLowOffset.Add(p); + else + badPrefabs.Add(p); + } + } + + if (badPrefabs.Count == 0 && badPrefabsLowOffset.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found prefabs were reset!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + if (badPrefabs.Count > 0) + result.AddMessage("The following prefabs' transforms do not fit the requirements", null, badPrefabs.ToArray()); + if (badPrefabsLowOffset.Count > 0) + result.AddMessage("The following prefabs have unusually low transform values, which might not be accurately displayed " + + "in the Inspector window. Please use the 'Debug' Inspector mode to review the Transform component of these prefabs " + + "or reset the Transform components using the right-click context menu", null, badPrefabsLowOffset.ToArray()); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs.meta new file mode 100644 index 00000000..cbffe1ae --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f712c17a60bf2d049a4e61c8f79e56c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckPrefabTransforms.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs new file mode 100644 index 00000000..034f4571 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs @@ -0,0 +1,30 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; +using UnityEditor; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckScriptCompilation : ITestScript + { + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var hasCompilationErrors = EditorUtility.scriptCompilationFailed; + + if (hasCompilationErrors) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("One or more scripts in the project failed to compile.\n" + + "Please check the Console window to see the list of errors"); + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All scripts in the project compiled successfully!"); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs.meta new file mode 100644 index 00000000..f50df8c6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 59db88f43969db8499299bce7f4fb967 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckScriptCompilation.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs new file mode 100644 index 00000000..a004febd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs @@ -0,0 +1,63 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; +using UnityEditor; +using UnityEngine; +#if !UNITY_2023_1_OR_NEWER +using UnityEngine.Experimental.Rendering; +#endif +#if UNITY_2023_1_OR_NEWER +using UnityEngine.Rendering; +#endif + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckShaderCompilation : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckShaderCompilation(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var shaders = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Shader); + var badShaders = shaders.Where(ShaderHasError).ToArray(); + + if (badShaders.Length > 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following shader files have errors", null, badShaders); + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All found Shaders have no compilation errors!"); + } + + return result; + } + + private bool ShaderHasError(Object obj) + { + switch (obj) + { + case Shader shader: + return ShaderUtil.ShaderHasError(shader); + case ComputeShader shader: + return ShaderUtil.GetComputeShaderMessageCount(shader) > 0; + case RayTracingShader shader: + return ShaderUtil.GetRayTracingShaderMessageCount(shader) > 0; + default: + return false; + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs.meta new file mode 100644 index 00000000..6bd1d2c7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7abb278a6082bde4391e0779394cb85b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckShaderCompilation.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs new file mode 100644 index 00000000..d05c1aed --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs @@ -0,0 +1,57 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckTextureDimensions : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckTextureDimensions(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var textures = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Texture); + var badTextures = new List(); + + foreach (var texture in textures) + { + if (Mathf.IsPowerOfTwo(texture.width) && Mathf.IsPowerOfTwo(texture.height)) + continue; + + var importer = _assetUtility.GetAssetImporter(_assetUtility.ObjectToAssetPath(texture)); + + if (importer == null || !(importer is TextureImporter textureImporter) + || textureImporter.textureType == TextureImporterType.Sprite + || textureImporter.textureType == TextureImporterType.GUI) + continue; + + badTextures.Add(texture); + } + + if (badTextures.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All texture dimensions are a power of 2!"); + } + else + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following texture dimensions are not a power of 2:", null, badTextures.ToArray()); + } + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs.meta new file mode 100644 index 00000000..eb27a1ce --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 073f1dacf3da34d4783140ae9d485d5f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTextureDimensions.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs new file mode 100644 index 00000000..35c9d4d1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs @@ -0,0 +1,233 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckTypeNamespaces : ITestScript + { + private readonly string[] ForbiddenNamespaces = new string[] { "Unity" }; + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private IScriptUtilityService _scriptUtility; + + private enum NamespaceEligibility + { + NoNamespace, + Ok, + Forbidden + } + + private class AnalysisResult + { + public Dictionary> TypesWithoutNamespaces; + public Dictionary> ForbiddenNamespaces; + + public bool HasIssues => TypesWithoutNamespaces.Count > 0 + || ForbiddenNamespaces.Count > 0; + } + + public CheckTypeNamespaces(GenericTestConfig config, IAssetUtilityService assetUtility, IScriptUtilityService scriptUtility) + { + _config = config; + _assetUtility = assetUtility; + _scriptUtility = scriptUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var scriptResult = CheckScripts(); + var assemblyResult = CheckAssemblies(); + + if (scriptResult.HasIssues || assemblyResult.HasIssues) + { + result.Status = TestResultStatus.Warning; + + // Error conditions for forbidden namespaces + + if (scriptResult.ForbiddenNamespaces.Count > 0) + { + result.Status = TestResultStatus.Fail; + result.AddMessage("The following scripts contain namespaces starting with a 'Unity' keyword:"); + AddJoinedMessage(result, scriptResult.ForbiddenNamespaces); + } + + if (assemblyResult.ForbiddenNamespaces.Count > 0) + { + result.Status = TestResultStatus.Fail; + result.AddMessage("The following assemblies contain namespaces starting with a 'Unity' keyword:"); + AddJoinedMessage(result, assemblyResult.ForbiddenNamespaces); + } + + // Variable severity conditions for no-namespace types + + if (scriptResult.TypesWithoutNamespaces.Count > 0) + { + if (result.Status != TestResultStatus.Fail) + result.Status = TestResultStatus.VariableSeverityIssue; + + result.AddMessage("The following scripts contain types not nested under a namespace:"); + AddJoinedMessage(result, scriptResult.TypesWithoutNamespaces); + } + + if (assemblyResult.TypesWithoutNamespaces.Count > 0) + { + if (result.Status != TestResultStatus.Fail) + result.Status = TestResultStatus.VariableSeverityIssue; + + result.AddMessage("The following assemblies contain types not nested under a namespace:"); + AddJoinedMessage(result, assemblyResult.TypesWithoutNamespaces); + } + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("All scripts contain valid namespaces!"); + } + + return result; + } + + private AnalysisResult CheckScripts() + { + var scripts = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.MonoScript).ToArray(); + var scriptNamespaces = _scriptUtility.GetTypeNamespacesFromScriptAssets(scripts); + + var scriptsWithoutNamespaces = new Dictionary>(); + var scriptsWithForbiddenNamespaces = new Dictionary>(); + + foreach (var kvp in scriptNamespaces) + { + var scriptAsset = kvp.Key; + var typesInScriptAsset = kvp.Value; + + var typesWithoutNamespace = new List(); + var discouragedNamespaces = new List(); + var forbiddenNamespaces = new List(); + + foreach (var t in typesInScriptAsset) + { + var eligibility = CheckNamespaceEligibility(t.Namespace); + + switch (eligibility) + { + case NamespaceEligibility.NoNamespace: + typesWithoutNamespace.Add(t.Name); + break; + case NamespaceEligibility.Forbidden: + if (!forbiddenNamespaces.Contains(t.Namespace)) + forbiddenNamespaces.Add(t.Namespace); + break; + case NamespaceEligibility.Ok: + break; + } + } + + if (typesWithoutNamespace.Count > 0) + scriptsWithoutNamespaces.Add(scriptAsset, typesWithoutNamespace); + + if (forbiddenNamespaces.Count > 0) + scriptsWithForbiddenNamespaces.Add(scriptAsset, forbiddenNamespaces); + } + + return new AnalysisResult + { + TypesWithoutNamespaces = scriptsWithoutNamespaces, + ForbiddenNamespaces = scriptsWithForbiddenNamespaces + }; + } + + private AnalysisResult CheckAssemblies() + { + var assemblies = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.PrecompiledAssembly).ToList(); + var assemblyTypes = _scriptUtility.GetTypesFromAssemblies(assemblies); + + var assembliesWithoutNamespaces = new Dictionary>(); + var assembliesWithForbiddenNamespaces = new Dictionary>(); + + foreach (var kvp in assemblyTypes) + { + var assemblyAsset = kvp.Key; + var typesInAssembly = kvp.Value; + + var typesWithoutNamespace = new List(); + var discouragedNamespaces = new List(); + var forbiddenNamespaces = new List(); + + foreach (var t in typesInAssembly) + { + var eligibility = CheckNamespaceEligibility(t.Namespace); + + switch (eligibility) + { + case NamespaceEligibility.NoNamespace: + typesWithoutNamespace.Add($"{GetTypeName(t)} {t.Name}"); + break; + case NamespaceEligibility.Forbidden: + if (!forbiddenNamespaces.Contains(t.Namespace)) + forbiddenNamespaces.Add(t.Namespace); + break; + case NamespaceEligibility.Ok: + break; + } + } + + if (typesWithoutNamespace.Count > 0) + assembliesWithoutNamespaces.Add(assemblyAsset, typesWithoutNamespace); + + if (forbiddenNamespaces.Count > 0) + assembliesWithForbiddenNamespaces.Add(assemblyAsset, forbiddenNamespaces); + } + + return new AnalysisResult + { + TypesWithoutNamespaces = assembliesWithoutNamespaces, + ForbiddenNamespaces = assembliesWithForbiddenNamespaces + }; + } + + private NamespaceEligibility CheckNamespaceEligibility(string fullNamespace) + { + if (string.IsNullOrEmpty(fullNamespace)) + return NamespaceEligibility.NoNamespace; + + var split = fullNamespace.Split('.'); + var topLevelNamespace = split[0]; + if (ForbiddenNamespaces.Any(x => topLevelNamespace.StartsWith(x, StringComparison.OrdinalIgnoreCase))) + return NamespaceEligibility.Forbidden; + + return NamespaceEligibility.Ok; + } + + private string GetTypeName(Type type) + { + if (type.IsClass) + return "class"; + if (type.IsInterface) + return "interface"; + if (type.IsEnum) + return "enum"; + if (type.IsValueType) + return "struct"; + + throw new ArgumentException($"Received an unrecognizable type {type}. Type must be either a class, interface, struct or enum"); + } + + private void AddJoinedMessage(TestResult result, Dictionary> assetsWithMessages) + { + foreach (var kvp in assetsWithMessages) + { + var message = string.Join("\n", kvp.Value); + result.AddMessage(message, null, kvp.Key); + } + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs.meta new file mode 100644 index 00000000..b8a80ea5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 279249fa7ef8c2446b3a9f013eeedbf0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/CheckTypeNamespaces.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs new file mode 100644 index 00000000..71f31bca --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveExecutableFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveExecutableFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var executables = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Executable).ToArray(); + + if (executables.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No executable files were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following executable files were found", null, executables); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs.meta new file mode 100644 index 00000000..b45d0eec --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8e4450592cc60e54286ad089b66db94d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveExecutableFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs new file mode 100644 index 00000000..3a5a4c7c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveJPGFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveJPGFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var jpgs = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.JPG).ToArray(); + + if (jpgs.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No JPG/JPEG textures were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following textures are compressed as JPG/JPEG", null, jpgs); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs.meta new file mode 100644 index 00000000..4df41e64 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5634a12b3a8544c4585bbc280ae59ce2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJPGFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs new file mode 100644 index 00000000..69a7681e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveJavaScriptFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveJavaScriptFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var javascriptObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.JavaScript).ToArray(); + + if (javascriptObjects.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No UnityScript / JS files were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following assets are UnityScript / JS files", null, javascriptObjects); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs.meta new file mode 100644 index 00000000..6153ea48 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ab1676bde9afba442b35fd3319c18063 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveJavaScriptFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs new file mode 100644 index 00000000..6cdc77ab --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs @@ -0,0 +1,83 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveLossyAudioFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveLossyAudioFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + string SanitizeForComparison(UnityObject o) + { + Regex alphanumericRegex = new Regex("[^a-zA-Z0-9]"); + string path = _assetUtility.ObjectToAssetPath(o); + path = path.ToLower(); + + int extensionIndex = path.LastIndexOf('.'); + string extension = path.Substring(extensionIndex + 1); + string sanitized = path.Substring(0, extensionIndex); + + int separatorIndex = sanitized.LastIndexOf('/'); + sanitized = sanitized.Substring(separatorIndex); + sanitized = alphanumericRegex.Replace(sanitized, String.Empty); + sanitized = sanitized.Replace(extension, String.Empty); + sanitized = sanitized.Trim(); + + return sanitized; + } + + var lossyAudioObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.LossyAudio).ToArray(); + if (lossyAudioObjects.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No lossy audio files were found!"); + return result; + } + + // Try to find and match variants + var nonLossyAudioObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.NonLossyAudio); + HashSet nonLossyPathSet = new HashSet(); + foreach (var asset in nonLossyAudioObjects) + { + var path = SanitizeForComparison(asset); + nonLossyPathSet.Add(path); + } + + var unmatchedAssets = new List(); + foreach (var asset in lossyAudioObjects) + { + var path = SanitizeForComparison(asset); + if (!nonLossyPathSet.Contains(path)) + unmatchedAssets.Add(asset); + } + + if (unmatchedAssets.Count == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No lossy audio files were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following lossy audio files were found without identically named non-lossy variants:", null, unmatchedAssets.ToArray()); + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs.meta new file mode 100644 index 00000000..55d0d0bc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b7205a85061273a4eb50586f13f35d35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveLossyAudioFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs new file mode 100644 index 00000000..17a1cb26 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveMixamoFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveMixamoFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var mixamoFiles = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Mixamo).ToArray(); + + if (mixamoFiles.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No Mixamo files were found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following Mixamo files were found", null, mixamoFiles); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs.meta new file mode 100644 index 00000000..603034c7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9df432e52aa958b44bb5e20c13d16552 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveMixamoFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs new file mode 100644 index 00000000..feef2306 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveSpeedTreeFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveSpeedTreeFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var speedtreeObjects = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.SpeedTree).ToArray(); + + if (speedtreeObjects.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No SpeedTree assets have been found!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following SpeedTree assets have been found", null, speedtreeObjects); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs.meta new file mode 100644 index 00000000..25f2a23e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e06bb7e0aa4f9944abc18281c002dff4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveSpeedTreeFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs new file mode 100644 index 00000000..ae0e5ff6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs @@ -0,0 +1,38 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class RemoveVideoFiles : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public RemoveVideoFiles(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var videos = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.Video).ToArray(); + + if (videos.Length == 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No video files were found, looking good!"); + return result; + } + + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("The following video files were found", null, videos); + + return result; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs.meta new file mode 100644 index 00000000..80ca9b89 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f99724c71b0de66419b5d6e8e9bfcc2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/Generic/RemoveVideoFiles.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage.meta new file mode 100644 index 00000000..b8fde811 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 016d62b2cd8346a49815615efd1d6e39 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs new file mode 100644 index 00000000..6c635c2c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs @@ -0,0 +1,172 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityObject = UnityEngine.Object; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckDemoScenes : ITestScript + { + private class DemoSceneScanResult + { + public List ValidAdbScenes; + public List HybridScenePaths; + public List NestedUnityPackages; + } + + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + private ISceneUtilityService _sceneUtility; + + public CheckDemoScenes(GenericTestConfig config, IAssetUtilityService assetUtility, ISceneUtilityService sceneUtility) + { + _config = config; + _assetUtility = assetUtility; + _sceneUtility = sceneUtility; + } + + public TestResult Run() + { + var result = new TestResult(); + var demoSceneScanResult = CheckForDemoScenes(_config); + + // Valid demo scenes were found in ADB + if (demoSceneScanResult.ValidAdbScenes.Count > 0) + { + result.Status = TestResultStatus.Pass; + result.AddMessage("Demo scenes found", null, demoSceneScanResult.ValidAdbScenes.ToArray()); + return result; + } + + // Valid demo scenes found in UPM package.json + if (demoSceneScanResult.HybridScenePaths.Count > 0) + { + result.Status = TestResultStatus.Pass; + + var upmSampleSceneList = string.Join("\n-", demoSceneScanResult.HybridScenePaths); + upmSampleSceneList = upmSampleSceneList.Insert(0, "-"); + + result.AddMessage($"Demo scenes found:\n{upmSampleSceneList}"); + return result; + } + + // No valid scenes found, but package contains nested .unitypackages + if (demoSceneScanResult.NestedUnityPackages.Count > 0) + { + result.Status = TestResultStatus.Warning; + result.AddMessage("Could not find any valid Demo scenes in the selected validation paths."); + result.AddMessage("The following nested .unitypackage files were found. " + + "If they contain any demo scenes, you can ignore this warning.", null, demoSceneScanResult.NestedUnityPackages.ToArray()); + return result; + } + + // No valid scenes were found and there is nothing pointing to their inclusion in the package + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("Could not find any valid Demo Scenes in the selected validation paths."); + return result; + } + + private DemoSceneScanResult CheckForDemoScenes(GenericTestConfig config) + { + var scanResult = new DemoSceneScanResult(); + scanResult.ValidAdbScenes = CheckForDemoScenesInAssetDatabase(config); + scanResult.HybridScenePaths = CheckForDemoScenesInUpmSamples(config); + scanResult.NestedUnityPackages = CheckForNestedUnityPackages(config); + + return scanResult; + } + + private List CheckForDemoScenesInAssetDatabase(GenericTestConfig config) + { + var scenePaths = _assetUtility.GetAssetPathsFromAssets(config.ValidationPaths, AssetType.Scene).ToArray(); + if (scenePaths.Length == 0) + return new List(); + + var originalScenePath = _sceneUtility.CurrentScenePath; + var validScenePaths = scenePaths.Where(CanBeDemoScene).ToArray(); + _sceneUtility.OpenScene(originalScenePath); + + if (validScenePaths.Length == 0) + return new List(); + + return validScenePaths.Select(x => AssetDatabase.LoadAssetAtPath(x)).ToList(); + } + + private bool CanBeDemoScene(string scenePath) + { + // Check skybox + var sceneSkyboxPath = _assetUtility.ObjectToAssetPath(RenderSettings.skybox).Replace("\\", "").Replace("/", ""); + var defaultSkyboxPath = "Resources/unity_builtin_extra".Replace("\\", "").Replace("/", ""); + + if (!sceneSkyboxPath.Equals(defaultSkyboxPath, StringComparison.OrdinalIgnoreCase)) + return true; + + // Check GameObjects + _sceneUtility.OpenScene(scenePath); + var rootObjects = _sceneUtility.GetRootGameObjects(); + var count = rootObjects.Length; + + if (count == 0) + return false; + + if (count != 2) + return true; + + var cameraGOUnchanged = rootObjects.Any(o => o.TryGetComponent(out _) && o.GetComponents(typeof(Component)).Length == 3); + var lightGOUnchanged = rootObjects.Any(o => o.TryGetComponent(out _) && o.GetComponents(typeof(Component)).Length == 2); + + return !cameraGOUnchanged || !lightGOUnchanged; + } + + private List CheckForDemoScenesInUpmSamples(GenericTestConfig config) + { + var scenePaths = new List(); + + foreach (var path in config.ValidationPaths) + { + if (!File.Exists($"{path}/package.json")) + continue; + + var packageJsonText = File.ReadAllText($"{path}/package.json"); + var json = JObject.Parse(packageJsonText); + + if (!json.ContainsKey("samples") || json["samples"].Type != JTokenType.Array || json["samples"].ToList().Count == 0) + continue; + + foreach (var sample in json["samples"].ToList()) + { + var samplePath = sample["path"].ToString(); + samplePath = $"{path}/{samplePath}"; + if (!Directory.Exists(samplePath)) + continue; + + var sampleScenePaths = Directory.GetFiles(samplePath, "*.unity", SearchOption.AllDirectories); + foreach (var scenePath in sampleScenePaths) + { + // If meta file is not found, the sample will not be included with the exported .unitypackage + if (!File.Exists($"{scenePath}.meta")) + continue; + + if (!scenePaths.Contains(scenePath.Replace("\\", "/"))) + scenePaths.Add(scenePath.Replace("\\", "/")); + } + } + } + + return scenePaths; + } + + private List CheckForNestedUnityPackages(GenericTestConfig config) + { + var unityPackages = _assetUtility.GetObjectsFromAssets(config.ValidationPaths, AssetType.UnityPackage).ToArray(); + return unityPackages.ToList(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs.meta new file mode 100644 index 00000000..a3689d41 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f844c2dfa4669ff4eacf5591b544edaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDemoScenes.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs new file mode 100644 index 00000000..1799c1d0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs @@ -0,0 +1,73 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System; +using System.IO; +using System.Linq; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckDocumentation : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + public CheckDocumentation(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var textFilePaths = _assetUtility.GetAssetPathsFromAssets(_config.ValidationPaths, AssetType.Documentation).ToArray(); + var documentationFilePaths = textFilePaths.Where(CouldBeDocumentation).ToArray(); + + if (textFilePaths.Length == 0) + { + result.Status = TestResultStatus.VariableSeverityIssue; + result.AddMessage("No potential documentation files ('.txt', '.pdf', " + + "'.html', '.rtf', '.md') found within the given path."); + } + else if (documentationFilePaths.Length == 0) + { + result.Status = TestResultStatus.Warning; + var textFileObjects = textFilePaths.Select(_assetUtility.AssetPathToObject).ToArray(); + result.AddMessage("The following files have been found to match the documentation file format," + + " but may not be documentation in content", + null, textFileObjects); + } + else + { + result.Status = TestResultStatus.Pass; + var documentationFileObjects = documentationFilePaths.Select(_assetUtility.AssetPathToObject).ToArray(); + result.AddMessage("Found documentation files", null, documentationFileObjects); + } + + return result; + } + + private bool CouldBeDocumentation(string filePath) + { + if (filePath.EndsWith(".pdf")) + return true; + + using (var fs = File.Open(filePath, FileMode.Open)) + using (var bs = new BufferedStream(fs)) + using (var sr = new StreamReader(bs)) + { + string line; + while ((line = sr.ReadLine()) != null) + { + var mentionsDocumentation = line.IndexOf("documentation", StringComparison.OrdinalIgnoreCase) >= 0; + if (mentionsDocumentation) + return true; + } + } + + return false; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs.meta new file mode 100644 index 00000000..91155950 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 3c8425198983eda4c9b35aa0d59ea33c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckDocumentation.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs new file mode 100644 index 00000000..caa8ac60 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs @@ -0,0 +1,69 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; +using System.IO; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckPackageSize : ITestScript + { + private GenericTestConfig _config; + + public CheckPackageSize(GenericTestConfig config) + { + _config = config; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var packageSize = CalculatePackageSize(_config.ValidationPaths); + float packageSizeInGB = packageSize / (1024f * 1024f * 1024f); + float maxPackageSizeInGB = Constants.Uploader.MaxPackageSizeBytes / (1024f * 1024f * 1024f); + + if (packageSizeInGB - maxPackageSizeInGB >= 0.1f) + { + result.Status = TestResultStatus.Warning; + + result.AddMessage($"The uncompressed size of your package ({packageSizeInGB:0.#} GB) exceeds the maximum allowed package size of {maxPackageSizeInGB:0.#} GB. " + + $"Please make sure that the compressed .unitypackage size does not exceed the size limit."); + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("Your package does not exceed the maximum allowed package size!"); + } + + return result; + } + + private long CalculatePackageSize(string[] assetPaths) + { + long totalSize = 0; + + foreach (var path in assetPaths) + { + totalSize += CalculatePathSize(path); + } + + return totalSize; + } + + private long CalculatePathSize(string path) + { + long size = 0; + + var dirInfo = new DirectoryInfo(path); + if (!dirInfo.Exists) + return size; + + foreach (var file in dirInfo.EnumerateFiles()) + size += file.Length; + + foreach (var nestedDir in dirInfo.EnumerateDirectories()) + size += CalculatePathSize(nestedDir.FullName); + + return size; + } + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs.meta new file mode 100644 index 00000000..36ea8801 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a8601b99f4afa5049954f3a2dd5996d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckPackageSize.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs new file mode 100644 index 00000000..eab7aee5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs @@ -0,0 +1,217 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services.Validation; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator.TestMethods +{ + internal class CheckProjectTemplateAssets : ITestScript + { + private GenericTestConfig _config; + private IAssetUtilityService _assetUtility; + + // Constructor also accepts dependency injection of registered IValidatorService types + public CheckProjectTemplateAssets(GenericTestConfig config, IAssetUtilityService assetUtility) + { + _config = config; + _assetUtility = assetUtility; + } + + public TestResult Run() + { + var result = new TestResult() { Status = TestResultStatus.Undefined }; + + var assets = _assetUtility.GetObjectsFromAssets(_config.ValidationPaths, AssetType.All); + var invalidAssetsByGuid = CheckGuids(assets); + var invalidAssetsByPath = CheckPaths(assets); + + var hasIssues = invalidAssetsByGuid.Length > 0 + || invalidAssetsByPath.Length > 0; + + if (hasIssues) + { + result.Status = TestResultStatus.VariableSeverityIssue; + + if (invalidAssetsByPath.Length > 0) + { + result.AddMessage("The following assets were found to have an asset path which is common to project template asset paths. They should be renamed or moved:", null, invalidAssetsByPath); + } + + if (invalidAssetsByGuid.Length > 0) + { + result.AddMessage("The following assets were found to be using a GUID which is common to project template asset GUIDs. They should be assigned a new GUID:", null, invalidAssetsByGuid); + } + } + else + { + result.Status = TestResultStatus.Pass; + result.AddMessage("No common assets that might cause asset clashing were found!"); + } + + return result; + } + + private Object[] CheckGuids(IEnumerable assets) + { + var clashingAssets = new List(); + foreach (var asset in assets) + { + if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _)) + continue; + + if (CommonTemplateAssets.Any(x => x.Key.Equals(guid, System.StringComparison.OrdinalIgnoreCase))) + clashingAssets.Add(asset); + } + + return clashingAssets.ToArray(); + } + + private Object[] CheckPaths(IEnumerable assets) + { + var clashingAssets = new List(); + foreach (var asset in assets) + { + var assetPath = AssetDatabase.GetAssetPath(asset); + if (CommonTemplateAssets.Any(x => x.Value.Equals(assetPath, System.StringComparison.OrdinalIgnoreCase))) + clashingAssets.Add(asset); + } + + return clashingAssets.ToArray(); + } + + private Dictionary CommonTemplateAssets = new Dictionary() + { + {"3f9215ea0144899419cfbc0957140d3f", "Assets/DefaultVolumeProfile.asset"}, + {"3d4c13846a3e9bd4c8ccfbd0657ed847", "Assets/DefaultVolumeProfile.asset"}, + {"4cee8bca36f2ab74b8feb832747fa6f4", "Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset"}, + {"45a04f37e0f48c744acc0874c4a8918a", "Assets/Editor/com.unity.mobile.notifications/NotificationSettings.asset"}, + {"54a3a0570aebe8949bec4966f1376581", "Assets/HDRPDefaultResources/DefaultHDRISky.exr"}, + {"e93c35b24eb03c74284e7dc0b755bfcc", "Assets/HDRPDefaultResources/DefaultHDRPAsset.asset"}, + {"254320a857a30444da2c99496a186368", "Assets/HDRPDefaultResources/DefaultLookDevProfile.asset"}, + {"2bfa7b9d63fa79e4abdc033f54a868d2", "Assets/HDRPDefaultResources/DefaultSceneRoot.prefab"}, + {"f9e3ff5a1b8f49c4fa8686e68d2dadae", "Assets/HDRPDefaultResources/DefaultSceneRoot.prefab"}, + {"d87f7d7815073e840834a16a518c1237", "Assets/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset"}, + {"145290c901d58b343bdeb3b4362c9ff2", "Assets/HDRPDefaultResources/DefaultVFXResources.asset"}, + {"acc11144f57719542b5fa25f02e74afb", "Assets/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset"}, + {"582adbd84082fdb4faf7cd4beb1ccd14", "Assets/HDRPDefaultResources/HDRPDefaultSettings.asset"}, + {"2801c2ff7303a7543a8727f862f6c236", "Assets/HDRPDefaultResources/Sky and Fog Settings Profile.asset"}, + {"ea5c25297f0c0a04da0eabb1c26a7509", "Assets/HDRPDefaultResources/SkyFogSettingsProfile.asset"}, + {"3590b91b4603b465dbb4216d601bff33", "Assets/InputSystem_Actions.inputactions"}, + {"289c1b55c9541489481df5cc06664110", "Assets/InputSystem_Actions.inputactions"}, + {"dc70d2c4f369241dd99afd7c451b813e", "Assets/InputSystem_Actions.inputactions"}, + {"2bcd2660ca9b64942af0de543d8d7100", "Assets/InputSystem_Actions.inputactions"}, + {"052faaac586de48259a63d0c4782560b", "Assets/InputSystem_Actions.inputactions"}, + {"35845fe01580c41289b024647b1d1c53", "Assets/InputSystem_Actions.inputactions"}, + {"8124e5870f4fd4c779e7a5f994e84ad1", "Assets/OutdoorsScene.unity"}, + {"2dd802e4d37c65149922028d3e973832", "Assets/Presets/AudioCompressedInMemory.preset"}, + {"e18fd6ecd9cdb524ca99844f39b9d9ac", "Assets/Presets/AudioCompressedInMemory.preset"}, + {"86bcce7f5575b54408aa0f3a7d321039", "Assets/Presets/AudioStreaming.preset"}, + {"460e573eb8466884baaa0b8475505f83", "Assets/Presets/AudioStreaming.preset"}, + {"e8537455c6c08bd4e8bf0be3707da685", "Assets/Presets/Defaults/AlbedoTexture_Default.preset"}, + {"7a99f8aa944efe94cb9bd74562b7d5f9", "Assets/Presets/Defaults/AlbedoTexture_Default.preset"}, + {"0cd792cc87e492d43b4e95b205fc5cc6", "Assets/Presets/Defaults/AudioDecompressOnLoad_Default.preset"}, + {"e7689051185d12f4298e1ebb2693a29f", "Assets/Presets/Defaults/AudioDecompressOnLoad.preset"}, + {"463065d4f17d1d94d848aa127b94dd43", "Assets/Presets/Defaults/DirectionalLight_Default.preset"}, + {"c1cf8506f04ef2c4a88b64b6c4202eea", "Assets/Presets/Defaults/DirectionalLight_Default.preset"}, + {"8fa3055e2a1363246838debd20206d37", "Assets/Presets/Defaults/SSSSettings_Default.preset"}, + {"78830bb1431cab940b74be615e2a739f", "Assets/Presets/HDRTexture.preset"}, + {"14a57cf3b9fa1c74b884aa7e0dcf1faa", "Assets/Presets/NormalTexture.preset"}, + {"1d826a4c23450f946b19c20560595a1f", "Assets/Presets/NormalTexture.preset"}, + {"45f7b2e3c78185248b3adbb14429c2ab", "Assets/Presets/UtilityTexture.preset"}, + {"78fae3569c6c66c46afc3d9d4fb0b8d4", "Assets/Presets/UtilityTexture.preset"}, + {"9303d565bd8aa6948ba775e843320e4d", "Assets/Presets/UtilityTexture.preset"}, + {"34f54ff1ff9415249a847506b6f2fec5", "Assets/Scenes/PrefabEditingScene.unity"}, + {"cbfe36cfddfde964d9dfce63a355d5dd", "Assets/Scenes/samplescene.unity"}, + {"2cda990e2423bbf4892e6590ba056729", "Assets/Scenes/SampleScene.unity"}, + {"9fc0d4010bbf28b4594072e72b8655ab", "Assets/Scenes/SampleScene.unity"}, + {"3db1837cc97a95e4c98610966fac2b0b", "Assets/Scenes/SampleScene.unity"}, + {"3fc8acdd13e6c734bafef6554d6fdbcd", "Assets/Scenes/SampleScene.unity"}, + {"8c9cfa26abfee488c85f1582747f6a02", "Assets/Scenes/SampleScene.unity"}, + {"c850ee8c3b14cc8459e7e186857cf567", "Assets/Scenes/SampleScene.unity"}, + {"99c9720ab356a0642a771bea13969a05", "Assets/Scenes/SampleScene.unity"}, + {"d1c3109bdb54ad54c8a2b2838528e640", "Assets/Scenes/SampleScene.unity"}, + {"477cc4148fad3449482a3bc3178594e2", "Assets/Scenes/SampleSceneLightingSettings.lighting"}, + {"4eb578550bc4f824e97f0a72eac1f3a5", "Assets/Scripts/LookWithMouse.cs"}, + {"87f6dfceb3e39a947a312f7eeaa2a113", "Assets/Scripts/PlayerMovement.cs"}, + {"be76e5f14cfee674cb30b491fb72b09b", "Assets/Scripts/SimpleCameraController.cs"}, + {"6547d18b2bc62c94aa5ec1e87434da4e", "Assets/Scripts/SimpleCameraController.cs"}, + {"e8a636f62116c0a40bbfefdf876d4608", "Assets/Scripts/SimpleCameraController.cs"}, + {"14e519c409be4a1428028347410f5677", "Assets/Scripts/SimpleCameraController.cs"}, + {"a04c28107d77d5e42b7155783b8475b6", "Assets/Settings/Cockpit_Renderer.asset"}, + {"ab09877e2e707104187f6f83e2f62510", "Assets/Settings/DefaultVolumeProfile.asset"}, + {"238cd62f6b58cb04e9c94749c4a015a7", "Assets/Settings/DefaultVolumeProfile.asset"}, + {"5a9a2dc462c7bde4f86d0615a19c2c72", "Assets/Settings/DiffusionProfiles/BambooLeaves.asset"}, + {"78322c7f82657514ebe48203160e3f39", "Assets/Settings/Foliage.asset"}, + {"3e2e6bfc59709614ab90c0cd7d755e48", "Assets/Settings/HDRP Balanced.asset"}, + {"36dd385e759c96147b6463dcd1149c11", "Assets/Settings/HDRP High Fidelity.asset"}, + {"168a2336534e4e043b2a210b6f8d379a", "Assets/Settings/HDRP Performant.asset"}, + {"4594f4a3fb14247e192bcca6dc23c8ed", "Assets/Settings/HDRPDefaultResources/DefaultLookDevProfile.asset"}, + {"14b392ee213d25a48b1feddbd9f5a9be", "Assets/Settings/HDRPDefaultResources/DefaultSettingsVolumeProfile.asset"}, + {"879ffae44eefa4412bb327928f1a96dd", "Assets/Settings/HDRPDefaultResources/FoliageDiffusionProfile.asset"}, + {"b9f3086da92434da0bc1518f19f0ce86", "Assets/Settings/HDRPDefaultResources/HDRenderPipelineAsset.asset"}, + {"ac0316ca287ba459492b669ff1317a6f", "Assets/Settings/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset"}, + {"48e911a1e337b44e2b85dbc65b47a594", "Assets/Settings/HDRPDefaultResources/SkinDiffusionProfile.asset"}, + {"d03ed43fc9d8a4f2e9fa70c1c7916eb9", "Assets/Settings/Lit2DSceneTemplate.scenetemplate"}, + {"65bc7dbf4170f435aa868c779acfb082", "Assets/Settings/Mobile_Renderer.asset"}, + {"5e6cbd92db86f4b18aec3ed561671858", "Assets/Settings/Mobile_RPAsset.asset"}, + {"23cccccf13c3d4170a9b21e52a9bc86b", "Assets/Settings/Mobile/Mobile_High_ScreenRenderer.asset"}, + {"6e8f76111115f44e0a76c2bff3cec258", "Assets/Settings/Mobile/Mobile_Low_Renderer.asset"}, + {"aed30aee6a3ceae4090dadd1934d2ad0", "Assets/Settings/Mobile/Mobile_Low_ScreenRenderer.asset"}, + {"d7686b11d09df481bac3c76ecc5ea626", "Assets/Settings/Mobile/Mobile_Low.asset"}, + {"f288ae1f4751b564a96ac7587541f7a2", "Assets/Settings/PC_Renderer.asset"}, + {"4b83569d67af61e458304325a23e5dfd", "Assets/Settings/PC_RPAsset.asset"}, + {"42b230d443c6d6c4b89c47f97db59121", "Assets/Settings/PC/PC_High_ScreenRenderer.asset"}, + {"13ba41cd2fa191f43890b271bd110ed9", "Assets/Settings/PC/PC_Low_Renderer.asset"}, + {"a73f6fa069dd14a42b40cbb01bae63b4", "Assets/Settings/PC/PC_Low_ScreenRenderer.asset"}, + {"4eb9ff6b5314098428cfa0be7e36ccda", "Assets/Settings/PC/PC_Low.asset"}, + {"573ac53c334415945bf239de2c2f0511", "Assets/Settings/PlayerControllerFPS.prefab"}, + {"7ba2b06fb32e5274aad88925a5b8d3f5", "Assets/Settings/PostProcessVolumeProfile.asset"}, + {"424799608f7334c24bf367e4bbfa7f9a", "Assets/Settings/Renderer2D.asset"}, + {"183cbd347d25080429f42b520742bbd8", "Assets/Settings/SampleScenePostProcessingSettings.asset"}, + {"10fc4df2da32a41aaa32d77bc913491c", "Assets/Settings/SampleSceneProfile.asset"}, + {"a6560a915ef98420e9faacc1c7438823", "Assets/Settings/SampleSceneProfile.asset"}, + {"a123fc0ac58cb774e8592c925f167e7c", "Assets/Settings/SampleSceneSkyandFogSettings.asset"}, + {"26bdddf49760c61438938733f07fa2a2", "Assets/Settings/Skin.asset"}, + {"8ba92e2dd7f884a0f88b98fa2d235fe7", "Assets/Settings/SkyandFogSettingsProfile.asset"}, + {"4a8e21d5c33334b11b34a596161b9360", "Assets/Settings/UniversalRenderer.asset"}, + {"18dc0cd2c080841dea60987a38ce93fa", "Assets/Settings/UniversalRenderPipelineGlobalSettings.asset"}, + {"bdede76083021864d8ff8bf23b2f37f1", "Assets/Settings/UniversalRenderPipelineGlobalSettings.asset"}, + {"19ba41d7c0026c3459d37c2fe90c55a0", "Assets/Settings/UniversalRP-HighQuality.asset"}, + {"a31e9f9f9c9d4b9429ed0d1234e22103", "Assets/Settings/UniversalRP-LowQuality.asset"}, + {"d847b876476d3d6468f5dfcd34266f96", "Assets/Settings/UniversalRP-MediumQuality.asset"}, + {"681886c5eb7344803b6206f758bf0b1c", "Assets/Settings/UniversalRP.asset"}, + {"e634585d5c4544dd297acaee93dc2beb", "Assets/Settings/URP-Balanced-Renderer.asset"}, + {"e1260c1148f6143b28bae5ace5e9c5d1", "Assets/Settings/URP-Balanced.asset"}, + {"c40be3174f62c4acf8c1216858c64956", "Assets/Settings/URP-HighFidelity-Renderer.asset"}, + {"7b7fd9122c28c4d15b667c7040e3b3fd", "Assets/Settings/URP-HighFidelity.asset"}, + {"707360a9c581a4bd7aa53bfeb1429f71", "Assets/Settings/URP-Performant-Renderer.asset"}, + {"d0e2fc18fe036412f8223b3b3d9ad574", "Assets/Settings/URP-Performant.asset"}, + {"b62413aeefabaaa41a4b5a71dd7ae1ac", "Assets/Settings/VolumeProfiles/CinematicProfile.asset"}, + {"ac0c2cad5778d4544b6a690963e02fe3", "Assets/Settings/VolumeProfiles/DefaultVolumeProfile.asset"}, + {"f2d4d916a6612574cad220d125febbf2", "Assets/Settings/VolumeProfiles/LowQualityVolumeProfile.asset"}, + {"cef078630d63d0442a070f84d4f13735", "Assets/Settings/VolumeProfiles/MarketProfile.asset"}, + {"7ede9c9f109e5c442b7d29e54b4996fc", "Assets/Settings/VolumeProfiles/MediaOverrides.asset"}, + {"3532e98caae428047bcefe69a344f72c", "Assets/Settings/VolumeProfiles/OutlineEnabled.asset"}, + {"bfc08ba7e35de1a44bb84a32f1a693e1", "Assets/Settings/VolumeProfiles/ZenGardenProfile.asset"}, + {"59a34a3881431c246b3564a0f0ca5bb0", "Assets/Settings/Volumes/CinematicPhysicalCamera.asset"}, + {"03bc34b71695890468eb021c73b228db", "Assets/Settings/Volumes/ScreenshotsTimelineProfile.asset"}, + {"7f342610b85f4164f808a1f380dcc668", "Assets/Settings/Volumes/VolumeGlobal.asset"}, + {"bd6d234073408c44ca3828113aac655e", "Assets/Settings/Volumes/VolumeRoom1.asset"}, + {"d78a1b031ab26034eb6ec3cbc9fbcec3", "Assets/Settings/Volumes/VolumeRoom2.asset"}, + {"5727d3e07f75c3744b6cc8a1e55850a9", "Assets/Settings/Volumes/VolumeRoom2Skylight.asset"}, + {"06114ad16a0bc0a41957375ac3bf472e", "Assets/Settings/Volumes/VolumeRoom3.asset"}, + {"1584bf21cf81d5147aa00e8a2deaf2fb", "Assets/Settings/Volumes/VolumeRoom3Corridor.asset"}, + {"7bca3a07cdd522c4c8020832c20b3eae", "Assets/Settings/Volumes/VolumeRoom3Sitting.asset"}, + {"2872d90954412244a8b4a477b939c3ca", "Assets/Settings/XR/Loaders/Mock_HMD_Loader.asset"}, + {"f25758a0f79593d4a9b3ee30a17b4c2e", "Assets/Settings/XR/Loaders/Oculus_Loader.asset"}, + {"9e9f2958d1b4b4642ace1d0c7770650b", "Assets/Settings/XR/Settings/Mock_HMD_Build_Settings.asset"}, + {"290a6e6411d135049940bec2237b8938", "Assets/Settings/XR/Settings/Oculus_Settings.asset"}, + {"4c1640683c539c14080cfd43fbeffbda", "Assets/Settings/XR/XRGeneralSettings.asset"}, + {"93b439a37f63240aca3dd4e01d978a9f", "Assets/UniversalRenderPipelineGlobalSettings.asset"}, + {"38b35347542e5af4c9b140950c5b18db", "Assets/UniversalRenderPipelineGlobalSettings.asset"} + }; + } +} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs.meta new file mode 100644 index 00000000..59b111e5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f02d52a702c712e4e8089f7c2e65bae7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods/UnityPackage/CheckProjectTemplateAssets.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI.meta new file mode 100644 index 00000000..f401e9e8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0eed33a351c3c544ba6bf3cd29d24c26 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data.meta new file mode 100644 index 00000000..c3a170c9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 461bfd99d0923cd4a8dae2f440af1064 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions.meta new file mode 100644 index 00000000..93d41554 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d7d9c6cc805e072429392e7a378d2c9c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs new file mode 100644 index 00000000..676b70cf --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs @@ -0,0 +1,15 @@ +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal interface IValidatorResults + { + event Action OnResultsChanged; + event Action OnRequireSerialize; + + void LoadResult(ValidationResult result); + IEnumerable GetSortedTestGroups(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs.meta new file mode 100644 index 00000000..88224cb5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 91c62333b36d5ef47989289e8f90c056 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorResults.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs new file mode 100644 index 00000000..d439b0dd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs @@ -0,0 +1,31 @@ +using AssetStoreTools.Validator.Data; +using System; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal interface IValidatorSettings + { + event Action OnCategoryChanged; + event Action OnValidationTypeChanged; + event Action OnValidationPathsChanged; + event Action OnRequireSerialize; + + void LoadSettings(ValidationSettings settings); + + string GetActiveCategory(); + void SetActiveCategory(string category); + List GetAvailableCategories(); + + ValidationType GetValidationType(); + void SetValidationType(ValidationType validationType); + + List GetValidationPaths(); + void AddValidationPath(string path); + void RemoveValidationPath(string path); + void ClearValidationPaths(); + bool IsValidationPathValid(string path, out string error); + + IValidator CreateValidator(); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs.meta new file mode 100644 index 00000000..d8ed8d4d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: cc6516196465ac6469258ef8950da607 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs new file mode 100644 index 00000000..1dcafcec --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs @@ -0,0 +1,15 @@ +using AssetStoreTools.Validator.Data; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal interface IValidatorTest + { + int Id { get; } + string Name { get; } + string Description { get; } + ValidationType ValidationType { get; } + TestResult Result { get; } + + void SetResult(TestResult result); + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs.meta new file mode 100644 index 00000000..dd9750e0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d1e4d9ba8de8cfc4aa42786fbbc5037a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTest.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs new file mode 100644 index 00000000..81b8d8f1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs @@ -0,0 +1,12 @@ +using AssetStoreTools.Validator.Data; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal interface IValidatorTestGroup + { + string Name { get; } + TestResultStatus Status { get; } + IEnumerable Tests { get; } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs.meta new file mode 100644 index 00000000..ee7a6574 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: fa8735b7eb65d3147ab8bdbf922f36cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Abstractions/IValidatorTestGroup.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization.meta new file mode 100644 index 00000000..4122afef --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec536685238584f41bd268edaaf0ad7d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs new file mode 100644 index 00000000..4e75ed61 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; + +namespace AssetStoreTools.Validator.UI.Data.Serialization +{ + internal class ValidatorStateData + { + [JsonProperty("validation_settings")] + private ValidatorStateSettings _settings; + [JsonProperty("validation_results")] + private ValidatorStateResults _results; + + public ValidatorStateData() + { + _settings = new ValidatorStateSettings(); + _results = new ValidatorStateResults(); + } + + public ValidatorStateSettings GetSettings() + { + return _settings; + } + + public ValidatorStateResults GetResults() + { + return _results; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs.meta new file mode 100644 index 00000000..e8029528 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: da7a885e302cb6b43855b68f44f2c0fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateData.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs new file mode 100644 index 00000000..a72360ab --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json.Serialization; + +namespace AssetStoreTools.Validator.UI.Data.Serialization +{ + internal class ValidatorStateDataContractResolver : DefaultContractResolver + { + private static ValidatorStateDataContractResolver _instance; + public static ValidatorStateDataContractResolver Instance => _instance ?? (_instance = new ValidatorStateDataContractResolver()); + + private NamingStrategy _namingStrategy; + + private ValidatorStateDataContractResolver() + { + _namingStrategy = new SnakeCaseNamingStrategy(); + } + + protected override string ResolvePropertyName(string propertyName) + { + var resolvedName = _namingStrategy.GetPropertyName(propertyName, false); + if (resolvedName.StartsWith("_")) + return resolvedName.Substring(1); + + return resolvedName; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs.meta new file mode 100644 index 00000000..79f10135 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 60f0e8d9b2ab86547a288c337fb2be0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateDataContractResolver.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs new file mode 100644 index 00000000..3558822c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs @@ -0,0 +1,83 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.UI.Data.Serialization +{ + internal class ValidatorStateResults + { + // Primary data + [JsonProperty("validation_status")] + private ValidationStatus _status; + [JsonProperty("test_results")] + private SortedDictionary _results; + + // Secondary data + [JsonProperty("project_path")] + private string _projectPath; + [JsonProperty("had_compilation_errors")] + private bool _hadCompilationErrors; + + public ValidatorStateResults() + { + _projectPath = string.Empty; + _status = ValidationStatus.NotRun; + _hadCompilationErrors = false; + _results = new SortedDictionary(); + } + + public ValidationStatus GetStatus() + { + return _status; + } + + public void SetStatus(ValidationStatus status) + { + if (_status == status) + return; + + _status = status; + } + + public SortedDictionary GetResults() + { + return _results; + } + + public void SetResults(IEnumerable tests) + { + _results.Clear(); + foreach (var test in tests) + { + _results.Add(test.Id, test.Result); + } + } + + public string GetProjectPath() + { + return _projectPath; + } + + public void SetProjectPath(string projectPath) + { + if (_projectPath == projectPath) + return; + + _projectPath = projectPath; + } + + public bool GetHadCompilationErrors() + { + return _hadCompilationErrors; + } + + public void SetHadCompilationErrors(bool hadCompilationErrors) + { + if (_hadCompilationErrors == hadCompilationErrors) + return; + + _hadCompilationErrors = hadCompilationErrors; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs.meta new file mode 100644 index 00000000..d75bc1c1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a90c3acfa50e8da4aa3da2b9c669502d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateResults.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs new file mode 100644 index 00000000..27cee0e7 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs @@ -0,0 +1,63 @@ +using AssetStoreTools.Validator.Data; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Validator.UI.Data.Serialization +{ + internal class ValidatorStateSettings + { + [JsonProperty("category")] + private string _category; + [JsonProperty("validation_type")] + private ValidationType _validationType; + [JsonProperty("validation_paths")] + private List _validationPaths; + + public ValidatorStateSettings() + { + _category = string.Empty; + _validationType = ValidationType.UnityPackage; + _validationPaths = new List(); + } + + public string GetCategory() + { + return _category; + } + + public void SetCategory(string category) + { + if (_category == category) + return; + + _category = category; + } + + public ValidationType GetValidationType() + { + return _validationType; + } + + public void SetValidationType(ValidationType validationType) + { + if (validationType == _validationType) + return; + + _validationType = validationType; + } + + public List GetValidationPaths() + { + return _validationPaths; + } + + public void SetValidationPaths(List validationPaths) + { + if (_validationPaths.SequenceEqual(validationPaths)) + return; + + _validationPaths = validationPaths; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs.meta new file mode 100644 index 00000000..a11280ae --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d39d56313ade8a8409aafe95dc84f79a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/Serialization/ValidatorStateSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs new file mode 100644 index 00000000..38244c8f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs @@ -0,0 +1,137 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; +using AssetStoreTools.Validator.UI.Data.Serialization; +using AssetStoreTools.Validator.Utility; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal class ValidatorResults : IValidatorResults + { + private ValidatorStateResults _stateData; + + private IValidatorSettings _settings; + private IEnumerable _tests; + + private readonly TestResultStatus[] _priorityGroups = new TestResultStatus[] + { + TestResultStatus.Undefined, + TestResultStatus.Fail, + TestResultStatus.Warning + }; + + public event Action OnResultsChanged; + public event Action OnRequireSerialize; + + public ValidatorResults(IValidatorSettings settings, ValidatorStateResults stateData) + { + _settings = settings; + _stateData = stateData; + + _tests = GetAllTests(); + + Deserialize(); + } + + private IEnumerable GetAllTests() + { + var tests = new List(); + var testObjects = ValidatorUtility.GetAutomatedTestCases(ValidatorUtility.SortType.Alphabetical); + + foreach (var testObject in testObjects) + { + var testSource = new AutomatedTest(testObject); + var test = new ValidatorTest(testSource); + tests.Add(test); + } + + return tests; + } + + public void LoadResult(ValidationResult result) + { + if (result == null) + return; + + foreach (var test in _tests) + { + if (!result.Tests.Any(x => x.Id == test.Id)) + continue; + + var matchingResult = result.Tests.First(x => x.Id == test.Id); + test.SetResult(matchingResult.Result); + } + + OnResultsChanged?.Invoke(); + + Serialize(result); + } + + public IEnumerable GetSortedTestGroups() + { + var groups = new List(); + var testsByStatus = _tests + .Where(x => x.ValidationType == ValidationType.Generic || x.ValidationType == _settings.GetValidationType()) + .GroupBy(x => x.Result.Status).ToDictionary(x => x.Key, x => x.ToList()); + + foreach (var kvp in testsByStatus) + { + var group = new ValidatorTestGroup(kvp.Key, kvp.Value); + groups.Add(group); + } + + return SortGroups(groups); + } + + private IEnumerable SortGroups(IEnumerable unsortedGroups) + { + var sortedGroups = new List(); + var groups = unsortedGroups.OrderBy(x => x.Status).ToList(); + + // Select priority groups first + foreach (var priority in _priorityGroups) + { + var priorityGroup = groups.FirstOrDefault(x => x.Status == priority); + if (priorityGroup == null) + continue; + + sortedGroups.Add(priorityGroup); + groups.Remove(priorityGroup); + } + + // Add the rest + sortedGroups.AddRange(groups); + + return sortedGroups; + } + + private void Serialize(ValidationResult result) + { + _stateData.SetStatus(result.Status); + _stateData.SetResults(result.Tests); + _stateData.SetProjectPath(result.ProjectPath); + _stateData.SetHadCompilationErrors(result.HadCompilationErrors); + OnRequireSerialize?.Invoke(); + } + + private void Deserialize() + { + if (_stateData == null) + return; + + var serializedResults = _stateData.GetResults(); + foreach (var test in _tests) + { + if (!serializedResults.Any(x => x.Key == test.Id)) + continue; + + var matchingResult = serializedResults.First(x => x.Key == test.Id); + test.SetResult(matchingResult.Value); + } + + OnResultsChanged?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs.meta new file mode 100644 index 00000000..166ec320 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: bf2839f8b2340294aae39c2965039d2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorResults.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs new file mode 100644 index 00000000..d65ab0c1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs @@ -0,0 +1,236 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.UI.Data.Serialization; +using AssetStoreTools.Validator.Utility; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal class ValidatorSettings : IValidatorSettings + { + private ValidatorStateSettings _stateData; + + private string _category; + private ValidationType _validationType; + private List _validationPaths; + + public event Action OnCategoryChanged; + public event Action OnValidationTypeChanged; + public event Action OnValidationPathsChanged; + public event Action OnRequireSerialize; + + public ValidatorSettings(ValidatorStateSettings stateData) + { + _stateData = stateData; + + _category = string.Empty; + _validationType = ValidationType.UnityPackage; + _validationPaths = new List(); + + Deserialize(); + } + + public void LoadSettings(ValidationSettings settings) + { + if (settings == null) + return; + + var currentProjectValidationSettings = settings as CurrentProjectValidationSettings; + if (currentProjectValidationSettings == null) + throw new ArgumentException($"Only {nameof(CurrentProjectValidationSettings)} can be loaded"); + + _category = currentProjectValidationSettings.Category; + OnCategoryChanged?.Invoke(); + + _validationType = currentProjectValidationSettings.ValidationType; + OnValidationTypeChanged?.Invoke(); + + _validationPaths = currentProjectValidationSettings.ValidationPaths.ToList(); + OnValidationPathsChanged?.Invoke(); + + Serialize(); + } + + public string GetActiveCategory() + { + return _category; + } + + public void SetActiveCategory(string category) + { + if (category == _category) + return; + + _category = category; + Serialize(); + OnCategoryChanged?.Invoke(); + } + + public List GetAvailableCategories() + { + var categories = new HashSet(); + + var testData = ValidatorUtility.GetAutomatedTestCases(); + foreach (var test in testData) + { + if (test.CategoryInfo == null) + continue; + + foreach (var filter in test.CategoryInfo.Filter) + categories.Add(ConvertSlashToUnicodeSlash(filter)); + } + + return categories.OrderBy(x => x).ToList(); + } + + private string ConvertSlashToUnicodeSlash(string text) + { + return text.Replace('/', '\u2215'); + } + + public ValidationType GetValidationType() + { + return _validationType; + } + + public void SetValidationType(ValidationType validationType) + { + if (validationType == _validationType) + return; + + _validationType = validationType; + + Serialize(); + OnValidationTypeChanged?.Invoke(); + } + + public List GetValidationPaths() + { + return _validationPaths; + } + + public void AddValidationPath(string path) + { + if (string.IsNullOrEmpty(path)) + return; + + if (_validationPaths.Contains(path)) + return; + + // Prevent redundancy for new paths + var existingPath = _validationPaths.FirstOrDefault(x => path.StartsWith(x + "/")); + if (existingPath != null) + { + Debug.LogWarning($"Path '{path}' is already included with existing path: '{existingPath}'"); + return; + } + + // Prevent redundancy for already added paths + var redundantPaths = _validationPaths.Where(x => x.StartsWith(path + "/")).ToArray(); + foreach (var redundantPath in redundantPaths) + { + Debug.LogWarning($"Existing validation path '{redundantPath}' has been made redundant by the inclusion of new validation path: '{path}'"); + _validationPaths.Remove(redundantPath); + } + + _validationPaths.Add(path); + + Serialize(); + OnValidationPathsChanged?.Invoke(); + } + + public void RemoveValidationPath(string path) + { + if (!_validationPaths.Contains(path)) + return; + + _validationPaths.Remove(path); + + Serialize(); + OnValidationPathsChanged?.Invoke(); + } + + public void ClearValidationPaths() + { + if (_validationPaths.Count == 0) + return; + + _validationPaths.Clear(); + + Serialize(); + OnValidationPathsChanged?.Invoke(); + } + + public bool IsValidationPathValid(string path, out string error) + { + error = string.Empty; + + if (string.IsNullOrEmpty(path)) + { + error = "Path cannot be empty"; + return false; + } + + var isAssetsPath = path.StartsWith("Assets/") + || path.Equals("Assets"); + var isPackagePath = PackageUtility.GetPackageByManifestPath($"{path}/package.json", out _); + + if (!isAssetsPath && !isPackagePath) + { + error = "Selected path must be within the Assets folder or point to a root path of a package"; + return false; + } + + if (!Directory.Exists(path)) + { + error = "Path does not exist"; + return false; + } + + if (path.Split('/').Any(x => x.StartsWith(".") || x.EndsWith("~"))) + { + error = $"Path '{path}' cannot be validated as it is a hidden folder and not part of the Asset Database"; + return false; + } + + return true; + } + + public IValidator CreateValidator() + { + var settings = new CurrentProjectValidationSettings() + { + Category = _category, + ValidationType = _validationType, + ValidationPaths = _validationPaths + }; + + var validator = new CurrentProjectValidator(settings); + return validator; + } + + private void Serialize() + { + _stateData.SetCategory(_category); + _stateData.SetValidationType(_validationType); + _stateData.SetValidationPaths(_validationPaths); + + OnRequireSerialize?.Invoke(); + } + + private void Deserialize() + { + if (_stateData == null) + return; + + _category = _stateData.GetCategory(); + _validationType = _stateData.GetValidationType(); + foreach (var path in _stateData.GetValidationPaths()) + _validationPaths.Add(path); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs.meta new file mode 100644 index 00000000..f2f3aecb --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 89504c2259614a743a164c5c162a197a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorSettings.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs new file mode 100644 index 00000000..126cb4f1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs @@ -0,0 +1,28 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.TestDefinitions; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal class ValidatorTest : IValidatorTest + { + public int Id { get; private set; } + public string Name { get; private set; } + public string Description { get; private set; } + public ValidationType ValidationType { get; private set; } + public TestResult Result { get; private set; } + + public ValidatorTest(AutomatedTest source) + { + Id = source.Id; + Name = source.Title; + Description = source.Description; + ValidationType = source.ValidationType; + Result = source.Result; + } + + public void SetResult(TestResult result) + { + Result = result; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs.meta new file mode 100644 index 00000000..f209046b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 838e8d45ce997d8489185bc194dfcf25 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTest.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs new file mode 100644 index 00000000..b3620d86 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs @@ -0,0 +1,18 @@ +using AssetStoreTools.Validator.Data; +using System.Collections.Generic; + +namespace AssetStoreTools.Validator.UI.Data +{ + internal class ValidatorTestGroup : IValidatorTestGroup + { + public string Name => Status.ToString(); + public TestResultStatus Status { get; private set; } + public IEnumerable Tests { get; private set; } + + public ValidatorTestGroup(TestResultStatus status, IEnumerable tests) + { + Status = status; + Tests = tests; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs.meta new file mode 100644 index 00000000..c648a669 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 8f5d1fc9ff785904fb2e663e9232a7a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Data/ValidatorTestGroup.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements.meta new file mode 100644 index 00000000..9a9f507c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7ee7e5be29b8b184ba2abcd3ed38454e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs new file mode 100644 index 00000000..93f8f891 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs @@ -0,0 +1,50 @@ +using AssetStoreTools.Validator.UI.Data; +using System; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorButtonElement : VisualElement + { + // Data + private IValidatorSettings _settings; + + // UI + private Button _validateButton; + + public event Action OnValidate; + + public ValidatorButtonElement(IValidatorSettings settings) + { + _settings = settings; + _settings.OnValidationPathsChanged += ValidationPathsChanged; + + Create(); + Deserialize(); + } + + private void Create() + { + _validateButton = new Button(Validate) { text = "Validate" }; + _validateButton.AddToClassList("validator-validate-button"); + + Add(_validateButton); + } + + private void Validate() + { + OnValidate?.Invoke(); + } + + private void ValidationPathsChanged() + { + var validationPathsPresent = _settings.GetValidationPaths().Count > 0; + _validateButton.SetEnabled(validationPathsPresent); + } + + private void Deserialize() + { + ValidationPathsChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs.meta new file mode 100644 index 00000000..1e54d935 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 44fac105314df6341bf6a70fb3200baf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorButtonElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs new file mode 100644 index 00000000..73d6e70d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs @@ -0,0 +1,114 @@ +ο»Ώusing UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorDescriptionElement : VisualElement + { + private const string DescriptionFoldoutText = "Validate your package to ensure your content follows the chosen submission guidelines."; + private const string DescriptionFoldoutContentText = "The validations below do not cover all of the content standards, and passing all validations does not " + + "guarantee that your package will be accepted to the Asset Store.\n\n" + + "The tests are not obligatory for submitting your assets, but they can help avoid instant rejection by the " + + "automated vetting system, or clarify reasons of rejection communicated by the vetting team.\n\n" + + "For more information about the validations, view the message by expanding the tests or contact our support team."; + + private VisualElement _descriptionSimpleContainer; + private Label _descriptionSimpleLabel; + private Button _showMoreButton; + + private VisualElement _descriptionFullContainer; + private Button _showLessButton; + + public ValidatorDescriptionElement() + { + AddToClassList("validator-description"); + Create(); + } + + private void Create() + { + CreateSimpleDescription(); + CreateFullDescription(); + } + + private void CreateSimpleDescription() + { + _descriptionSimpleContainer = new VisualElement(); + _descriptionSimpleContainer.AddToClassList("validator-description-simple-container"); + + _descriptionSimpleLabel = new Label(DescriptionFoldoutText); + _descriptionSimpleLabel.AddToClassList("validator-description-simple-label"); + + _showMoreButton = new Button(ToggleFullDescription) { text = "Show more..." }; + _showMoreButton.AddToClassList("validator-description-show-button"); + _showMoreButton.AddToClassList("validator-description-hyperlink-button"); + + _descriptionSimpleContainer.Add(_descriptionSimpleLabel); + _descriptionSimpleContainer.Add(_showMoreButton); + + Add(_descriptionSimpleContainer); + } + + private void CreateFullDescription() + { + _descriptionFullContainer = new VisualElement(); + _descriptionFullContainer.AddToClassList("validator-description-full-container"); + + var validatorDescription = new Label() + { + text = DescriptionFoldoutContentText + }; + validatorDescription.AddToClassList("validator-description-full-label"); + + var submissionGuidelinesButton = new Button(OpenSubmissionGuidelinesUrl) + { + text = "Submission Guidelines" + }; + submissionGuidelinesButton.AddToClassList("validator-description-hyperlink-button"); + + var supportTicketButton = new Button(OpenSupportTicketUrl) + { + text = "Contact our Support Team" + }; + supportTicketButton.AddToClassList("validator-description-hyperlink-button"); + + _showLessButton = new Button(ToggleFullDescription) { text = "Show less..." }; + _showLessButton.AddToClassList("validator-description-hide-button"); + _showLessButton.AddToClassList("validator-description-hyperlink-button"); + + _descriptionFullContainer.Add(validatorDescription); + _descriptionFullContainer.Add(submissionGuidelinesButton); + _descriptionFullContainer.Add(supportTicketButton); + _descriptionFullContainer.Add(_showLessButton); + + _descriptionFullContainer.style.display = DisplayStyle.None; + Add(_descriptionFullContainer); + } + + private void ToggleFullDescription() + { + var displayFullDescription = _descriptionFullContainer.style.display == DisplayStyle.None; + + if (displayFullDescription) + { + _showMoreButton.style.display = DisplayStyle.None; + _descriptionFullContainer.style.display = DisplayStyle.Flex; + } + else + { + _showMoreButton.style.display = DisplayStyle.Flex; + _descriptionFullContainer.style.display = DisplayStyle.None; + } + } + + private void OpenSubmissionGuidelinesUrl() + { + Application.OpenURL(Constants.Validator.SubmissionGuidelinesUrl); + } + + private void OpenSupportTicketUrl() + { + Application.OpenURL(Constants.Validator.SupportTicketUrl); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs.meta new file mode 100644 index 00000000..14c5f70f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs.meta @@ -0,0 +1,10 @@ +ο»ΏfileFormatVersion: 2 +guid: 9866d77420d947ba852055eed2bac895 +timeCreated: 1653383883 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorDescriptionElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs new file mode 100644 index 00000000..6e4fe6dc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs @@ -0,0 +1,128 @@ +using AssetStoreTools.Utility; +using AssetStoreTools.Validator.UI.Data; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorPathsElement : VisualElement + { + // Data + private IValidatorSettings _settings; + + // UI + private ScrollView _pathBoxScrollView; + + public ValidatorPathsElement(IValidatorSettings settings) + { + AddToClassList("validator-paths"); + + _settings = settings; + _settings.OnValidationPathsChanged += ValidationPathsChanged; + + Create(); + Deserialize(); + } + + private void Create() + { + var pathSelectionRow = new VisualElement(); + pathSelectionRow.AddToClassList("validator-settings-selection-row"); + + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("validator-settings-selection-label-help-row"); + labelHelpRow.style.alignSelf = Align.FlexStart; + + Label pathLabel = new Label { text = "Validation paths" }; + Image pathLabelTooltip = new Image + { + tooltip = "Select the folder (or multiple folders) that your package consists of." + + "\n\nAll files and folders of your package should be contained within " + + "a single root folder that is named after your package " + + "(e.g. 'Assets/[MyPackageName]' or 'Packages/[MyPackageName]')" + + "\n\nIf your package includes special folders that cannot be nested within " + + "the root package folder (e.g. 'WebGLTemplates'), they should be added to this list " + + "together with the root package folder" + }; + + labelHelpRow.Add(pathLabel); + labelHelpRow.Add(pathLabelTooltip); + + var fullPathBox = new VisualElement() { name = "ValidationPaths" }; + fullPathBox.AddToClassList("validator-paths-box"); + + _pathBoxScrollView = new ScrollView { name = "ValidationPathsScrollView" }; + _pathBoxScrollView.AddToClassList("validator-paths-scroll-view"); + + VisualElement scrollViewBottomRow = new VisualElement(); + scrollViewBottomRow.AddToClassList("validator-paths-scroll-view-bottom-row"); + + var addExtraPathsButton = new Button(BrowsePath) { text = "Add a path" }; + addExtraPathsButton.AddToClassList("validator-paths-add-button"); + scrollViewBottomRow.Add(addExtraPathsButton); + + fullPathBox.Add(_pathBoxScrollView); + fullPathBox.Add(scrollViewBottomRow); + + pathSelectionRow.Add(labelHelpRow); + pathSelectionRow.Add(fullPathBox); + + Add(pathSelectionRow); + } + + private VisualElement CreateSinglePathElement(string path) + { + var validationPath = new VisualElement(); + validationPath.AddToClassList("validator-paths-path-row"); + + var folderPathLabel = new Label(path); + folderPathLabel.AddToClassList("validator-paths-path-row-input-field"); + + var removeButton = new Button(() => + { + _settings.RemoveValidationPath(path); + }); + removeButton.text = "X"; + removeButton.AddToClassList("validator-paths-path-row-remove-button"); + + validationPath.Add(folderPathLabel); + validationPath.Add(removeButton); + + return validationPath; + } + + private void BrowsePath() + { + string absolutePath = EditorUtility.OpenFolderPanel("Select a directory", "Assets", ""); + + if (string.IsNullOrEmpty(absolutePath)) + return; + + var relativePath = FileUtility.AbsolutePathToRelativePath(absolutePath, ASToolsPreferences.Instance.EnableSymlinkSupport); + + if (!_settings.IsValidationPathValid(relativePath, out var error)) + { + EditorUtility.DisplayDialog("Invalid path", error, "OK"); + return; + } + + _settings.AddValidationPath(relativePath); + } + + private void ValidationPathsChanged() + { + var validationPaths = _settings.GetValidationPaths(); + + _pathBoxScrollView.Clear(); + foreach (var path in validationPaths) + { + _pathBoxScrollView.Add(CreateSinglePathElement(path)); + } + } + + private void Deserialize() + { + ValidationPathsChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs.meta new file mode 100644 index 00000000..a0c57ef5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 370dcd3bc87ace647940b4b07147bf93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorPathsElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs new file mode 100644 index 00000000..f8e5113f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs @@ -0,0 +1,47 @@ +using AssetStoreTools.Validator.UI.Data; +using System.Linq; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorResultsElement : ScrollView + { + private IValidatorResults _results; + + public ValidatorResultsElement(IValidatorResults results) + { + AddToClassList("validator-test-list"); + + _results = results; + _results.OnResultsChanged += ResultsChanged; + + Create(); + } + + private void Create() + { + var groups = _results.GetSortedTestGroups().ToList(); + for (int i = 0; i < groups.Count; i++) + { + var groupElement = new ValidatorTestGroupElement(groups[i]); + Add(groupElement); + if (i != groups.Count - 1) + Add(CreateSeparator()); + } + } + + private void ResultsChanged() + { + Clear(); + Create(); + } + + private VisualElement CreateSeparator() + { + var groupSeparator = new VisualElement { name = "GroupSeparator" }; + groupSeparator.AddToClassList("validator-test-list-group-separator"); + + return groupSeparator; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs.meta new file mode 100644 index 00000000..9c934329 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 12f80f9088944a149a34b3f078ca859a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorResultsElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs new file mode 100644 index 00000000..b3f69d75 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs @@ -0,0 +1,96 @@ +using AssetStoreTools.Validator.UI.Data; +using UnityEditor.UIElements; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorSettingsElement : VisualElement + { + // Data + private IValidatorSettings _settings; + + // UI + private ToolbarMenu _categoryMenu; + private ValidatorPathsElement _validationPathsElement; + + public ValidatorSettingsElement(IValidatorSettings settings) + { + AddToClassList("validator-settings"); + + _settings = settings; + _settings.OnCategoryChanged += CategoryChanged; + + Create(); + Deserialize(); + } + + public void Create() + { + CreateCategorySelection(); + CreateValidationPathSelection(); + } + + private void CreateCategorySelection() + { + var categorySelectionBox = new VisualElement(); + categorySelectionBox.AddToClassList("validator-settings-selection-row"); + + VisualElement labelHelpRow = new VisualElement(); + labelHelpRow.AddToClassList("validator-settings-selection-label-help-row"); + + Label categoryLabel = new Label { text = "Category" }; + Image categoryLabelTooltip = new Image + { + tooltip = "Choose a base category of your package" + + "\n\nThis can be found in the Publishing Portal when creating the package listing or just " + + "selecting a planned one." + + "\n\nNote: Different categories could have different severities of several test cases." + }; + + labelHelpRow.Add(categoryLabel); + labelHelpRow.Add(categoryLabelTooltip); + + _categoryMenu = new ToolbarMenu { name = "CategoryMenu" }; + _categoryMenu.AddToClassList("validator-settings-selection-dropdown"); + + categorySelectionBox.Add(labelHelpRow); + categorySelectionBox.Add(_categoryMenu); + + // Append available categories + var categories = _settings.GetAvailableCategories(); + foreach (var category in categories) + { + _categoryMenu.menu.AppendAction(category, _ => _settings.SetActiveCategory(category)); + } + + // Append misc category + _categoryMenu.menu.AppendAction("Other", _ => _settings.SetActiveCategory(string.Empty)); + + Add(categorySelectionBox); + } + + private void CreateValidationPathSelection() + { + _validationPathsElement = new ValidatorPathsElement(_settings); + Add(_validationPathsElement); + } + + private void CategoryChanged() + { + var category = _settings.GetActiveCategory(); + if (!string.IsNullOrEmpty(category)) + _categoryMenu.text = category; + else + _categoryMenu.text = "Other"; + } + + private void Deserialize() + { + if (_settings == null) + return; + + // Set initial category + CategoryChanged(); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs.meta new file mode 100644 index 00000000..3ffe0c88 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 760d25556d755d544bece3a605adea09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorSettingsElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs new file mode 100644 index 00000000..c477c72b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs @@ -0,0 +1,239 @@ +ο»Ώusing AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.UI.Data; +using AssetStoreTools.Validator.Utility; +using System.Linq; +using UnityEditor.SceneManagement; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.SceneManagement; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorTestElement : VisualElement + { + // Data + private IValidatorTest _test; + private bool _isExpanded; + + // UI + private Button _testFoldoutButton; + private Label _testFoldoutExpandStateLabel; + private Label _testFoldoutLabel; + private Image _testStatusImage; + + private VisualElement _testContent; + private VisualElement _resultMessagesBox; + + public ValidatorTestElement(IValidatorTest test) + { + AddToClassList("validator-test"); + + _test = test; + + Create(); + Unexpand(); + + SubscribeToSceneChanges(); + } + + private void Create() + { + CreateFoldoutButton(); + CreateTestContent(); + CreateTestDescription(); + CreateTestMessages(); + } + + private void CreateFoldoutButton() + { + _testFoldoutButton = new Button(ToggleExpand) { name = _test.Name }; + _testFoldoutButton.AddToClassList("validator-test-foldout"); + + // Expander and Asset Label + VisualElement labelExpanderRow = new VisualElement { name = "labelExpanderRow" }; + labelExpanderRow.AddToClassList("validator-test-expander"); + + _testFoldoutExpandStateLabel = new Label { name = "ExpanderLabel", text = "β–Ί" }; + _testFoldoutExpandStateLabel.AddToClassList("validator-test-expander-arrow"); + + _testFoldoutLabel = new Label { name = "TestLabel", text = _test.Name }; + _testFoldoutLabel.AddToClassList("validator-text-expander-label"); + + labelExpanderRow.Add(_testFoldoutExpandStateLabel); + labelExpanderRow.Add(_testFoldoutLabel); + + _testStatusImage = new Image + { + name = "TestImage", + image = ValidatorUtility.GetStatusTexture(_test.Result.Status) + }; + + _testStatusImage.AddToClassList("validator-test-expander-image"); + + _testFoldoutButton.Add(labelExpanderRow); + _testFoldoutButton.Add(_testStatusImage); + + Add(_testFoldoutButton); + } + + private void CreateTestContent() + { + _testContent = new VisualElement(); + _testContent.AddToClassList("validator-test-content"); + Add(_testContent); + } + + private void CreateTestDescription() + { + var testCaseDescription = new TextField + { + name = "Description", + value = _test.Description, + isReadOnly = true, + multiline = true, + focusable = false, + doubleClickSelectsWord = false, + tripleClickSelectsLine = false + }; + testCaseDescription.AddToClassList("validator-test-content-textfield"); + +#if UNITY_2022_1_OR_NEWER + testCaseDescription.focusable = true; + testCaseDescription.selectAllOnFocus = false; + testCaseDescription.selectAllOnMouseUp = false; +#endif + + _testContent.Add(testCaseDescription); + } + + private void CreateTestMessages() + { + if (_test.Result.MessageCount == 0) + return; + + _resultMessagesBox = new VisualElement(); + _resultMessagesBox.AddToClassList("validator-test-content-result-messages"); + + switch (_test.Result.Status) + { + case TestResultStatus.Pass: + _resultMessagesBox.AddToClassList("validator-test-content-result-messages-pass"); + break; + case TestResultStatus.Warning: + _resultMessagesBox.AddToClassList("validator-test-content-result-messages-warning"); + break; + case TestResultStatus.Fail: + _resultMessagesBox.AddToClassList("validator-test-content-result-messages-fail"); + break; + } + + for (int i = 0; i < _test.Result.MessageCount; i++) + { + _resultMessagesBox.Add(CreateMessage(_test.Result.GetMessage(i))); + + if (i == _test.Result.MessageCount - 1) + continue; + + var separator = new VisualElement() { name = "Separator" }; + separator.AddToClassList("message-separator"); + _resultMessagesBox.Add(separator); + } + + _testContent.Add(_resultMessagesBox); + } + + private VisualElement CreateMessage(TestResultMessage message) + { + var resultText = message.GetText(); + var clickAction = message.GetClickAction(); + + var resultMessage = new VisualElement { name = "ResultMessageElement" }; + resultMessage.AddToClassList("validator-test-content-result-messages-content"); + + var informationButton = new Button(); + informationButton.AddToClassList("validator-test-content-result-messages-content-button"); + + if (clickAction != null) + { + informationButton.tooltip = clickAction.Tooltip; + informationButton.clicked += clickAction.Execute; + informationButton.SetEnabled(true); + } + + var informationDescription = new Label { name = "InfoDesc", text = resultText }; + informationDescription.AddToClassList("validator-test-content-result-messages-content-label"); + + informationButton.Add(informationDescription); + resultMessage.Add(informationButton); + + for (int i = 0; i < message.MessageObjectCount; i++) + { + var obj = message.GetMessageObject(i); + if (obj == null) + continue; + + if (obj.GetObject() == null) + continue; + + var objectField = new ObjectField() { objectType = obj.GetType(), value = obj.GetObject() }; + objectField.RegisterCallback>((evt) => + objectField.SetValueWithoutNotify(evt.previousValue)); + resultMessage.Add(objectField); + } + + return resultMessage; + } + + private void ToggleExpand() + { + if (!_isExpanded) + Expand(); + else + Unexpand(); + } + + private void Expand() + { + _testFoldoutExpandStateLabel.text = "β–Ό"; + _testFoldoutButton.AddToClassList("validator-test-foldout-expanded"); + _testContent.style.display = DisplayStyle.Flex; + _isExpanded = true; + } + + private void Unexpand() + { + _testFoldoutExpandStateLabel.text = "β–Ί"; + _testFoldoutButton.RemoveFromClassList("validator-test-foldout-expanded"); + _testContent.style.display = DisplayStyle.None; + _isExpanded = false; + } + + private void SubscribeToSceneChanges() + { + // Some result message objects only exist in specific scenes, + // therefore the UI must be refreshed on scene change + var windowToSubscribeTo = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + UnityAction sceneChanged = null; + sceneChanged = new UnityAction((_, __) => RefreshObjects(windowToSubscribeTo)); + EditorSceneManager.activeSceneChangedInEditMode += sceneChanged; + + void RefreshObjects(ValidatorWindow subscribedWindow) + { + // Remove callback if validator window instance changed + var activeWindow = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + if (subscribedWindow == null || subscribedWindow != activeWindow) + { + EditorSceneManager.activeSceneChangedInEditMode -= sceneChanged; + return; + } + + if (_resultMessagesBox != null) + _testContent.Remove(_resultMessagesBox); + + CreateTestMessages(); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs.meta new file mode 100644 index 00000000..dc3393cf --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 56c93e6f23ba5724da8cc38f832be4e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs new file mode 100644 index 00000000..7906a0dd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs @@ -0,0 +1,102 @@ +ο»Ώusing AssetStoreTools.Validator.UI.Data; +using AssetStoreTools.Validator.Utility; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Elements +{ + internal class ValidatorTestGroupElement : VisualElement + { + // Data + private IValidatorTestGroup _group; + private bool _isExpanded; + + // UI + private Button _groupFoldoutButton; + private Label _groupExpandStateLabel; + private Label _groupFoldoutLabel; + private Image _groupStatusImage; + + private VisualElement _groupContent; + private List _testElements; + + public ValidatorTestGroupElement(IValidatorTestGroup group) + { + AddToClassList("validator-test-list-group"); + + _group = group; + + Create(); + } + + private void Create() + { + CreateGroupFoldout(); + CreateGroupContent(); + } + + private void CreateGroupFoldout() + { + _groupFoldoutButton = new Button(ToggleExpand); + _groupFoldoutButton.AddToClassList("validator-test-list-group-expander"); + + _groupExpandStateLabel = new Label { name = "ExpanderLabel", text = "β–Ί" }; + _groupExpandStateLabel.AddToClassList("validator-test-list-group-expander-arrow"); + + _groupStatusImage = new Image + { + name = "TestImage", + image = ValidatorUtility.GetStatusTexture(_group.Status) + }; + _groupStatusImage.AddToClassList("validator-test-list-group-expander-image"); + + _groupFoldoutLabel = new Label() { text = $"{_group.Name} ({_group.Tests.Count()})" }; + _groupFoldoutLabel.AddToClassList("validator-test-list-group-expander-label"); + + _groupFoldoutButton.Add(_groupExpandStateLabel); + _groupFoldoutButton.Add(_groupStatusImage); + _groupFoldoutButton.Add(_groupFoldoutLabel); + + Add(_groupFoldoutButton); + } + + private void CreateGroupContent() + { + _groupContent = new VisualElement(); + _groupContent.AddToClassList("validator-test-list-group-content"); + + Add(_groupContent); + + _testElements = new List(); + foreach (var test in _group.Tests) + { + var testElement = new ValidatorTestElement(test); + _testElements.Add(testElement); + _groupContent.Add(testElement); + } + } + + private void ToggleExpand() + { + if (!_isExpanded) + Expand(); + else + Unexpand(); + } + + private void Expand() + { + _groupExpandStateLabel.text = "β–Ό"; + _groupContent.style.display = DisplayStyle.Flex; + _isExpanded = true; + } + + private void Unexpand() + { + _groupExpandStateLabel.text = "β–Ί"; + _groupContent.style.display = DisplayStyle.None; + _isExpanded = false; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs.meta new file mode 100644 index 00000000..40067410 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d7c7a8788d0ea324e843a475244d8e18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Elements/ValidatorTestGroupElement.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs new file mode 100644 index 00000000..cea8163d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs @@ -0,0 +1,56 @@ +ο»Ώusing AssetStoreTools.Utility; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services; +using AssetStoreTools.Validator.UI.Views; +using UnityEditor.UIElements; +using UnityEngine; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI +{ + + internal class ValidatorWindow : AssetStoreToolsWindow + { + protected override string WindowTitle => "Asset Store Validator"; + + private ICachingService _cachingService; + + private ValidatorTestsView _validationTestsView; + + protected override void Init() + { + minSize = new Vector2(350, 350); + + this.SetAntiAliasing(4); + + VisualElement root = rootVisualElement; + + // Clean it out, in case the window gets initialized again + root.Clear(); + + // Getting a reference to the USS Document and adding stylesheet to the root + root.styleSheets.Add(StyleSelector.ValidatorWindow.ValidatorWindowStyle); + root.styleSheets.Add(StyleSelector.ValidatorWindow.ValidatorWindowTheme); + + GetServices(); + ConstructWindow(); + } + + private void GetServices() + { + _cachingService = ValidatorServiceProvider.Instance.GetService(); + } + + private void ConstructWindow() + { + _validationTestsView = new ValidatorTestsView(_cachingService); + rootVisualElement.Add(_validationTestsView); + } + + public void Load(ValidationSettings settings, ValidationResult result) + { + _validationTestsView.LoadSettings(settings); + _validationTestsView.LoadResult(result); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs.meta new file mode 100644 index 00000000..e7a381b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: a0dc99b826513dd4f868f1cf405c3923 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/ValidatorWindow.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views.meta new file mode 100644 index 00000000..e90db603 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8a973656ad14b8941b790ed83c874e97 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs new file mode 100644 index 00000000..b25a8b44 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs @@ -0,0 +1,103 @@ +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services; +using AssetStoreTools.Validator.UI.Data; +using AssetStoreTools.Validator.UI.Data.Serialization; +using AssetStoreTools.Validator.UI.Elements; +using UnityEditor; +using UnityEngine.UIElements; + +namespace AssetStoreTools.Validator.UI.Views +{ + internal class ValidatorTestsView : VisualElement + { + // Data + private ValidatorStateData _stateData; + private IValidatorSettings _settings; + private IValidatorResults _results; + + private ICachingService _cachingService; + + // UI + private ValidatorSettingsElement _validatorSettingsElement; + private ValidatorButtonElement _validatorButtonElement; + private ValidatorResultsElement _validationTestListElement; + + public ValidatorTestsView(ICachingService cachingService) + { + _cachingService = cachingService; + + if (!_cachingService.GetCachedValidatorStateData(out _stateData)) + _stateData = new ValidatorStateData(); + + _settings = new ValidatorSettings(_stateData.GetSettings()); + _settings.OnRequireSerialize += Serialize; + + _results = new ValidatorResults(_settings, _stateData.GetResults()); + _results.OnRequireSerialize += Serialize; + + Create(); + } + + private void Create() + { + CreateValidatorDescription(); + CreateValidationSettings(); + CreateValidationButton(); + CreateValidatorResults(); + } + + private void CreateValidatorDescription() + { + var validationInfoElement = new ValidatorDescriptionElement(); + Add(validationInfoElement); + } + + private void CreateValidationSettings() + { + _validatorSettingsElement = new ValidatorSettingsElement(_settings); + Add(_validatorSettingsElement); + } + + private void CreateValidationButton() + { + _validatorButtonElement = new ValidatorButtonElement(_settings); + _validatorButtonElement.OnValidate += Validate; + Add(_validatorButtonElement); + } + + private void CreateValidatorResults() + { + _validationTestListElement = new ValidatorResultsElement(_results); + Add(_validationTestListElement); + } + + private void Validate() + { + var validator = _settings.CreateValidator(); + var result = validator.Validate(); + + if (result.Status == ValidationStatus.Failed) + { + EditorUtility.DisplayDialog("Validation failed", result.Exception.Message, "OK"); + return; + } + + LoadResult(result); + } + + public void LoadSettings(ValidationSettings settings) + { + _settings.LoadSettings(settings); + } + + public void LoadResult(ValidationResult result) + { + _results.LoadResult(result); + } + + private void Serialize() + { + _cachingService.CacheValidatorStateData(_stateData); + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs.meta new file mode 100644 index 00000000..cb6bfb46 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: c5e0da39c6638684c9d3faf8e62c60d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/UI/Views/ValidatorTestsView.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility.meta new file mode 100644 index 00000000..148dca9d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3bc3a78a4b494e44b75268ad1444ab81 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs new file mode 100644 index 00000000..0d58db5c --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs @@ -0,0 +1,142 @@ +ο»Ώusing AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services; +using AssetStoreTools.Validator.TestDefinitions; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using static AssetStoreTools.Constants; +using ValidatorConstants = AssetStoreTools.Constants.Validator; + +namespace AssetStoreTools.Validator.Utility +{ + internal static class ValidatorUtility + { + public enum SortType + { + Id, + Alphabetical + } + + public static ValidationTestScriptableObject[] GetAutomatedTestCases() => GetAutomatedTestCases(SortType.Id); + + public static ValidationTestScriptableObject[] GetAutomatedTestCases(SortType sortType) + { + string[] guids = AssetDatabase.FindAssets("t:AutomatedTestScriptableObject", new[] { ValidatorConstants.Tests.TestDefinitionsPath }); + ValidationTestScriptableObject[] tests = new ValidationTestScriptableObject[guids.Length]; + for (int i = 0; i < tests.Length; i++) + { + string testPath = AssetDatabase.GUIDToAssetPath(guids[i]); + AutomatedTestScriptableObject test = AssetDatabase.LoadAssetAtPath(testPath); + + tests[i] = test; + } + + switch (sortType) + { + default: + case SortType.Id: + tests = tests.Where(x => x != null).OrderBy(x => x.Id).ToArray(); + break; + case SortType.Alphabetical: + tests = tests.Where(x => x != null).OrderBy(x => x.Title).ToArray(); + break; + } + + return tests; + } + + public static MonoScript GenerateTestScript(string testName, ValidationType validationType) + { + var derivedType = nameof(ITestScript); + var configType = string.Empty; + var scriptPath = string.Empty; + switch (validationType) + { + case ValidationType.Generic: + configType = nameof(GenericTestConfig); + scriptPath = ValidatorConstants.Tests.GenericTestMethodsPath; + break; + case ValidationType.UnityPackage: + configType = nameof(GenericTestConfig); + scriptPath = ValidatorConstants.Tests.UnityPackageTestMethodsPath; + break; + default: + throw new System.Exception("Undefined validation type"); + } + + var newScriptPath = $"{scriptPath}/{testName}"; + if (!newScriptPath.EndsWith(".cs")) + newScriptPath += ".cs"; + + var existingScript = AssetDatabase.LoadAssetAtPath(newScriptPath); + if (existingScript != null) + return existingScript; + + var scriptContent = + $"using AssetStoreTools.Validator.Data;\n" + + $"using AssetStoreTools.Validator.TestDefinitions;\n\n" + + $"namespace AssetStoreTools.Validator.TestMethods\n" + + $"{{\n" + + $" internal class {testName} : {derivedType}\n" + + $" {{\n" + + $" private {configType} _config;\n\n" + + $" // Constructor also accepts dependency injection of registered {nameof(IValidatorService)} types\n" + + $" public {testName}({configType} config)\n" + + $" {{\n" + + $" _config = config;\n" + + $" }}\n\n" + + $" public {nameof(TestResult)} {nameof(ITestScript.Run)}()\n" + + $" {{\n" + + $" var result = new {nameof(TestResult)}() {{ {nameof(TestResult.Status)} = {nameof(TestResultStatus)}.{nameof(TestResultStatus.Undefined)} }};\n" + + $" return result;\n" + + $" }}\n" + + $" }}\n" + + $"}}\n"; + + File.WriteAllText(newScriptPath, scriptContent); + AssetDatabase.Refresh(); + return AssetDatabase.LoadAssetAtPath(newScriptPath); + } + + public static string GetLongestProjectPath() + { + var longPaths = GetProjectPaths(new string[] { "Assets", "Packages" }); + return longPaths.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur); + } + + public static IEnumerable GetProjectPaths(string[] rootPaths) + { + var longPaths = new List(); + var guids = AssetDatabase.FindAssets("*", rootPaths); + + foreach (var guid in guids) + { + var path = AssetDatabase.GUIDToAssetPath(guid); + longPaths.Add(path); + } + + return longPaths; + } + + public static Texture GetStatusTexture(TestResultStatus status) + { + var iconTheme = ""; + if (!EditorGUIUtility.isProSkin) + iconTheme = "_d"; + + switch (status) + { + case TestResultStatus.Pass: + return (Texture)EditorGUIUtility.Load($"{WindowStyles.ValidatorIconsPath}/success{iconTheme}.png"); + case TestResultStatus.Warning: + return (Texture)EditorGUIUtility.Load($"{WindowStyles.ValidatorIconsPath}/warning{iconTheme}.png"); + case TestResultStatus.Fail: + return (Texture)EditorGUIUtility.Load($"{WindowStyles.ValidatorIconsPath}/error{iconTheme}.png"); + default: + return (Texture)EditorGUIUtility.Load($"{WindowStyles.ValidatorIconsPath}/undefined{iconTheme}.png"); + } + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs.meta new file mode 100644 index 00000000..0c75432e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 24792af98b4d87746a4b945e2a45dc2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Utility/ValidatorUtility.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs new file mode 100644 index 00000000..e65f137f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs @@ -0,0 +1,108 @@ +using AssetStoreTools.Validator.Categories; +using AssetStoreTools.Validator.Data; +using AssetStoreTools.Validator.Services; +using AssetStoreTools.Validator.TestDefinitions; +using AssetStoreTools.Validator.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace AssetStoreTools.Validator +{ + internal abstract class ValidatorBase : IValidator + { + public ValidationSettings Settings { get; private set; } + + private CategoryEvaluator _categoryEvaluator; + private List _automatedTests; + + protected ICachingService CachingService; + + public ValidatorBase(ValidationSettings settings) + { + Settings = settings; + _categoryEvaluator = new CategoryEvaluator(settings?.Category); + + CachingService = ValidatorServiceProvider.Instance.GetService(); + + CreateAutomatedTestCases(); + } + + private void CreateAutomatedTestCases() + { + var testData = ValidatorUtility.GetAutomatedTestCases(ValidatorUtility.SortType.Alphabetical); + _automatedTests = new List(); + + foreach (var t in testData) + { + var test = new AutomatedTest(t); + _automatedTests.Add(test); + } + } + + protected abstract void ValidateSettings(); + protected abstract ValidationResult GenerateValidationResult(); + + public ValidationResult Validate() + { + try + { + ValidateSettings(); + } + catch (Exception e) + { + return new ValidationResult() { Status = ValidationStatus.Failed, Exception = e }; + } + + var result = GenerateValidationResult(); + return result; + } + + protected List GetApplicableTests(params ValidationType[] validationTypes) + { + return _automatedTests.Where(x => validationTypes.Any(y => y == x.ValidationType)).ToList(); + } + + protected ValidationResult RunTests(List tests, ITestConfig config) + { + var completedTests = new List(); + + for (int i = 0; i < tests.Count; i++) + { + var test = tests[i]; + + EditorUtility.DisplayProgressBar("Validating", $"Running validation: {i + 1} - {test.Title}", (float)i / _automatedTests.Count); + + test.Run(config); + + // Adjust result based on categories + var updatedStatus = _categoryEvaluator.Evaluate(test); + test.Result.Status = updatedStatus; + + // Add the result + completedTests.Add(test); + +#if AB_BUILDER + EditorUtility.UnloadUnusedAssetsImmediate(); +#endif + } + + EditorUtility.UnloadUnusedAssetsImmediate(); + EditorUtility.ClearProgressBar(); + + var projectPath = Application.dataPath.Substring(0, Application.dataPath.Length - "/Assets".Length); + var hasCompilationErrors = EditorUtility.scriptCompilationFailed; + var result = new ValidationResult() + { + Status = ValidationStatus.RanToCompletion, + Tests = completedTests, + ProjectPath = projectPath, + HadCompilationErrors = hasCompilationErrors + }; + + return result; + } + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs.meta new file mode 100644 index 00000000..a1f39f01 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2360246050affaa458413c6569c1f925 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/ValidatorBase.cs + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles.meta new file mode 100644 index 00000000..a5cbef6e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 21f473cb130d5f0458b2823b3a67f789 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss new file mode 100644 index 00000000..4a79ecdd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss @@ -0,0 +1,337 @@ +/* Validator Description */ + +.validator-description { + flex-direction: column; + flex-shrink: 0; + + margin: 10px 5px 2px 5px; + padding: 2px 4px; +} + +.validator-description-simple-container { + flex-direction: column; + flex-wrap: wrap; +} + +.validator-description-simple-label { + white-space: normal; +} + +.validator-description-full-container { + margin-top: 12px; +} + +.validator-description-full-label { + white-space: normal; + margin-bottom: 10px; +} + +.validator-description-hyperlink-button { + margin: 0; + padding: 0; + + align-self: flex-start; + cursor: link; +} + +.validator-description-show-button { + margin-top: 12px; +} + +.validator-description-hide-button { + margin-top: 12px; +} + +/* Validator Settings */ + +.validator-settings { + flex-direction: column; + flex-shrink: 0; + + margin: 0px 5px 2px 5px; + padding: 2px 4px; +} + +.validator-settings-selection-row { + flex-direction: row; + flex-grow: 1; + + margin-top: 10px; + padding: 0 3px 0 2px; +} + +.validator-settings-selection-label-help-row { + flex-direction: row; + flex-shrink: 1; + flex-grow: 0; + + align-self: center; + align-items: center; + justify-content: flex-start; + + width: 120px; +} + +.validator-settings-selection-label-help-row > Label { + -unity-font-style: bold; +} + +.validator-settings-selection-label-help-row > Image { + height: 16px; + width: 16px; +} + +.validator-settings-selection-dropdown { + flex-grow: 1; + flex-shrink: 1; + + align-self: stretch; + + margin-right: 0; + margin-left: 3px; + padding: 1px 4px; +} + +/* Validate Button */ + +.validator-validate-button { + align-self: stretch; + + height: 25px; + margin-left: 2px; +} + +/* Validation Paths */ + +.validator-paths { + flex-direction: column; + flex-grow: 1; + flex-shrink: 0; + + margin-bottom: 10px; + padding: 0; +} + +.validator-paths-box { + flex-grow: 1; + flex-direction: column; +} + +.validator-paths-scroll-view { + flex-grow: 1; + height: 100px; + margin-left: 3px; +} + +.validator-paths-scroll-view > .unity-scroll-view__content-viewport +{ + margin-left: 1px; +} + +.validator-paths-scroll-view > * > .unity-scroll-view__content-container +{ + padding: 0 0 0 0; +} + +.validator-paths-scroll-view > * > .unity-scroll-view__vertical-scroller +{ + margin: -1px 0; +} + +.validator-paths-scroll-view-bottom-row { + flex-direction: row-reverse; + margin: -1px 0 0 3px; +} + +.validator-paths-add-button { + margin: 3px 0 0 0; + align-self: center; +} + +.validator-paths-path-row { + flex-direction: row; + flex-grow: 1; + + margin-top: 2px; + padding: 0 5px 0 2px; +} + +.validator-paths-path-row-input-field { + flex-grow: 1; + flex-shrink: 1; + + padding-left: 5px; + + white-space: normal; + -unity-text-align: middle-left; +} + +.validator-paths-path-row-remove-button { + width: 20px; + height: 20px; + margin-left: 2px; + margin-right: 1px; + padding: 1px 0 0 0; +} + +/* Tests List & Groups */ + +.validator-test-list { + flex-grow: 1; + flex-shrink: 1; +} + +.validator-test-list-group-separator { + height: 2px; + margin: 5px 15px; +} + +.validator-test-list-group { + overflow: hidden; +} + +.validator-test-list-group-expander { + flex-direction: row; + flex-grow: 0; + flex-shrink: 0; + + align-items: center; + + min-width: 200px; + min-height: 30px; + + margin: 10px -1px 2px -1px; +} + +.validator-test-list-group-expander-arrow { + align-self: center; + + width: 30px; + height: 30px; + + margin: 0; + padding: 0; +} + +.validator-test-list-group-expander-image { + flex-shrink: 0; + flex-grow: 0; + + width: 17px; + height: 17px; + + margin: 0 7px 0 2px; +} + +.validator-test-list-group-expander-label { + font-size: 14px; +} + +.validator-test-list-group-content { + margin: -2px -2px -2px -2px; +} + +/* Validation Test */ + +.validator-test { + flex-direction: column; + flex-shrink: 0; + flex-grow: 0; + + padding: 2px 0; +} + +.validator-test-foldout { + flex-direction: row; + flex-grow: 1; + flex-shrink: 1; + + align-items: center; + justify-content: space-between; + + min-width: 200px; + min-height: 35px; + + margin: 0; + padding: 5px 10px; +} + +.validator-test-expander { + flex-direction: row; + flex-grow: 1; +} + +.validator-test-expander-arrow { + font-size: 11px; + align-self: center; + + width: 30px; + height: 30px; + + margin: 0; + padding: 0; +} + +.validator-text-expander-label { + flex-grow: 1; + flex-shrink: 1; + + -unity-text-align: middle-left; + -unity-font-style: bold; + white-space: normal; +} + +.validator-test-expander-image { + flex-shrink: 0; + + width: 14px; + height: 14px; + + margin: 0 10px; +} + +.validator-test-content { + flex-grow: 1; + flex-shrink: 0; + + margin: 0; + padding: 5px 30px; +} + +.validator-test-content-textfield { + white-space: normal; +} + +.validator-test-content-result-messages { + flex-direction: column; + flex-shrink: 0; + flex-grow: 0; + + margin: 10px 0 5px 0; + padding: 0 3px 3px 3px; +} + +.validator-test-content-result-messages-content { + flex-basis: auto; + flex-direction: column; + + margin-top: 3px; +} + +.validator-test-content-result-messages-content-button { + align-self: stretch; + + -unity-font-style: normal; + -unity-text-align: middle-left; + + margin: 0; +} + +.validator-test-content-result-messages-content-label { + white-space: normal; +} + +.validator-test-content-result-messages-separator { + height: 3px; + margin: 5px -3px 0 -3px; +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss.meta new file mode 100644 index 00000000..344d5f67 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 2c67a10c292c653428af654599fc15aa +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Styles/Style.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss new file mode 100644 index 00000000..47c13ea1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss @@ -0,0 +1,166 @@ +.primary-colors +{ + /* Light - lighter */ + background-color: rgb(220, 220, 220); + /* Light - middle */ + background-color: rgb(200, 200, 200); + /* Light - darker */ + background-color: rgb(180, 180, 180); + + /* Dark - lighter */ + background-color: rgb(78, 78, 78); + /* Dark - middle */ + background-color: rgb(68, 68, 68); + /* Dark - darker */ + background-color: rgb(58, 58, 58); + + /* Border color - light */ + border-color: rgb(200, 200, 200); + /* Border color - dark */ + border-color: rgb(33, 33, 33); +} + +/* Validator Description */ + +.validator-description-hyperlink-button { + color: rgb(68, 113, 229); + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.validator-description-hyperlink-button:hover { + color: rgb(68, 133, 229); +} + +.validator-description-hyperlink-button:active { + color: rgb(68, 93, 229); +} + +/* Validator Settings */ + +.validator-settings-selection-label-help-row > Image { + --unity-image: resource("d__Help@2x"); +} + +.validator-settings-selection-dropdown { + color: rgb(238, 238, 238); + background-color: rgb(88, 88, 88); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(36, 36, 36); +} + +/* Validation Paths */ + +.validator-paths-scroll-view { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(58, 58, 58); +} + +.validator-paths-scroll-view > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.validator-paths-path-row-input-field:hover { + background-color: rgb(78, 78, 78); +} + +/* Tests List & Groups */ + +.validator-test-list { + flex-grow: 1; + flex-shrink: 1; +} + +.validator-test-list-group-separator { + background-color: rgb(104, 104, 104); +} + +.validator-test-list-group-expander { + border-width: 0; + border-color: rgba(0, 0, 0, 0); + + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-list-group-expander-arrow { + color: rgb(104, 104, 104); +} + +.validator-test-list-group-expander-label { + color: rgb(255, 255, 255); + -unity-font-style: bold; +} + +/* Validation Test */ + +.validator-test-foldout { + border-width: 0; + border-radius: 0; + background-color: rgb(56, 56, 56); +} + +.validator-test-foldout:hover { + background-color: rgb(68, 68, 68); +} + +.validator-test-foldout:active { + background-color: rgb(48, 48, 48); +} + +.validator-test-foldout-expanded { + background-color: rgb(68, 68, 68); +} + +.validator-test-expander-arrow { + color: rgb(104, 104, 104); +} + +.validator-test-content { + background-color: rgb(68, 68, 68); +} + +.validator-test-content-textfield > .unity-base-field__input { + border-width: 0; + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages { + border-left-width: 2px; + border-color: rgb(33, 33, 33); + background-color: rgb(58, 58, 58); +} + +.validator-test-content-result-messages-pass { + border-color: rgb(40, 200, 40); +} + +.validator-test-content-result-messages-warning { + border-color: rgb(200, 140, 40); +} + +.validator-test-content-result-messages-fail { + border-color: rgb(200, 40, 40); +} + +.validator-test-content-result-messages-content-button { + border-width: 0; + border-radius: 0; + + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages-content-button:hover { + background-color: rgb(78, 78, 78); +} + +.validator-test-content-result-messages-content-button:active { + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages-separator { + background-color: rgb(68, 68, 68); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss.meta new file mode 100644 index 00000000..5c5344d2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d09164f0be2befd40aac764571737ff7 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeDark.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss new file mode 100644 index 00000000..2c29c721 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss @@ -0,0 +1,166 @@ +.primary-colors +{ + /* Light - lighter */ + background-color: rgb(220, 220, 220); + /* Light - middle */ + background-color: rgb(200, 200, 200); + /* Light - darker */ + background-color: rgb(180, 180, 180); + + /* Dark - lighter */ + background-color: rgb(50, 50, 50); + /* Dark - middle */ + background-color: rgb(28, 28, 28); + /* Dark - darker */ + background-color: rgb(0, 0, 0); + + /* Border color - light */ + border-color: rgb(200, 200, 200); + /* Border color - dark */ + border-color: rgb(33, 33, 33); +} + +/* Validator Description */ + +.validator-description-hyperlink-button { + color: rgb(68, 113, 229); + border-width: 0; + background-color: rgba(0, 0, 0, 0); +} + +.validator-description-hyperlink-button:hover { + color: rgb(68, 133, 229); +} + +.validator-description-hyperlink-button:active { + color: rgb(68, 93, 229); +} + +/* Validator Settings */ + +.validator-settings-selection-label-help-row > Image { + --unity-image: resource("_Help@2x"); +} + +.validator-settings-selection-dropdown { + color: rgb(9, 9, 9); + background-color: rgb(228, 228, 228); + + border-width: 1px; + border-radius: 3px; + border-color: rgb(178, 178, 178); +} + +/* Validation Paths */ + +.validator-paths-scroll-view { + border-width: 1px; + border-color: rgb(33, 33, 33); + background-color: rgb(180, 180, 180); +} + +.validator-paths-scroll-view > * > .unity-scroll-view__vertical-scroller { + border-right-width: 0; +} + +.validator-paths-path-row-input-field:hover { + background-color: rgb(200, 200, 200); +} + +/* Tests List & Groups */ + +.validator-test-list { + flex-grow: 1; + flex-shrink: 1; +} + +.validator-test-list-group-separator { + background-color: rgb(77, 77, 77); +} + +.validator-test-list-group-expander { + border-width: 0; + border-color: rgba(0, 0, 0, 0); + + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-list-group-expander-arrow { + color: rgb(77, 77, 77); +} + +.validator-test-list-group-expander-label { + color: rgb(48, 48, 48); + -unity-font-style: bold; +} + +/* Validation Test */ + +.validator-test-foldout { + border-width: 0; + border-radius: 0; + background-color: rgb(198, 198, 198); +} + +.validator-test-foldout:hover { + background-color: rgb(212, 212, 212); +} + +.validator-test-foldout:active { + background-color: rgb(180, 180, 180); +} + +.validator-test-foldout-expanded { + background-color: rgb(212, 212, 212); +} + +.validator-test-expander-arrow { + color: rgb(77, 77, 77); +} + +.validator-test-content { + background-color: rgb(212, 212, 212); +} + +.validator-test-content-textfield > .unity-base-field__input { + border-width: 0; + border-color: rgba(0, 0, 0, 0); + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages { + border-left-width: 2px; + border-color: rgb(33, 33, 33); + background-color: rgb(198, 198, 198); +} + +.validator-test-content-result-messages-pass { + border-color: rgb(40, 200, 40); +} + +.validator-test-content-result-messages-warning { + border-color: rgb(200, 140, 40); +} + +.validator-test-content-result-messages-fail { + border-color: rgb(200, 40, 40); +} + +.validator-test-content-result-messages-content-button { + border-width: 0; + border-radius: 0; + + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages-content-button:hover { + background-color: rgb(212, 212, 212); +} + +.validator-test-content-result-messages-content-button:active { + background-color: rgba(0, 0, 0, 0); +} + +.validator-test-content-result-messages-separator { + background-color: rgb(212, 212, 212); +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss.meta new file mode 100644 index 00000000..e2acc316 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 7404a65e6f9592846a20fd5190b12b1a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Styles/ThemeLight.uss + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests.meta new file mode 100644 index 00000000..45154436 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82d68ee644bbbb44183019f731e9f205 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic.meta new file mode 100644 index 00000000..e10e15e0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38036e7f211469848b7cf706e3a1febf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset new file mode 100644 index 00000000..c9b418f8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset @@ -0,0 +1,27 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Animation Clips + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 31 + Title: Check Animation Clips + Description: Animation Clips should not have the default name 'Take 001'. This + could lead to confusion when filtering assets by animation clips. + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 0 + AppliesToSubCategories: 1 + Filter: + - Animation + ValidationType: 0 + TestScript: {fileID: 11500000, guid: 7a28985886f182c4bacc89a44777c742, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset.meta new file mode 100644 index 00000000..23653ab3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Animation Clips.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: e0426dd01b5136a4ca1d42d312e12fad +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Animation Clips.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset new file mode 100644 index 00000000..356c3aed --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Audio Clipping + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 27 + Title: Check Audio Clipping + Description: 'Audio files should not peak above the defined dB threshold of -0.3db + + + Please + note that lossless audio files that are imported into Unity with their Compression + Format set to anything other than PCM can still fail the Validator. If such cases + arise, please export your audio files with extra headroom, or set the Compression + Format to PCM if applicable.' + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - Audio + TestScript: {fileID: 11500000, guid: f604db0353da0cb46bb048f5cd37186f, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset.meta new file mode 100644 index 00000000..d60afa99 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Audio Clipping.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 03c6cd398931b3e41b0784e8589e153f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Audio Clipping.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset new file mode 100644 index 00000000..079d75b0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Colliders + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 4 + Title: Check Colliders + Description: Prefabs with meshes inside them have to have colliders applied to + them, if the Prefabs are marked as Static. Please make sure you have appropriately + sized colliders applied to your prefabs. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 308b3d7b7a883b949a14f47cfd5c7ebe, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset.meta new file mode 100644 index 00000000..01c62f2a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Colliders.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 28ab5af444cf3c849800ed0d8f4a3102 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Colliders.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset new file mode 100644 index 00000000..f8aa71f2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Compressed Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 22 + Title: Check Compressed Files + Description: "Package should not contain nested .unitypackage or archive files + that obscure most of, or the entirety of the content.\n\n.unitypackage files + are acceptable for including setup preferences, settings, supplemental files + for other Asset Store products, or alternative render pipeline content\n\n.zip + files are acceptable if they are compressing files that do not natively function + in the Unity Editor. (For example, Blender, HTML Documentation, or Visual Studio + Projects). Such files should include 'source' in the file name (e.g. \"Blender_source.zip\" + or \"PSDSource.zip\")." + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 84b23febe0d923842aef73b95da5f25b, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset.meta new file mode 100644 index 00000000..47a8d65f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Compressed Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 53189e6e51235b14192c4d5b3145dd27 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Compressed Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset new file mode 100644 index 00000000..6154efa6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Empty Prefabs + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 5 + Title: Check Empty Prefabs + Description: Prefabs cannot be empty, please make sure that you set up your prefabs. + correctly. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - 2D + - 3D + - Animation + - Essentials + - Templates + - VFX + TestScript: {fileID: 11500000, guid: 8055bed9373283e4793463b90b42f08f, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset.meta new file mode 100644 index 00000000..6add0735 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Empty Prefabs.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 08790ea0ed0fd274fb1df75ccc32d415 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Empty Prefabs.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset new file mode 100644 index 00000000..ff0f7a46 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check File Menu Names + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 21 + Title: Check File Menu Names + Description: File menus should be placed under an existing menu, such as "Window/". + If no existing menus are a good fit, they should be placed under a custom menu + called "Tools". + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: d8e3b12ecc1fcd74d9a9f8d2b549fc63, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset.meta new file mode 100644 index 00000000..d3c997fe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check File Menu Names.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: eaf232919893db04b8e05e91f6815424 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + File Menu Names.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset new file mode 100644 index 00000000..2b332d74 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check LODs + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 17 + Title: Check LODs + Description: 'Prefabs containing meshes with ''LOD'' in their name must meet the + following requirements: + + - LOD Mesh must be referenced by an LOD Group Component + + - + LOD Mesh GameObject must be a child of an LOD Group Component.' + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - 3D + - Essentials + - Templates + TestScript: {fileID: 11500000, guid: 43b2158602f87704fa7b91561cfc8678, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset.meta new file mode 100644 index 00000000..56caee22 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check LODs.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: ad52ffa05767e9d4bb4d92093ad68b03 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + LODs.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset new file mode 100644 index 00000000..08e94263 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Line Endings + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 20 + Title: Check Line Endings + Description: Inconsistent line endings in scripts might lead to incorrect line + numbers in stacktraces and compiler errors. Many text editors can fix this using + Convert Line Endings menu commands. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 85885005d1c594f42826de3555e98365, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset.meta new file mode 100644 index 00000000..268b8094 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Line Endings.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 1e7b5480c1d8bda43ab4fa945939e243 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Line Endings.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset new file mode 100644 index 00000000..3d8a99ab --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Mesh Prefabs + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 2 + Title: Check Mesh Prefabs + Description: Each mesh should have a corresponding prefab set up with all variations + of the texture/mesh/material that you are providing. Please create prefabs for + all of your imported objects. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 3c3d0d642ac6a6a48aa124a93dae3734, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset.meta new file mode 100644 index 00000000..266cf689 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Mesh Prefabs.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 03b362b67028eb443b7ba8b84aedd5f2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Mesh Prefabs.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset new file mode 100644 index 00000000..0a69e354 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Missing Components in Assets + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 9 + Title: Check Missing Components in Assets + Description: We do not allow missing or broken material/texture/prefab/script connections + in your package. Please make sure none of your assets have missing components. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 22d8f814e2363e34ea220736a4042728, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset.meta new file mode 100644 index 00000000..ac6dbc21 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Assets.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 1a3d0b3827fc16347867bee335e8f4ea +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Missing Components in Assets.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset new file mode 100644 index 00000000..f5ecb1ad --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Missing Components in Scenes + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 10 + Title: Check Missing Components in Scenes + Description: We do not allow missing or broken material/texture/prefab/script connections + in your package. Please make sure none of your scene objects have missing components. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 511e76d0ebcb23d40a7b49dda0e2980f, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset.meta new file mode 100644 index 00000000..31f0f0a8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Missing Components in Scenes.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: bc2cb4e6635aa334ea4a52e2e3ce57c8 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Missing Components in Scenes.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset new file mode 100644 index 00000000..f5d9b0f6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Model Import Logs + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 32 + Title: Check Model Import Logs + Description: Model assets should work without issues. Please make sure that there + are no errors or warnings when these models are imported. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + ValidationType: 0 + TestScript: {fileID: 11500000, guid: 98f3ec209166855408eaf4abe5bff591, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset.meta new file mode 100644 index 00000000..9e8b2e6a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Import Logs.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: c889cdd91c2f41941a14363dad7a1a38 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Model Import Logs.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset new file mode 100644 index 00000000..dfd8345e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Model Orientation + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 7 + Title: Check Model Orientation + Description: 'Meshes should be facing the correct way. The proper facing is: Z + vector is forward, Y vector is up, X vector is right.' + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 56cdcdc41a80fbc46b5b2b83ec8d66d7, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset.meta new file mode 100644 index 00000000..2a8546fc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Orientation.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 45b2b11da67e8864aacc62d928524b4c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Model Orientation.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset new file mode 100644 index 00000000..e9c9aacd --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset @@ -0,0 +1,24 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Model Types + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 23 + Title: Check Model Types + Description: Mesh assets must be either .fbx, .dae, .abc, or .obj file types. + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 428b1fb838e6f5a469bbfd26ca3fbfd2, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset.meta new file mode 100644 index 00000000..07da7947 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Model Types.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: ffef800a102b0e04cae1a3b98549ef1b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Model Types.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset new file mode 100644 index 00000000..2f65269e --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Normal Map Textures + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 26 + Title: Check Normal Map Textures + Description: Textures that are assigned to Materials as Normal Maps should have + their import Texture Type set to 'Normal Map' + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: d55cea510248f814eb2194c2b53f88d2, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset.meta new file mode 100644 index 00000000..bd5f0812 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Normal Map Textures.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 241ad0174fcadb64da867011d196acbb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Normal Map Textures.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset new file mode 100644 index 00000000..5c34623f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Package Naming + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 33 + Title: Check Package Naming + Description: Your package and its contents should be named appropriately and not + artificially force themselves up the hierarchy within commonly used project folders. + This can happen when a file or a folder name starts with a special character + (such as an underscore). + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 0 + AppliesToSubCategories: 1 + Filter: + - Essentials + - Templates + ValidationType: 0 + TestScript: {fileID: 11500000, guid: afe9e04825c7d904981a54404b222290, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset.meta new file mode 100644 index 00000000..4cfa90e4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Package Naming.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 04098aa074d151b4a908dfa79dfddec3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Package Naming.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset new file mode 100644 index 00000000..62d55cde --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Particle Systems + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 25 + Title: Check Particle Systems + Description: All Particle Systems should be saved as Prefabs + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - VFX + TestScript: {fileID: 11500000, guid: 6a623f7988c75884bb17b169ccd3e993, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset.meta new file mode 100644 index 00000000..7120a201 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Particle Systems.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 87da7eaed3cee0d4b8ada0b500e3a958 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Particle Systems.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset new file mode 100644 index 00000000..676ae48f --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Path Lengths + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 28 + Title: Check Path Lengths + Description: Package content file paths should not be excessively lengthened. File + paths for assets must be under 140 characters + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: ae379305e9165e84584373a8272c09e7, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset.meta new file mode 100644 index 00000000..3a1b4cb3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Path Lengths.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 21f8ec0602ffac045b1f4a93f8a9b555 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Path Lengths.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset new file mode 100644 index 00000000..2cf336b9 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset @@ -0,0 +1,28 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Prefab Transforms + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 3 + Title: Check Prefab Transforms + Description: Prefabs must have their position/rotation set to 0, and their scale + set to 1. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - 3D + - Essentials + - Templates + TestScript: {fileID: 11500000, guid: f712c17a60bf2d049a4e61c8f79e56c2, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset.meta new file mode 100644 index 00000000..0c1957d2 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Prefab Transforms.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 700026f446833f649a3c63b33a90a295 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Prefab Transforms.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset new file mode 100644 index 00000000..fae309f1 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Script Compilation + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 29 + Title: Check Script Compilation + Description: Scripts in the package must compile successfully and not result in + compilation errors + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 59db88f43969db8499299bce7f4fb967, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset.meta new file mode 100644 index 00000000..b45fff62 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Script Compilation.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 339e21c955642a04289482aa923e10b6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Script Compilation.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset new file mode 100644 index 00000000..dcbd6093 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Shader Compilation + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 18 + Title: Check Shader Compilation + Description: Please make sure the shaders inside your package do not have errors + and compile successfully. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 7abb278a6082bde4391e0779394cb85b, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset.meta new file mode 100644 index 00000000..0d4b2202 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Shader Compilation.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 1450037453608204a989ff95dca62fae +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Shader Compilation.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset new file mode 100644 index 00000000..d676f146 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Texture Dimensions + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 24 + Title: Check Texture Dimensions + Description: Dimensions of textures, where appropriate, should have pixel counts + that are a power of 2 + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 073f1dacf3da34d4783140ae9d485d5f, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset.meta new file mode 100644 index 00000000..e07ac720 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Texture Dimensions.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: c23253393b8e28846b8e02aeaee7e152 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Texture Dimensions.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset new file mode 100644 index 00000000..8331d606 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Type Namespaces + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 19 + Title: Check Type Namespaces + Description: 'Types in your scripts (classes, interfaces, structs, enums) should + be nested under a namespace block to prevent them from being mistaken for other + potential types and for better organization as a whole. + + + It is not allowed + to nest your code under a Unity namespace.' + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + ValidationType: 0 + TestScript: {fileID: 11500000, guid: 279249fa7ef8c2446b3a9f013eeedbf0, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset.meta new file mode 100644 index 00000000..83ea2e70 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check Type Namespaces.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: dd110ee16e8de4d48a602349ed7a0b25 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Check + Type Namespaces.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset new file mode 100644 index 00000000..1a00c2fa --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset @@ -0,0 +1,27 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove Executable Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 14 + Title: Remove Executable Files + Description: Your package must not contain an .exe, installer programs or applications. + If your plugin requires an external program to run, please remove the installer + program from your package and write the instructions on how to download and install + the installer program in your documentation. + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 8e4450592cc60e54286ad089b66db94d, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset.meta new file mode 100644 index 00000000..35699560 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Executable Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: e996c53186de96e49a742d414648a809 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + Executable Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset new file mode 100644 index 00000000..cd2900fc --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove JPG Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 8 + Title: Remove JPG Files + Description: We do not allow texture images that are saved in lossy formats. Please + save all of your images as lossless format file types, such as PNG, TGA, or PSD. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - 2D + - 3D + - Animation + - Essentials + - VFX/Shaders + TestScript: {fileID: 11500000, guid: 5634a12b3a8544c4585bbc280ae59ce2, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset.meta new file mode 100644 index 00000000..d0a2eb2d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JPG Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 781021ae3aa6570468e08d78e3195127 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + JPG Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset new file mode 100644 index 00000000..bc5102e0 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove JavaScript Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 11 + Title: Remove JavaScript Files + Description: JavaScript / UnityScript files are not allowed, as they are no longer + supported. + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: ab1676bde9afba442b35fd3319c18063, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset.meta new file mode 100644 index 00000000..11b0f886 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove JavaScript Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: bf01c18b66907f54c99517f6a877e3e0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + JavaScript Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset new file mode 100644 index 00000000..954f6fd6 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove Lossy Audio Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 12 + Title: Remove Lossy Audio Files + Description: 'We do not recommend audio files that are saved as .mp3 or .ogg. Please + save all of your audio as lossless format file types, such as .wav. If you have + non-lossy alternative files to your lossy audio files, please make sure to name + them identically to avoid rejection. For example: ''shout.mp3'', ''shout.wav''. + Listing of the format in the file name is also allowed and accounted for by the + validator. For example: ''taunt MP3.mp3'', ''taunt WAV.wav''.' + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - Audio + - Essentials + - Templates + TestScript: {fileID: 11500000, guid: b7205a85061273a4eb50586f13f35d35, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset.meta new file mode 100644 index 00000000..10847924 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Lossy Audio Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: a48657926de5cfb47ac559a7108d03ee +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + Lossy Audio Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset new file mode 100644 index 00000000..8d3cc14a --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove Mixamo Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 15 + Title: Remove Mixamo Files + Description: We do not allow or accept packages files that were made with third-party + software, such as Mixamo, Fuse, etc. because these files are under licensing + that does not agree with the Asset Store End User License Agreement (EULA). + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: 9df432e52aa958b44bb5e20c13d16552, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset.meta new file mode 100644 index 00000000..8d2699e4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Mixamo Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: a0a44055f786ec64f86a07a214d5f831 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + Mixamo Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset new file mode 100644 index 00000000..14ff13fe --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove SpeedTree Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 16 + Title: Remove SpeedTree Files + Description: You cannot redistribute SpeedTree files on other marketplaces. Please + remove all SpeedTree files that are in this package. + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: e06bb7e0aa4f9944abc18281c002dff4, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset.meta new file mode 100644 index 00000000..cc98ca36 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove SpeedTree Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 305bbe67f7c644d18bc8a5b2273aa6a4 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + SpeedTree Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset new file mode 100644 index 00000000..1df19b9d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Remove Video Files + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 13 + Title: Remove Video Files + Description: You cannot include a video file in your package. Please upload your + video file to an online video hosting website (Youtube, Vimeo, etc.) and include + the link to the video in your written documentation. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + TestScript: {fileID: 11500000, guid: f99724c71b0de66419b5d6e8e9bfcc2d, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset.meta new file mode 100644 index 00000000..7f4074e5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove Video Files.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 893a0df188c2026438be48eed39b301f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/Generic/Remove + Video Files.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage.meta new file mode 100644 index 00000000..0a50cef4 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e978e836f2fb224fa11de94e913da49 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset new file mode 100644 index 00000000..af6ecc2b --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Demo Scenes + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 1 + Title: Check Demo Scenes + Description: If your product has content to show off, it should be displayed in + a demo scene. Please provide a practical demo with all of your assets set up. + If your asset is based on scripting or Editor extensions, please consider adding + a demo scene showcasing the asset or showing setup steps in the scene. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - 3D + - 2D + - Animation + - Essentials + - Templates + - VFX + ValidationType: 1 + TestScript: {fileID: 11500000, guid: f844c2dfa4669ff4eacf5591b544edaf, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset.meta new file mode 100644 index 00000000..d2a69967 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Demo Scenes.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: f108107be07f69045813d69eff580078 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check + Demo Scenes.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset new file mode 100644 index 00000000..6ce011e3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Documentation + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 6 + Title: Check Documentation + Description: If your asset contains any code (scripts, shaders) - we ask that you + include offline documentation in the format of pdf or rtf with your submission, + as it is mandatory for all packages that include scripts or other components + that require set up. Your documentation must be organized with a table of contents + and numbered, written in English and have no grammar mistakes. Create a setup + guide with a step-by-step tutorial (pdf or video), as well as a script reference + if users will need to do any coding. If your asset contains art (3D models, sprites) + and you used code to set up a demo scene, you may skip this step. + CategoryInfo: + IsFailFilter: 1 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: [] + ValidationType: 1 + TestScript: {fileID: 11500000, guid: 3c8425198983eda4c9b35aa0d59ea33c, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset.meta new file mode 100644 index 00000000..b6978e28 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Documentation.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: b03433f7977b29e4ca7e8d76393a6c26 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check + Documentation.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset new file mode 100644 index 00000000..e80b2c45 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Package Size + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 30 + Title: Check Package Size + Description: Package submissions should not be more than 6 GB in size + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 0 + AppliesToSubCategories: 1 + Filter: [] + ValidationType: 1 + TestScript: {fileID: 11500000, guid: a8601b99f4afa5049954f3a2dd5996d6, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset.meta new file mode 100644 index 00000000..eaf18964 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Package Size.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 25721b2d7384e5b4f936cf3b33b80a02 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check + Package Size.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset new file mode 100644 index 00000000..645117c3 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d813ff809ae82f643bf975031305d541, type: 3} + m_Name: Check Project Template Assets + m_EditorClassIdentifier: + HasBeenInitialized: 1 + Id: 34 + Title: Check Project Template Assets + Description: 'Assets in your package derived from project template assets should + be assigned a new GUID and be located under a different path. + + + This is to + minimize the risk of users accidentally overwriting their own assets when importing + your package. + + + Example commonly used asset: ''Assets/Scenes/SampleScene.unity''' + CategoryInfo: + IsFailFilter: 0 + IsInclusiveFilter: 1 + AppliesToSubCategories: 1 + Filter: + - Essentials + - Templates + ValidationType: 1 + TestScript: {fileID: 11500000, guid: f02d52a702c712e4e8089f7c2e65bae7, type: 3} diff --git a/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset.meta b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset.meta new file mode 100644 index 00000000..e8d4e6c5 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check Project Template Assets.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 5392e9de0549574419ff76897d1e0fa1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/Editor/Validator/Tests/UnityPackage/Check + Project Template Assets.asset + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/LICENSE.md b/Packages/com.unity.asset-store-tools/LICENSE.md new file mode 100644 index 00000000..b20d72b8 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/LICENSE.md @@ -0,0 +1,5 @@ +Asset Store Tools v2 copyright Β© 2025 Unity Technologies + +Source code of the package is licensed under the Unity Companion License (see https://unity.com/legal/licenses/unity-companion-license); otherwise licensed under the Unity Package Distribution License (see https://unity.com/legal/licenses/unity-package-distribution-license ) + +Unless expressly provided otherwise, the software under this license is made available strictly on an β€œAS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/LICENSE.md.meta b/Packages/com.unity.asset-store-tools/LICENSE.md.meta new file mode 100644 index 00000000..b20ebc6d --- /dev/null +++ b/Packages/com.unity.asset-store-tools/LICENSE.md.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: baeaa62ad0dc664428d6069db8fd986d +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/LICENSE.md + uploadId: 724584 diff --git a/Packages/com.unity.asset-store-tools/package.json b/Packages/com.unity.asset-store-tools/package.json new file mode 100644 index 00000000..8a64e184 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/package.json @@ -0,0 +1,11 @@ +{ + "name": "com.unity.asset-store-tools", + "displayName": "Asset Store Tools", + "version": "12.0.1", + "unity": "2019.4", + "description": "Whether you're a programmer, game designer, texture artist or 3D modeler, you're welcome to share your creations with everybody in the Unity developer community!", + "type": "tool", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.2.1" + } +} \ No newline at end of file diff --git a/Packages/com.unity.asset-store-tools/package.json.meta b/Packages/com.unity.asset-store-tools/package.json.meta new file mode 100644 index 00000000..c2682472 --- /dev/null +++ b/Packages/com.unity.asset-store-tools/package.json.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: fca7c22c787fbfd4cb0d7f186668631a +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 115 + packageName: Asset Store Publishing Tools + packageVersion: 12.0.1 + assetPath: Packages/com.unity.asset-store-tools/package.json + uploadId: 724584 diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 05905abf..b81600a2 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -21,6 +21,14 @@ }, "url": "https://packages.unity.com" }, + "com.unity.asset-store-tools": { + "version": "file:com.unity.asset-store-tools", + "depth": 0, + "source": "embedded", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "3.2.1" + } + }, "com.unity.burst": { "version": "1.8.19", "depth": 1, @@ -102,6 +110,13 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.nuget.newtonsoft-json": { + "version": "3.2.1", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, "com.unity.performance.profile-analyzer": { "version": "1.2.3", "depth": 1, diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index f76e40c1..12fdbe71 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -654,7 +654,8 @@ PlayerSettings: webGLWebAssemblyBigInt: 0 webGLCloseOnQuit: 0 webWasm2023: 0 - scriptingDefineSymbols: {} + scriptingDefineSymbols: + Standalone: UNITY_ASTOOLS_EXPERIMENTAL additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: {} From dce7bb1130e7ad168f3db93bc54d389bba692b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 5 Mar 2025 16:34:03 -0300 Subject: [PATCH 41/53] fix test for versions earlier than unity 6 --- .../Tests/Runtime/SceneManager_DisposeTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs index f072d6ea..105751a1 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/SceneManager_DisposeTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using System; using System.Collections; +using System.Threading.Tasks; using UnityEngine; using UnityEngine.TestTools; @@ -47,7 +48,7 @@ public IEnumerator Dipose_DuringUnload([ValueSource(nameof(_sceneManagerCreateFu [UnityTest] public IEnumerator Dispose_DuringTransition([ValueSource(nameof(_sceneManagerCreateFuncs))] Func managerCreateFunc, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.TransitionSceneParametersList))] SceneParameters sceneParameters, [ValueSource(typeof(SceneManagerTests), nameof(SceneManagerTests.LoadingSceneInfos))] ILoadSceneInfo loadingScene) { - async Awaitable Test() + async Task Test() { ISceneManager manager = managerCreateFunc(); await SceneManagerTests.LoadFirstScene(manager).Task; @@ -65,8 +66,9 @@ async Awaitable Test() canceled = true; } Assert.True(canceled); + return true; } - return Test(); + return new WaitTask(Test()); } } } \ No newline at end of file From 0c58ff50ff11b6139bb95ff80ace3afe826bca04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Wed, 5 Mar 2025 20:48:48 -0300 Subject: [PATCH 42/53] fix: add missing preprocessor directives to addressable code --- .../Tests/Runtime/StaticSceneManager_ExtensionTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs index 3bf29a14..1d0772f2 100644 --- a/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs +++ b/Packages/com.mygamedevtools.scene-loader/Tests/Runtime/StaticSceneManager_ExtensionTests.cs @@ -1,8 +1,10 @@ using System.Collections; using System.Threading.Tasks; using NUnit.Framework; +#if ENABLE_ADDRESSABLES using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; +#endif using UnityEngine.TestTools; namespace MyGameDevTools.SceneLoading.Tests @@ -11,6 +13,7 @@ public partial class StaticSceneManager_Tests { int[] _buildIndexes = new[] { 1, 2, 3 }; +#if ENABLE_ADDRESSABLES AssetReference[] _assetReferences; [OneTimeSetUp] @@ -24,6 +27,7 @@ public void AssetReferenceSetup() Addressables.Release(operationHandle); } +#endif [UnityTest] public IEnumerator Load_Extension_ByIndex() From 87da444f9dfb06bee9f7b4d37391a5968eb9b06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 20:56:45 -0300 Subject: [PATCH 43/53] feat: downgrade unity project, auto generate unity package --- .github/workflows/release-template.yml | 42 +- .../HDRenderPipelineGlobalSettings.asset | 787 +----------------- Assets/Scripts.meta | 8 + Assets/Scripts/Editor.meta | 8 + Assets/Scripts/Editor/Editor.asmdef | 16 + Assets/Scripts/Editor/Editor.asmdef.meta | 7 + Assets/Scripts/Editor/PackageExporter.cs | 19 + Assets/Scripts/Editor/PackageExporter.cs.meta | 11 + Packages/manifest.json | 5 +- Packages/packages-lock.json | 150 ++-- ProjectSettings/GraphicsSettings.asset | 14 +- ProjectSettings/PackageManagerSettings.asset | 2 - .../Settings.json | 2 + ProjectSettings/ProjectVersion.txt | 4 +- ProjectSettings/URPProjectSettings.asset | 2 +- ProjectSettings/VFXManager.asset | 9 +- 16 files changed, 203 insertions(+), 883 deletions(-) create mode 100644 Assets/Scripts.meta create mode 100644 Assets/Scripts/Editor.meta create mode 100644 Assets/Scripts/Editor/Editor.asmdef create mode 100644 Assets/Scripts/Editor/Editor.asmdef.meta create mode 100644 Assets/Scripts/Editor/PackageExporter.cs create mode 100644 Assets/Scripts/Editor/PackageExporter.cs.meta diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 38ad8d76..572aee61 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -28,11 +28,13 @@ jobs: with: fetch-depth: 0 persist-credentials: false + # Removes the git plugin from semantic release so it doesn't generate a new commit - name: βœ‚οΈ Disable semantic release commit if: ${{ inputs.blockReleaseCommit == true }} run: | cat .releaserc.json | jq 'del(.plugins[] | select(type == "array" and .[0] == "@semantic-release/git"))' .releaserc.json > .releaserc.json.tmp && mv .releaserc.json.tmp .releaserc.json + - name: πŸš€ Semantic Release id: release uses: cycjimmy/semantic-release-action@v4 @@ -41,6 +43,7 @@ jobs: ci: ${{ inputs.blockPullRequestRelease }} env: GH_TOKEN: ${{ secrets.githubToken }} + - name: πŸ“„ Summary run: | if [ '${{ steps.release.outputs.new_release_published }}' == 'true' ] && [ '${{ inputs.dryRun }}' == 'false' ]; then @@ -60,29 +63,56 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: πŸ“€ Extract Path id: extract-path run: | PACKAGE_PATH=$(jq -r '.plugins[] | select(type == "array" and .[0] == "@semantic-release/npm") | .[1].pkgRoot' .releaserc.json) echo "PACKAGE_PATH=$PACKAGE_PATH" >> $GITHUB_ENV + + - name: βš™οΈ Git Setup + run: | + git config --global user.name 'semantic-release-bot' + git config --global user.email 'semantic-release-bot@martynus.net' + - name: ✏️ Update package.json run: | jq '.version = "${{ env.releaseVersion }}"' $PACKAGE_PATH/package.json > package.json.tmp && mv package.json.tmp $PACKAGE_PATH/package.json + git commit --amend -a --no-edit + - name: πŸ“¦ Package UPM Branch id: package_upm run: | - git config --global user.name 'semantic-release-bot' - git config --global user.email 'semantic-release-bot@martynus.net' - git commit --amend -a --no-edit git branch -d upm &> /dev/null || echo upm branch not found git subtree split -P "$PACKAGE_PATH" -b upm git checkout upm - if [[ -d "Samples" ]]; then - git mv Samples Samples~ - rm -f Samples.meta + + - name: πŸ”„ Rename Samples Folder + run: | + if [[ -d "$PACKAGE_PATH/Samples" ]]; then + mv "$PACKAGE_PATH/Samples" "$PACKAGE_PATH/Samples~" + rm -f "$PACKAGE_PATH/Samples.meta" git commit --amend -a --no-edit fi + + - name: πŸš€ Push UPM Branch + run: | git push -f -u origin upm + + - name: πŸ“¦ Export Unity Package + uses: game-ci/unity-builder@v4 + with: + targetPlatform: StandaloneLinux64 + buildMethod: PackageExporter.ExportPackage + env: + UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} + + - name: πŸ—‚οΈ Upload Unity Package Artifact + uses: actions/upload-artifact@v4 + with: + name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} + path: com.mygamedevtools.scene-loader.unitypackage + - name: 🏷️ Create UPM Tag run: | git tag $TAG upm diff --git a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset index d5a880cc..dc8f4657 100644 --- a/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset +++ b/Assets/Rendering/HDRPDefaultResources/HDRenderPipelineGlobalSettings.asset @@ -12,54 +12,12 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 781cc897cf8675041a751163b51f97dd, type: 3} m_Name: HDRenderPipelineGlobalSettings m_EditorClassIdentifier: - m_CustomPostProcessOrdersSettings: - m_Version: 0 - m_BeforeTransparentCustomPostProcesses: - m_InjectionPoint: 0 - m_CustomPostProcessTypesAsString: [] - m_BeforeTAACustomPostProcesses: - m_InjectionPoint: 3 - m_CustomPostProcessTypesAsString: [] - m_BeforePostProcessCustomPostProcesses: - m_InjectionPoint: 1 - m_CustomPostProcessTypesAsString: [] - m_AfterPostProcessBlursCustomPostProcesses: - m_InjectionPoint: 4 - m_CustomPostProcessTypesAsString: [] - m_AfterPostProcessCustomPostProcesses: - m_InjectionPoint: 2 - m_CustomPostProcessTypesAsString: [] - beforeTransparentCustomPostProcesses: [] - beforePostProcessCustomPostProcesses: [] - afterPostProcessBlursCustomPostProcesses: [] - afterPostProcessCustomPostProcesses: [] - beforeTAACustomPostProcesses: [] - m_ShaderStrippingSetting: - m_Version: 0 - m_ExportShaderVariants: 1 - m_ShaderVariantLogLevel: 0 - m_StripRuntimeDebugShaders: 1 - m_ShaderVariantLogLevel: 0 - m_SupportRuntimeDebugDisplay: 0 - m_ExportShaderVariants: 1 - m_StripDebugVariants: 0 - DLSSProjectId: 000000 - useDLSSCustomProjectId: 0 - supportProbeVolumes: 0 - autoRegisterDiffusionProfiles: 1 - analyticDerivativeEmulation: 0 - analyticDerivativeDebugOutput: 0 - lensAttenuationMode: 0 - colorGradingSpace: 0 - m_ObsoleteDiffusionProfileSettingsList: [] - specularFade: 0 - rendererListCulling: 0 - m_ObsoleteDefaultVolumeProfile: {fileID: 0} - m_ObsoleteLookDevVolumeProfile: {fileID: 0} - m_ObsoleteRenderingPathDefaultCameraFrameSettings: + m_DefaultVolumeProfile: {fileID: 0} + m_LookDevVolumeProfile: {fileID: 0} + m_RenderingPathDefaultCameraFrameSettings: bitDatas: - data1: 5770166122053453 - data2: 12934340311651418136 + data1: 72198260625768269 + data2: 13763000477350330392 lodBias: 1 lodBiasMode: 0 lodBiasQualityLevel: 0 @@ -69,13 +27,12 @@ MonoBehaviour: sssQualityMode: 0 sssQualityLevel: 0 sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 msaaMode: 1 materialQuality: 0 - m_ObsoleteRenderingPathDefaultBakedOrCustomReflectionFrameSettings: + m_RenderingPathDefaultBakedOrCustomReflectionFrameSettings: bitDatas: - data1: 4643523019153229 - data2: 12898309406071980048 + data1: 135310754214733 + data2: 4539628428684460056 lodBias: 1 lodBiasMode: 0 lodBiasQualityLevel: 0 @@ -85,13 +42,12 @@ MonoBehaviour: sssQualityMode: 0 sssQualityLevel: 0 sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 msaaMode: 1 materialQuality: 0 - m_ObsoleteRenderingPathDefaultRealtimeReflectionFrameSettings: + m_RenderingPathDefaultRealtimeReflectionFrameSettings: bitDatas: - data1: 4638910381585229 - data2: 12898310333516513304 + data1: 139923391782733 + data2: 13763000465807638544 lodBias: 1 lodBiasMode: 0 lodBiasQualityLevel: 0 @@ -101,99 +57,15 @@ MonoBehaviour: sssQualityMode: 0 sssQualityLevel: 0 sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 msaaMode: 1 materialQuality: 0 - m_ObsoleteRenderingPath: - m_Version: 0 - m_Camera: - bitDatas: - data1: 5770166122053453 - data2: 12934340311651418136 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - m_CustomOrBakedReflection: - bitDatas: - data1: 4643523019153229 - data2: 12898309406071980048 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - m_RealtimeReflection: - bitDatas: - data1: 4638910381585229 - data2: 12898310333516513304 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - m_Settings: - m_SettingsList: - m_List: - - rid: 3368384739993452858 - - rid: 3368384739993452859 - - rid: 3368384739993452860 - - rid: 3368384739993452861 - - rid: 3368384739993452862 - - rid: 3368384739993452863 - - rid: 3368384739993452864 - - rid: 3368384739993452865 - - rid: 3368384739993452866 - - rid: 3368384739993452867 - - rid: 3368384739993452868 - - rid: 3368384739993452869 - - rid: 3368384739993452870 - - rid: 3368384739993452871 - - rid: 3368384739993452872 - - rid: 3368384739993452873 - - rid: 3368384739993452874 - - rid: 3368384739993452875 - - rid: 3368384739993452876 - - rid: 3368384739993452877 - - rid: 3368384739993452878 - - rid: 3368384739993452879 - - rid: 3368384739993452880 - - rid: 3368384739993452881 - - rid: 3368384739993452882 - - rid: 3368384739993452883 - - rid: 3368384739993452884 - - rid: 3368384739993452885 - - rid: 3368384739993452886 - - rid: 3368384739993452887 - - rid: 3368384739993452888 - - rid: 3368384739993452889 - - rid: 3368384739993452890 - m_RuntimeSettings: - m_List: [] - renderingLayerNames: - - Default + m_RenderPipelineResources: {fileID: 0} + m_RenderPipelineRayTracingResources: {fileID: 0} + beforeTransparentCustomPostProcesses: [] + beforePostProcessCustomPostProcesses: [] + afterPostProcessBlursCustomPostProcesses: [] + afterPostProcessCustomPostProcesses: [] + beforeTAACustomPostProcesses: [] lightLayerName0: lightLayerName1: lightLayerName2: @@ -210,615 +82,18 @@ MonoBehaviour: decalLayerName5: decalLayerName6: decalLayerName7: + shaderVariantLogLevel: 0 + lensAttenuationMode: 0 + diffusionProfileSettingsList: [] + rendererListCulling: 0 + DLSSProjectId: 000000 + useDLSSCustomProjectId: 0 + supportProbeVolumes: 0 + supportRuntimeDebugDisplay: 0 apvScenesData: - obsoleteSceneBounds: - m_Keys: [] - m_Values: [] - obsoleteHasProbeVolumes: - m_Keys: [] - m_Values: + serializedBounds: [] + serializedHasVolumes: [] + serializedProfiles: [] + serializedBakeSettings: [] + serializedBakingSets: [] m_Version: 14 - references: - version: 2 - RefIds: - - rid: 3368384739993452858 - type: {class: HDRPRayTracingResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_ReflectionRayTracingRT: {fileID: 4807578003741378534, guid: 1a500e5079fba734aa90fe92e70ea131, type: 3} - m_ReflectionRayTracingCS: {fileID: 7200000, guid: 591207652a75a4844a89c0b9f45a61f2, type: 3} - m_ReflectionBilateralFilterCS: {fileID: 7200000, guid: 07c445e7aa373284a9cc1584ca9b3f84, type: 3} - m_ShadowRayTracingRT: {fileID: 4807578003741378534, guid: 6f93cb4dc095de14993f8d2baa972d5b, type: 3} - m_ContactShadowRayTracingRT: {fileID: 4807578003741378534, guid: acaf840af875ab541b8f10069b7444c8, type: 3} - m_ShadowRayTracingCS: {fileID: 7200000, guid: fc95b5dff16ba594896e211a389c03fc, type: 3} - m_ShadowFilterCS: {fileID: 7200000, guid: f71fd853a538bf74e9e5a7228fc14dae, type: 3} - m_ForwardRayTracing: {fileID: 4807578003741378534, guid: d3a89a2d3f73b3e4da6f191e844fe68c, type: 3} - m_LightClusterBuildCS: {fileID: 7200000, guid: c0625ea908b52854bbf1d456e34026e4, type: 3} - m_LightClusterDebugS: {fileID: 4800000, guid: c4d81c6e573560444bb1ea11ae4acfcb, type: 3} - m_LightClusterDebugCS: {fileID: 7200000, guid: d48a3a5496d98a44c89f335934805d10, type: 3} - m_IndirectDiffuseRayTracingOffRT: {fileID: 4807578003741378534, guid: fbcaf423d9f8e3843b2c046420608293, type: 3} - m_IndirectDiffuseRayTracingL1RT: {fileID: 4807578003741378534, guid: 653044b9878c5764e818b20399112284, type: 3} - m_IndirectDiffuseRaytracingL2RT: {fileID: 4807578003741378534, guid: 866a72c4868acec4088b0956b9ca73f9, type: 3} - m_IndirectDiffuseRayTracingCS: {fileID: 7200000, guid: c5ad968b7cd39114d85dd860b3809087, type: 3} - m_AoRayTracingRT: {fileID: 4807578003741378534, guid: 82dc8cd069971d2488c502b0f32b94fb, type: 3} - m_AoRayTracingCS: {fileID: 7200000, guid: 10c05366baf9b0a44a827f3ef890b9e6, type: 3} - m_SubSurfaceRayTracingRT: {fileID: 4807578003741378534, guid: b29a18f967c92364492508dddf78cff7, type: 3} - m_SubSurfaceRayTracingCS: {fileID: 7200000, guid: 4e5684a8dba46fe42a47642f9b0a6b89, type: 3} - m_SimpleDenoiserCS: {fileID: 7200000, guid: 74a980f1da9a4f842996035350fe756c, type: 3} - m_ReflectionDenoiserCS: {fileID: 7200000, guid: 1b12fb238086d0f49983b4aa72768349, type: 3} - m_DiffuseShadowDenoiserCS: {fileID: 7200000, guid: 9af806eab5889a74dad838edc9b07d07, type: 3} - m_ReblurPreBlurCS: {fileID: 7200000, guid: 0be88ddf5240d49468d9159340465bfd, type: 3} - m_ReblurTemporalAccumulationCS: {fileID: 7200000, guid: 11794ae415a38c747ba65d57d1bb60f9, type: 3} - m_ReblurMipGenerationCS: {fileID: 7200000, guid: 44195ddb6d9240646847cbf4f38dfa98, type: 3} - m_ReblurHistoryFixCS: {fileID: 7200000, guid: 4cc204b99166a9c40819bc04927c4feb, type: 3} - m_ReblurBlurCS: {fileID: 7200000, guid: cff077c60ac76074893014e2f49e3159, type: 3} - m_ReblurPostBlurCS: {fileID: 7200000, guid: 965700f9b9e0fec4bb31415ae91f0e09, type: 3} - m_ReblurCopyHistoryCS: {fileID: 7200000, guid: 0d5230c403883b84cbf9d1d3b9e57beb, type: 3} - m_ReblurTemporalStabilizationCS: {fileID: 7200000, guid: 4feaa605aeff33840b659850ce6bfcc2, type: 3} - m_GBufferRayTracingRT: {fileID: 4807578003741378534, guid: e4c61a77b91f35845bbb546b848b18e5, type: 3} - m_DeferredRayTracingCS: {fileID: 7200000, guid: 6e5ef632062bc484f812c7976f450ed1, type: 3} - m_PathTracingRT: {fileID: 4807578003741378534, guid: c4f4525a058009a409fea974f9ad8d03, type: 3} - m_PathTracingSkySamplingDataCS: {fileID: 7200000, guid: 8ef71a4b666992544ac5575a0e599a68, type: 3} - m_RayMarchingCS: {fileID: 7200000, guid: 78d9a89700295a4418d0921bf27e1857, type: 3} - m_RayBinningCS: {fileID: 7200000, guid: cddcb515ffe9a914893d6d8fc1d85454, type: 3} - m_CountTracedRaysCS: {fileID: 7200000, guid: e1f3fa867f1dfbd4ab7dd4d39d2b96d8, type: 3} - m_ReflectionFilterMappingTexture: {fileID: 2800000, guid: 82eec49626a00b047ba86244607816c8, type: 3} - m_RtasDebugRT: {fileID: 4807578003741378534, guid: 7f98079d20376fd4f8590d58be99ab0d, type: 3} - - rid: 3368384739993452859 - type: {class: RenderingPathFrameSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_Camera: - bitDatas: - data1: 5770166122053453 - data2: 12934340311651418136 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - m_CustomOrBakedReflection: - bitDatas: - data1: 4643523019153229 - data2: 12898309406071980048 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - m_RealtimeReflection: - bitDatas: - data1: 4638910381585229 - data2: 12898310333516513304 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - sssCustomDownsampleSteps: 0 - msaaMode: 1 - materialQuality: 0 - - rid: 3368384739993452860 - type: {class: HDRenderPipelineEditorTextures, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_MoonAlbedo: {fileID: 2800000, guid: cce9f0cf7e606e547a7317aedb4ad6d9, type: 3} - - rid: 3368384739993452861 - type: {class: WaterSystemGlobalSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 1 - m_EnableMaskAndCurrentWaterDecals: 0 - - rid: 3368384739993452862 - type: {class: HDRenderPipelineEditorShaders, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_GpuInlineDebugDrawerLine: {fileID: 4800000, guid: 039c5248164c71b4aa6d780131c1bfaf, type: 3} - m_AutodeskInteractive: {fileID: 4800000, guid: 7252379db4c18b641b517f2c91bb57e1, type: 3} - m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: ee2ce0be66f45d9449d71ba9b49c2acd, type: 3} - m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 29c4adff654862b40a2e9fb2015a42c3, type: 3} - m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 4819724840ee9444f9da841b477038ce, type: 3} - m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: d81c74dd5f463104ca482aa23ef2c798, type: 3} - - rid: 3368384739993452863 - type: {class: AnalyticDerivativeSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_AnalyticDerivativeEmulation: 0 - m_AnalyticDerivativeDebugOutput: 0 - - rid: 3368384739993452864 - type: {class: CustomPostProcessOrdersSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_BeforeTransparentCustomPostProcesses: - m_InjectionPoint: 0 - m_CustomPostProcessTypesAsString: [] - m_BeforeTAACustomPostProcesses: - m_InjectionPoint: 3 - m_CustomPostProcessTypesAsString: [] - m_BeforePostProcessCustomPostProcesses: - m_InjectionPoint: 1 - m_CustomPostProcessTypesAsString: [] - m_AfterPostProcessBlursCustomPostProcesses: - m_InjectionPoint: 4 - m_CustomPostProcessTypesAsString: [] - m_AfterPostProcessCustomPostProcesses: - m_InjectionPoint: 2 - m_CustomPostProcessTypesAsString: [] - - rid: 3368384739993452865 - type: {class: DiffusionProfileDefaultSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_AutoRegisterDiffusionProfiles: 0 - - rid: 3368384739993452866 - type: {class: LensSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_LensAttenuationMode: 0 - - rid: 3368384739993452867 - type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_DynamicRenderPassCulling: 0 - - rid: 3368384739993452868 - type: {class: HDRenderPipelineRuntimeMaterials, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_PBRSkyMaterial: {fileID: -876546973899608171, guid: 02532cbb810fb404db49da84f1efe41e, type: 3} - m_AreaLightMaterial: {fileID: 2100000, guid: ef5f65c980e25304098a95e28f3bd20b, type: 2} - m_AreaLightCookieMaterial: {fileID: 2100000, guid: 78c6825c5d9c3664f9879ae8609618c7, type: 2} - - rid: 3368384739993452869 - type: {class: HDRenderPipelineEditorAssets, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: f940a8037e6cda542891dc1aac1fa4e8, type: 2} - m_LookDevDefaultLookDevVolumeProfile: {fileID: 11400000, guid: 254c4fe87beb7be4fa72e1681edbed02, type: 2} - m_DefaultDiffusionProfileSettingsList: - - {fileID: 11400000, guid: 404820c4cf36ad944862fa59c56064f0, type: 2} - - {fileID: 11400000, guid: 2384dbf2c1c420f45a792fbc315fbfb1, type: 2} - - rid: 3368384739993452870 - type: {class: VolumetricCloudsRuntimeResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_VolumetricCloudsCS: {fileID: 7200000, guid: f911a8577fa9a4546a6b255bcf888baf, type: 3} - m_VolumetricCloudsTraceCS: {fileID: 7200000, guid: 66eaa9becc91a8646a88c15375af8b86, type: 3} - m_VolumetricCloudsTraceShadowsCS: {fileID: 7200000, guid: f350c5c3b41fd1b408aac9076f96610e, type: 3} - m_VolumetricCloudsShadowFilterCS: {fileID: 7200000, guid: 771ea9a52996c024095906ac37a8a71f, type: 3} - m_VolumetricCloudMapGeneratorCS: {fileID: 7200000, guid: 6b22771f0aa98744cb09f455a5a818cb, type: 3} - m_VolumetricCloudsCombinePS: {fileID: 4800000, guid: 12f1a69ddf916f042ae6ce8a994506f3, type: 3} - m_CloudLutRainAO: {fileID: 2800000, guid: e0bcfddf26ed5584ba3d8b94d3200114, type: 3} - m_WorleyNoise128RGBA: {fileID: 11700000, guid: 1fe54a721d0e2504e89f121c723404a8, type: 3} - m_WorleyNoise32RGB: {fileID: 11700000, guid: ec156c314a242914dbb706f73ad78cf2, type: 3} - m_PerlinNoise32RGB: {fileID: 11700000, guid: d1aae012f8a4f23478471851f17ff915, type: 3} - - rid: 3368384739993452871 - type: {class: ColorGradingSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_ColorGradingSpace: 0 - - rid: 3368384739993452872 - type: {class: SpecularFadeSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_SpecularFade: 0 - - rid: 3368384739993452873 - type: {class: HDRenderPipelineRuntimeAssets, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_DefaultDiffusionProfile: {fileID: 11400000, guid: 2b7005ba3a4d8474b8cdc34141ad766e, type: 2} - m_ComputeMaterialLibrary: {fileID: 11400000, guid: 833ab0ec618db411699ea8cb1a221d0d, type: 2} - m_EmissiveCylinderMesh: {fileID: 2534964839176971238, guid: accb6d90f0d50fe4ca0f68159b4323de, type: 3} - m_EmissiveQuadMesh: {fileID: 4300000, guid: 1d5a8595286f94f4bb54171d49f473c3, type: 3} - m_SphereMesh: {fileID: 4300000, guid: 9e0af751bc36ea146940ba245193e28c, type: 3} - - rid: 3368384739993452874 - type: {class: HDRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_DebugFontTex: {fileID: 2800000, guid: a3ad2df0e49aaa341a3b3a80f93b3f66, type: 3} - m_ColorGradient: {fileID: 2800000, guid: 4ea52e665573c1644bf05dd9b11fd2a4, type: 3} - m_MatcapTex: {fileID: 2800000, guid: e655445a13b501944a2641ea144edda5, type: 3} - m_BlueNoise16LTex: - - {fileID: 2800000, guid: efa2ea5416a18da46b64f1266464ffc7, type: 3} - - {fileID: 2800000, guid: 0330b95d1d741fc4281eac4aec9d2eae, type: 3} - - {fileID: 2800000, guid: 8a51abfa06f36a24e8621796aa6cd4b3, type: 3} - - {fileID: 2800000, guid: 29f15236a89d7d748abaa25d8f69f614, type: 3} - - {fileID: 2800000, guid: 6abadf255584bba4c944b1e00436ef03, type: 3} - - {fileID: 2800000, guid: 979eec7b1833b0441a2cc73bf8db2544, type: 3} - - {fileID: 2800000, guid: 8f520abb155364c46b0f0748ef34ec0d, type: 3} - - {fileID: 2800000, guid: 8b7bdf66a62cb51409d47548bb0d542f, type: 3} - - {fileID: 2800000, guid: fed7135c4936ff947b1477236ec392cd, type: 3} - - {fileID: 2800000, guid: 3c2108b42cf27e3479d8587367508c6f, type: 3} - - {fileID: 2800000, guid: b6fa54cec31997445a1b5fd8e2887484, type: 3} - - {fileID: 2800000, guid: 79f42a2cc0e32614ba4e0fee3e0f88b9, type: 3} - - {fileID: 2800000, guid: a75de30c08d74744c9e973e42c2e00e5, type: 3} - - {fileID: 2800000, guid: c6c47a7f59293a847a8471bb74b9a262, type: 3} - - {fileID: 2800000, guid: 55e474b0d2c992240aed7e3bcbebb78a, type: 3} - - {fileID: 2800000, guid: b987ab952dc89bc439eebfaf7b977f51, type: 3} - - {fileID: 2800000, guid: f242013130364874486ad0854d54b5d9, type: 3} - - {fileID: 2800000, guid: 5e40f3339a0a5be4ea4442562c53575a, type: 3} - - {fileID: 2800000, guid: 6f6e861d2ff8cd641b424245a18393a0, type: 3} - - {fileID: 2800000, guid: 96b4b7db9e972c54db03d280a7924fb8, type: 3} - - {fileID: 2800000, guid: f8c387db83f623d4c875b355974b1398, type: 3} - - {fileID: 2800000, guid: ba5d54ee870713c41a40c8435ad4fdea, type: 3} - - {fileID: 2800000, guid: 98de916e94bbf4541981fe7c1bd7008f, type: 3} - - {fileID: 2800000, guid: e013b0f34384ea242b2366eafe8d66b4, type: 3} - - {fileID: 2800000, guid: 08e7f74e876f85247ad1104f35322e19, type: 3} - - {fileID: 2800000, guid: eaed38d1a2336e14b8fd351f65d3eddb, type: 3} - - {fileID: 2800000, guid: 9b47ce76307ef714d9c08f1f7d37a173, type: 3} - - {fileID: 2800000, guid: 4cf893d4f07705d40a404330fb6694d5, type: 3} - - {fileID: 2800000, guid: 4ba6dd9a348fff64aba90f736da533bd, type: 3} - - {fileID: 2800000, guid: faedd3bf25384dc47b38a94a658e19fc, type: 3} - - {fileID: 2800000, guid: cb7d595d4b67de146abf1b1f4d45f417, type: 3} - - {fileID: 2800000, guid: a836cbb14cfefd54a8b9ca37d6aadde6, type: 3} - m_BlueNoise16RGBTex: - - {fileID: 2800000, guid: b232903ea527aba4786ab9a725e610e9, type: 3} - - {fileID: 2800000, guid: fe6c6d7fed228ae4c9034639926613ff, type: 3} - - {fileID: 2800000, guid: 1dae10311eb6da5428b4247f883f9f0c, type: 3} - - {fileID: 2800000, guid: 668a0101474cc3149bdf7b69bdaad1eb, type: 3} - - {fileID: 2800000, guid: a3a352512b3774b44aeeb7414aafce58, type: 3} - - {fileID: 2800000, guid: f3767acdf061ed14380a360366ffe91c, type: 3} - - {fileID: 2800000, guid: a0d5f1353077a9d4d9bf0fdfbc07d718, type: 3} - - {fileID: 2800000, guid: 5a195bcf888979144a5db9a99c43a747, type: 3} - - {fileID: 2800000, guid: 8d79e4efe64973b4ab5c6e3982b15772, type: 3} - - {fileID: 2800000, guid: eaf67a58951a945428cb394e81ed3765, type: 3} - - {fileID: 2800000, guid: 287dda93fa25eea4fbb9f7f5ef014718, type: 3} - - {fileID: 2800000, guid: 4cb7c602f368c2d44b42c51c353e5b2c, type: 3} - - {fileID: 2800000, guid: 3fa94aebb9c04c54aa0cebde90c210ff, type: 3} - - {fileID: 2800000, guid: aa35bbfe9eac94d49bb95cd8804c51a7, type: 3} - - {fileID: 2800000, guid: ba3b2a48f5297c74eb3b4b2771629d60, type: 3} - - {fileID: 2800000, guid: 17165acde01c02f4bb45d0ffd25d5158, type: 3} - - {fileID: 2800000, guid: 280a79ac7e2b6e940a7199b8f7e10407, type: 3} - - {fileID: 2800000, guid: b75a320b602f27c4ab28904a10142a98, type: 3} - - {fileID: 2800000, guid: 226149deca448e745a7c377133e6ca7f, type: 3} - - {fileID: 2800000, guid: 059fba768df29964e9f07bd4fffb5776, type: 3} - - {fileID: 2800000, guid: 9dee14979276d81489a17afa605f3030, type: 3} - - {fileID: 2800000, guid: 3963568f414ac1545b64e5f1ff5daf5d, type: 3} - - {fileID: 2800000, guid: a96a5d146fa164d4ebd67318a957a75a, type: 3} - - {fileID: 2800000, guid: b5fa2a735b9278349a91f3dbb77691c0, type: 3} - - {fileID: 2800000, guid: d3c864eb1f6e4b34c91d1931ad0064a3, type: 3} - - {fileID: 2800000, guid: 97f308a7009457545a975a9a498499ce, type: 3} - - {fileID: 2800000, guid: daa405d7e1e253a40952bed9e9ca63cc, type: 3} - - {fileID: 2800000, guid: 4dbadef8044229d47b9a391147dad1c4, type: 3} - - {fileID: 2800000, guid: 7ce9507d3d1997743b39f335a7f868fd, type: 3} - - {fileID: 2800000, guid: 7641a2b116fafd64d9c3d6459fdfe801, type: 3} - - {fileID: 2800000, guid: c6a5e40e6746fef4fa486e8f620ee8d4, type: 3} - - {fileID: 2800000, guid: fd4189357c6dfb94fa2d36afbce72086, type: 3} - m_OwenScrambledRGBATex: {fileID: 2800000, guid: b0fe077c1ee7d80428f3d8dfa28a027d, type: 3} - m_OwenScrambled256Tex: {fileID: 2800000, guid: 2a205358e67aa9e4a94a128ac9362f4e, type: 3} - m_ScramblingTex: {fileID: 2800000, guid: bf25cd6288e2c8d43854a61a8496a830, type: 3} - m_RankingTile1SPP: {fileID: 2800000, guid: f2fe0251f704c4c478a8063775cffedb, type: 3} - m_ScramblingTile1SPP: {fileID: 2800000, guid: 6185473f62ad3e74da4acac5d482917a, type: 3} - m_RankingTile8SPP: {fileID: 2800000, guid: af4bd638a4b3eb14781e6441adcdfbb9, type: 3} - m_ScramblingTile8SPP: {fileID: 2800000, guid: 152f8b933250a7b448fc2d4d301b9944, type: 3} - m_RankingTile256SPP: {fileID: 2800000, guid: 1e604a266c415cd46b36d97cd9220aa8, type: 3} - m_ScramblingTile256SPP: {fileID: 2800000, guid: 882fb55d7b3e7c94598a318df9376e32, type: 3} - m_EyeCausticLUT: {fileID: 11700000, guid: d4ec12283a044584794485916f4142a9, type: 3} - m_HairAttenuationLUT: {fileID: 11700000, guid: d37662e2b254e594abf839dddc5ab653, type: 2} - m_HairAzimuthalScatteringLUT: {fileID: 11700000, guid: d217deac7ff61094080126811521ab5b, type: 2} - m_HairLongitudinalScatteringLUT: {fileID: 11700000, guid: 0da412d38ea6ba3459322abe6984ca9b, type: 2} - m_FilmGrainTex: - - {fileID: 2800000, guid: 284a1ac236869fa4eacf377d73c7dff8, type: 3} - - {fileID: 2800000, guid: bd74961b009b93145a998ae93a5fc186, type: 3} - - {fileID: 2800000, guid: 58c1a5135746f854e8841c70a4b588b9, type: 3} - - {fileID: 2800000, guid: bdc6fb6e37de5824bb06e17ac19a8a1d, type: 3} - - {fileID: 2800000, guid: e4d8303457ba4854090965d854a7a741, type: 3} - - {fileID: 2800000, guid: 75e19bf5d3ef41d489aa05586243b58b, type: 3} - - {fileID: 2800000, guid: 6cafd4bed3e420a45a5702d61df0762c, type: 3} - - {fileID: 2800000, guid: a187955d1d88a954cb32c3c4e5f0aeda, type: 3} - - {fileID: 2800000, guid: 3f3cb0f4924d7a241b82a9081875f30d, type: 3} - - {fileID: 2800000, guid: a35bdcb2008832646b3c8d2eb11e38a9, type: 3} - m_SMAASearchTex: {fileID: 2800000, guid: dc95d70472e232b438d0fd38651e7ec2, type: 3} - m_SMAAAreaTex: {fileID: 2800000, guid: 92e0d85ab4eca874098e7fcf6f8f674e, type: 3} - m_DefaultHDRISky: {fileID: 8900000, guid: 8253d41e6e8b11a4cbe77a4f8f82934d, type: 3} - m_DefaultCloudMap: {fileID: 2800000, guid: 57a33fc2476a01644865bfde5f06e2f4, type: 3} - - rid: 3368384739993452875 - type: {class: HDRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_DefaultMaterial: {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17, type: 2} - m_DefaultParticleMaterial: {fileID: 2100000, guid: b739a3f02ff77bf48b7636e64c3e3b4c, type: 2} - m_DefaultTerrainMaterial: {fileID: 2100000, guid: 22ff8771d87ef27429e670136399094b, type: 2} - m_DefaultMirrorMat: {fileID: 2100000, guid: 6b17274157b33bc45b6a40e7d4ff51fe, type: 2} - m_DefaultDecalMat: {fileID: 2100000, guid: 500e733574922d04ea961553b1b26a63, type: 2} - m_GUITextureBlit2SRGB: {fileID: 2100000, guid: 6e95c04e4e686554e8bed96ee69f690c, type: 2} - - rid: 3368384739993452876 - type: {class: HDRPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_VolumeProfile: {fileID: 11400000, guid: 0a821dc928355c04091e259c62eaa534, type: 2} - - rid: 3368384739993452877 - type: {class: WaterSystemRuntimeResources, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_WaterMaterial: {fileID: -876546973899608171, guid: 3fda5e465882bec4d8e64161b681806c, type: 3} - m_WaterExclusionMaterial: {fileID: 2100000, guid: 1e520c84f7fd17c46af5586f6632155c, type: 2} - m_WaterDecalMaterial: {fileID: -876546973899608171, guid: 7e2c0d424490bfc4698c37245b8c63ed, type: 3} - m_WaterSimulationCS: {fileID: 7200000, guid: 32ac7f445960a854595586a600c24034, type: 3} - m_FourierTransformCS: {fileID: 7200000, guid: bc2ee21836a0b5147900ef35a6e1f508, type: 3} - m_WaterEvaluationCS: {fileID: 7200000, guid: c24e765a2bbaace4d9a0ecec600e1967, type: 3} - m_WaterPS: {fileID: -6465566751694194690, guid: 3fda5e465882bec4d8e64161b681806c, type: 3} - m_WaterLightingCS: {fileID: 7200000, guid: 05d00ad19f202ee4891fdaa90d6d1b23, type: 3} - m_WaterLineCS: {fileID: 7200000, guid: 1e7e38362b5026d44ab4f3ff4a612026, type: 3} - m_WaterCausticsPS: {fileID: 4800000, guid: 020d64d10886f754e91664d240248c13, type: 3} - m_WaterDecalPS: {fileID: 4800000, guid: cf863cbd7bbd44a43b414caed214ba29, type: 3} - m_WaterDeformationCS: {fileID: 7200000, guid: 9b8063fa5834d4243bfca8c68a92d9f1, type: 3} - m_WaterFoamCS: {fileID: 7200000, guid: 0d16d14b783e65f4d81dbcece2bd0ef9, type: 3} - m_WaterDecalMigrationShader: {fileID: -6465566751694194690, guid: 9f1661ed5b4d6ee4685ad5683b09a903, type: 3} - m_FoamMask: {fileID: 2800000, guid: ca1d72d84c34dba4390eab4c86e62f62, type: 3} - - rid: 3368384739993452878 - type: {class: HDRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_DefaultShader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3} - m_CameraMotionVectorsPS: {fileID: 4800000, guid: 035941b63024d1943af48811c1db20d9, type: 3} - m_ColorPyramidPS: {fileID: 4800000, guid: 2fcfb8d92f45e4549b3f0bad5d0654bf, type: 3} - m_ColorPyramidCS: {fileID: 7200000, guid: 4e3267a1135742441a14298d8dcac04a, type: 3} - m_DepthPyramidCS: {fileID: 7200000, guid: 64a553bb564274041906f78ffba955e4, type: 3} - m_MaxZCS: {fileID: 7200000, guid: e95abf8c7230c344595f41c4dd5ff517, type: 3} - m_ApplyDistortionPS: {fileID: 4800000, guid: 02ae56f4306413c4a96dcf005cde1971, type: 3} - m_CustomPassUtils: {fileID: 4800000, guid: 7e3722d0388000848acb25fd3cc8c088, type: 3} - m_CustomPassRenderersUtils: {fileID: 4800000, guid: cef5ba33ee5063d4c8b495d2292e394d, type: 3} - m_ClearStencilBufferPS: {fileID: 4800000, guid: 8ea49ef16606acd489439e676ab84040, type: 3} - m_CopyStencilBufferPS: {fileID: 4800000, guid: 3d1574f1cdfa0ce4995f9bc79ed7f8ec, type: 3} - m_CopyDepthBufferPS: {fileID: 4800000, guid: 42dfcc8fe803ece4096c58630689982f, type: 3} - m_BlitPS: {fileID: 4800000, guid: e22fc1942c664490980b8793dd4a163d, type: 3} - m_BlitColorAndDepthPS: {fileID: 4800000, guid: b22ad378c678348729d3a3f981b9f270, type: 3} - m_DownsampleDepthPS: {fileID: 4800000, guid: 67d6171b0acc6554aad48c845ec7e67f, type: 3} - m_UpsampleTransparentPS: {fileID: 4800000, guid: 2ad7ce40f0dbaf64dadef1f58d8524d3, type: 3} - m_ResolveStencilCS: {fileID: 7200000, guid: 65b89cac5f286b043a31bf8041776ee7, type: 3} - m_DebugDisplayLatlongPS: {fileID: 4800000, guid: c1d1d149a043a5349ba367da6c2051ba, type: 3} - m_DebugViewMaterialGBufferPS: {fileID: 4800000, guid: 439949ea1bfa91b4ba0d04269fcde33d, type: 3} - m_DebugViewTilesPS: {fileID: 4800000, guid: c7c2bd17b06ceb4468e14081aaf1b96f, type: 3} - m_DebugFullScreenPS: {fileID: 4800000, guid: e874aca2df8300a488258738c31f85cf, type: 3} - m_DebugColorPickerPS: {fileID: 4800000, guid: 8137b807709e178498f22ed710864bb0, type: 3} - m_DebugExposurePS: {fileID: 4800000, guid: 0ef322534f047a34c96d29419d56d17a, type: 3} - m_DebugHDRPS: {fileID: 4800000, guid: 9bc5229549892084da43ad706d84f1bc, type: 3} - m_DebugLightVolumePS: {fileID: 4800000, guid: 8e706c0e71fcec34a8f5c9713e5e2943, type: 3} - m_DebugLightVolumeCS: {fileID: 7200000, guid: f5d5d21faef5cf445ac2c5d8ff9c4184, type: 3} - m_DebugBlitQuad: {fileID: 4800000, guid: cf5ca5b6ef18b3f429ed707ee9ceac9f, type: 3} - m_DebugViewVirtualTexturingBlit: {fileID: 4800000, guid: 55d195396b03b804eb78c92d468e3c8e, type: 3} - m_MaterialError: {fileID: 4800000, guid: 79a966a5200a456188dec0d48d805614, type: 3} - m_MaterialLoading: {fileID: 4800000, guid: 392325671f122f540be9033ca5ae7a56, type: 3} - m_ClearDebugBufferCS: {fileID: 7200000, guid: 7fc6041d5cf70004aa33bb1ac64e3c06, type: 3} - m_DebugWaveformPS: {fileID: 4800000, guid: 0024f9d09a828734192f3e1cd5931745, type: 3} - m_DebugWaveformCS: {fileID: 7200000, guid: 62b785f79355903428a21d5d8f8aeabe, type: 3} - m_DebugVectorscopePS: {fileID: 4800000, guid: 7a09af24008164d40ae85ccd6bf87e17, type: 3} - m_DebugVectorscopeCS: {fileID: 7200000, guid: 6a70efb18a2b2964c8eb0fc04aba20e9, type: 3} - m_DebugImageHistogramCS: {fileID: 7200000, guid: 52cc17ef5a5ffc443a5c142f9b745a85, type: 3} - m_DebugHDRxyMappingCS: {fileID: 7200000, guid: f055d2983d992b64494f1a03fc725cde, type: 3} - m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 22de19bc461f84742857dd64c56b0397, type: 3} - m_PlanarReflectionFilteringCS: {fileID: 7200000, guid: 9f3f8a01b8caaaa4595591dc96d43dd2, type: 3} - m_ScreenSpaceGlobalIlluminationCS: {fileID: 7200000, guid: 96170a954eb538b40a5ff369552c3629, type: 3} - m_ScreenSpaceReflectionsCS: {fileID: 7200000, guid: d1de9ac7d9016204da289affe9677942, type: 3} - m_ClearDispatchIndirectCS: {fileID: 7200000, guid: fc1f553acb80a6446a32d33e403d0656, type: 3} - m_ClearLightListsCS: {fileID: 7200000, guid: 743eb3491795b9545955695d591195a1, type: 3} - m_BuildDispatchIndirectCS: {fileID: 7200000, guid: 4eb1b418be7044c40bb5200496c50f14, type: 3} - m_BuildScreenAABBCS: {fileID: 7200000, guid: 728dce960f8a9c44bbc3abb3b851d8f6, type: 3} - m_BuildPerTileLightListCS: {fileID: 7200000, guid: 65af3444cbf4b3747a4dead7ee00cfee, type: 3} - m_BuildPerBigTileLightListCS: {fileID: 7200000, guid: 5ee1f9d6e09abe045b2f5e0b784b9072, type: 3} - m_BuildPerVoxelLightListCS: {fileID: 7200000, guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196, type: 3} - m_LightListClusterClearAtomicIndexCS: {fileID: 7200000, guid: 1e3472a94b14a334a93230bbc700d7b2, type: 3} - m_BuildMaterialFlagsCS: {fileID: 7200000, guid: fb3eda953cd6e634e877fb777be2cd08, type: 3} - m_DeferredCS: {fileID: 7200000, guid: 0b64f79746d2daf4198eaf6eab9af259, type: 3} - m_VolumeVoxelizationCS: {fileID: 7200000, guid: c20b371db720da244b73830ec74a343a, type: 3} - m_VolumetricLightingCS: {fileID: 7200000, guid: b4901a10df2d1e24282725e9fbc77c97, type: 3} - m_VolumetricLightingFilteringCS: {fileID: 7200000, guid: ef9a910d0ec6ebb41ae3f5c7a69daf46, type: 3} - m_DefaultFogVolumeShader: {fileID: -6465566751694194690, guid: 95060fe3e070428418e64e6bed27b111, type: 3} - m_ScreenSpaceMultipleScatteringCS: {fileID: 7200000, guid: 29c79555731a206478f0ea448352340c, type: 3} - m_SubsurfaceScatteringCS: {fileID: 7200000, guid: b06a7993621def248addd55d0fe931b1, type: 3} - m_SubsurfaceScatteringDownsampleCS: {fileID: 7200000, guid: 4f8aaf0160a259e499fdfac512ca2692, type: 3} - m_CombineLightingPS: {fileID: 4800000, guid: 2e37131331fbdca449b1a2bc47a639ca, type: 3} - m_BlitCubemapPS: {fileID: 4800000, guid: d05913e251bed7a4992c921c62e1b647, type: 3} - m_OpaqueAtmosphericScatteringPS: {fileID: 4800000, guid: 32f724728cf19904291226f239ec16f0, type: 3} - m_HdriSkyPS: {fileID: 4800000, guid: 9bd32a6ece529fd4f9408b8d7e00c10d, type: 3} - m_IntegrateHdriSkyPS: {fileID: 4800000, guid: 48db2705cf2856d4e893eb30a6892d1b, type: 3} - m_SkyboxCubemapPS: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} - m_GradientSkyPS: {fileID: 4800000, guid: 2b5d4f1b26f03dc4a873b093e0c4adb1, type: 3} - m_AmbientProbeConvolutionCS: {fileID: 7200000, guid: 6d048f7b1bd45e840b4e79ec92639fa8, type: 3} - m_GroundIrradiancePrecomputationCS: {fileID: 7200000, guid: eb6ae6f326207ee4d987a3e5adddf63a, type: 3} - m_InScatteredRadiancePrecomputationCS: {fileID: 7200000, guid: 70c69d514688f8545855680760d77418, type: 3} - m_PhysicallyBasedSkyPS: {fileID: 4800000, guid: a06934a4863e778498be65d8f865b7a4, type: 3} - m_CloudLayerPS: {fileID: 4800000, guid: 001a47fa123e95a4bba13ecb0442d944, type: 3} - m_BakeCloudTextureCS: {fileID: 7200000, guid: 09a7f6850ee9fb4439e5ebd632127da5, type: 3} - m_BakeCloudShadowsCS: {fileID: 7200000, guid: 3e7317e0800c066448ee07a3e47f102b, type: 3} - m_SkyLUTGenerator: {fileID: 7200000, guid: 79224112d91b32241be6b65802863db4, type: 3} - m_LineStagePrepareCS: {fileID: 7200000, guid: 53231d98bbe64477aacc1adc14ba2619, type: 3} - m_LineStageSetupSegmentCS: {fileID: 7200000, guid: 028836c66d494d8d94e1b2ca7d5382ae, type: 3} - m_LineStageShadingSetupCS: {fileID: 7200000, guid: fefde0fac988da24a93bc2d8d6e0a0a1, type: 3} - m_LineStageRasterBinCS: {fileID: 7200000, guid: 17d1e3e43f0e4c878b40b52848a58a77, type: 3} - m_LineStageWorkQueueCS: {fileID: 7200000, guid: dae4ea8aeff24b16be3f0b2948e0acc5, type: 3} - m_LineStageRasterFineCS: {fileID: 7200000, guid: 8691ac13e67d457abb92eca75e88e995, type: 3} - m_LineCompositePS: {fileID: 4800000, guid: 8d9fbe0862434a2298748d335b9abea5, type: 3} - m_PreIntegratedFGD_GGXDisneyDiffusePS: {fileID: 4800000, guid: 123f13d52852ef547b2962de4bd9eaad, type: 3} - m_PreIntegratedFGD_CharlieFabricLambertPS: {fileID: 4800000, guid: 3b3bf235775cf8b4baae7f3306787ab0, type: 3} - m_PreIntegratedFGD_WardPS: {fileID: 4800000, guid: d279c46a545b0af4f9f0c4fa82cd489e, type: 3} - m_PreIntegratedFGD_CookTorrancePS: {fileID: 4800000, guid: a6402c19b020b4a4fb7073aaa2e26aba, type: 3} - m_PreIntegratedFGD_MarschnerPS: {fileID: 4800000, guid: 31f36caf0a5e7f848a1b5328b6ad3eb8, type: 3} - m_PreIntegratedFiberScatteringCS: {fileID: 7200000, guid: 4a087c9d074552c48aeb85184d56312e, type: 3} - m_VolumetricMaterialCS: {fileID: 7200000, guid: 26f18c9cb0bccbf4481f8c84579affb1, type: 3} - m_EyeMaterialCS: {fileID: 7200000, guid: 76f78ba05cea1ed449c1ef613ab90597, type: 3} - m_FilterAreaLightCookiesPS: {fileID: 4800000, guid: c243aac96dda5fa40bed693ed5ba02c4, type: 3} - m_BuildProbabilityTablesCS: {fileID: 7200000, guid: b9f26cf340afe9145a699753531b2a4c, type: 3} - m_ComputeGgxIblSampleDataCS: {fileID: 7200000, guid: 764a24bb47ef5ba4781d9ae82ca07445, type: 3} - m_GGXConvolvePS: {fileID: 4800000, guid: 123ed592ad5c2494b8aed301fd609e7b, type: 3} - m_CharlieConvolvePS: {fileID: 4800000, guid: 5685fd17e71045e4ca9fefca38a7c177, type: 3} - m_GpuPrefixSumCS: {fileID: 7200000, guid: 76fcf27f72d24907b1846939a7a2d83f, type: 3} - m_GpuSortCS: {fileID: 7200000, guid: e485b8d649234276ababbd36fcec8c1a, type: 3} - m_BilateralUpsampleCS: {fileID: 7200000, guid: 68e831c555284d741b985e05369f0e63, type: 3} - m_TemporalFilterCS: {fileID: 7200000, guid: 741979ff70f7bd6489fbcb464280ecff, type: 3} - m_DiffuseDenoiserCS: {fileID: 7200000, guid: b4ed2382141619f40af1f743a84ccaea, type: 3} - m_FurnaceTestCS: {fileID: 7200000, guid: 9c19385e40e70ea41811a942a46b04a3, type: 3} - m_ObjectIDPS: {fileID: -6465566751694194690, guid: 89daf81f8e8f6634da726cbca859ca38, type: 3} - m_ComputeThicknessPS: {fileID: 4800000, guid: 4d2c6daf0d4968748bb5b82d5016fdea, type: 3} - m_CopyChannelCS: {fileID: 7200000, guid: a4d45eda75e8e474dbe24a31f741f3b4, type: 3} - m_ClearBuffer2D: {fileID: 7200000, guid: fa9b66253270e9c47a67ae142f669eb4, type: 3} - m_EncodeBC6HCS: {fileID: 7200000, guid: aa922d239de60304f964e24488559eeb, type: 3} - m_CubeToPanoPS: {fileID: 4800000, guid: 595434cc3b6405246b6cd3086d0b6f7d, type: 3} - m_BlitCubeTextureFacePS: {fileID: 4800000, guid: d850d0a2481878d4bbf17e5126b04163, type: 3} - m_ClearUIntTextureCS: {fileID: 7200000, guid: d067ad4b88af51c498875426894aef76, type: 3} - m_Texture3DAtlasCS: {fileID: 7200000, guid: 81522e314a83afd4a8ed43bd00757051, type: 3} - m_XrMirrorViewPS: {fileID: 4800000, guid: e6255f98cf405eb45ab6f9006cf11e1f, type: 3} - m_XrOcclusionMeshPS: {fileID: 4800000, guid: 46a45b32bb110604fb36216b63bcdb81, type: 3} - m_ContactShadowCS: {fileID: 7200000, guid: 3e6900e06dc185a4380af4dacb4db0a4, type: 3} - m_ScreenSpaceShadowPS: {fileID: 4800000, guid: bfa43a48695613b4ea19c58858ae1a61, type: 3} - m_ShadowClearPS: {fileID: 4800000, guid: e3cab24f27741f44d8af1e94d006267c, type: 3} - m_EvsmBlurCS: {fileID: 7200000, guid: fb36979473602464fa32deacb9630c08, type: 3} - m_DebugHDShadowMapPS: {fileID: 4800000, guid: 93d40cc9a6e13994f86f576a624efa18, type: 3} - m_DebugLocalVolumetricFogAtlasPS: {fileID: 4800000, guid: 8371b763f09c7304889c22aa97ebdfd2, type: 3} - m_MomentShadowsCS: {fileID: 7200000, guid: 4dea53e2ff15ed0448817c2aa4246e53, type: 3} - m_ShadowBlitPS: {fileID: 4800000, guid: ca059f1af4587a24b9a9eed3b66cff0f, type: 3} - m_DecalNormalBufferPS: {fileID: 4800000, guid: fd532bf1795188c4daaa66ea798b8b0a, type: 3} - m_GTAOCS: {fileID: 7200000, guid: 6710b06492bd58c4bb8aec0fdc1fced3, type: 3} - m_GTAOSpatialDenoiseCS: {fileID: 7200000, guid: 2cb33c21587d12b4388d7866ab6c65f6, type: 3} - m_GTAOTemporalDenoiseCS: {fileID: 7200000, guid: 31e0ca4c210f97c468037d11a5b832bb, type: 3} - m_GTAOCopyHistoryCS: {fileID: 7200000, guid: 7f43be57ffd12ff469d4fc175c00c4b4, type: 3} - m_GTAOBlurAndUpsample: {fileID: 7200000, guid: 9eb1abde882538a4ea46fa23e49ab9fa, type: 3} - m_CopyAlphaCS: {fileID: 7200000, guid: c2c7eb6611725264187721ef9df0354b, type: 3} - m_NanKillerCS: {fileID: 7200000, guid: 83982f199acf927499576a99abc9bea9, type: 3} - m_ExposureCS: {fileID: 7200000, guid: 976d7bce54fae534fb9ec67e9c18570c, type: 3} - m_HistogramExposureCS: {fileID: 7200000, guid: 222da48299136f34b8e3fb75ae9f8ac7, type: 3} - m_ApplyExposureCS: {fileID: 7200000, guid: 1a6fea1dc099b984d8f2b27d504dc096, type: 3} - m_UberPostCS: {fileID: 7200000, guid: f1bf52f7c71bffd4f91e6cd90d12a4f7, type: 3} - m_LutBuilder3DCS: {fileID: 7200000, guid: 37f2b1b0ecd6f1c439e4c1b4f2fdb524, type: 3} - m_DepthOfFieldKernelCS: {fileID: 7200000, guid: 7869415cc3e4eaa4d82ac21a752a2780, type: 3} - m_DepthOfFieldCoCCS: {fileID: 7200000, guid: 048b235b54fbfaa4d80ec85ea847d4f8, type: 3} - m_DepthOfFieldCoCReprojectCS: {fileID: 7200000, guid: 4980decaa3878d6448569489f5fc7931, type: 3} - m_DepthOfFieldDilateCS: {fileID: 7200000, guid: 1c93af4338c0c1b42b92464992eebc10, type: 3} - m_DepthOfFieldMipCS: {fileID: 7200000, guid: d3ef53de069ded64e8377cba6eb951fa, type: 3} - m_DepthOfFieldMipSafeCS: {fileID: 7200000, guid: 2d24ee7b2c804d947a5c371c12ed46bd, type: 3} - m_DepthOfFieldPrefilterCS: {fileID: 7200000, guid: f2b89d19910854346b792fe7177ce634, type: 3} - m_DepthOfFieldTileMaxCS: {fileID: 7200000, guid: 84f84585ea8a7a849bea4a581adb93a7, type: 3} - m_DepthOfFieldGatherCS: {fileID: 7200000, guid: 486be52dddc4e054fb10a7b9b78788c2, type: 3} - m_DepthOfFieldCombineCS: {fileID: 7200000, guid: c8049ca85c4c7d047ba28f34d800c663, type: 3} - m_DepthOfFieldPreCombineFarCS: {fileID: 7200000, guid: 3b4a2acd03d1ce2438d93c325d588735, type: 3} - m_DepthOfFieldClearIndirectArgsCS: {fileID: 7200000, guid: 69905045e1d0a65458b205d6ab55502b, type: 3} - m_PaniniProjectionCS: {fileID: 7200000, guid: 0ddbf72c8fbb6e44b983f470c8384ef6, type: 3} - m_DofCircleOfConfusion: {fileID: 7200000, guid: 75332b7b315c80d4babe506820aa0bfd, type: 3} - m_DofGatherCS: {fileID: 7200000, guid: 1e6b16a7970a1494db74b1d3d007d1cc, type: 3} - m_DofCoCMinMaxCS: {fileID: 7200000, guid: c70dd492c3d2fe94589d6ca8d4e37915, type: 3} - m_DofMinMaxDilateCS: {fileID: 7200000, guid: 757a3f81b35177b44b2b178909b49172, type: 3} - m_DofCombineCS: {fileID: 7200000, guid: d9b940a90a2d0884f94990a0dde43a53, type: 3} - m_DofComputeSlowTilesCS: {fileID: 7200000, guid: b89f86a76de81ee42ae16daad78eb382, type: 3} - m_DofComputeApertureShapeCS: {fileID: 7200000, guid: dd5acecb27e20334fa3be332e85172df, type: 3} - m_MotionBlurMotionVecPrepCS: {fileID: 7200000, guid: ed9438fa777911d48933402087203b15, type: 3} - m_MotionBlurGenTileCS: {fileID: 7200000, guid: 336e1fdbb3a1b8647b06208415f87804, type: 3} - m_MotionBlurMergeTileCS: {fileID: 7200000, guid: cd14ddf849edeed43b0e3ccf66023038, type: 3} - m_MotionBlurNeighborhoodTileCS: {fileID: 7200000, guid: 5ea9865df3e53b448856785b88f8e7b9, type: 3} - m_MotionBlurCS: {fileID: 7200000, guid: 2af5c49c7865edb4b823826970ec176a, type: 3} - m_BloomPrefilterCS: {fileID: 7200000, guid: 243b24008041aaa4a91800690f63c684, type: 3} - m_BloomBlurCS: {fileID: 7200000, guid: 133a68380d324de4ea8d3ff8657b02d8, type: 3} - m_BloomUpsampleCS: {fileID: 7200000, guid: 5dbb0ac12cb11f84084b7e5633481bd1, type: 3} - m_DepthValuesPS: {fileID: 4800000, guid: 6e6a4a3dbb788234594aa74f2d6aeb6f, type: 3} - m_ColorResolvePS: {fileID: 4800000, guid: dd7047092f3c82b40b3a07868f9c4de2, type: 3} - m_ResolveMotionVecPS: {fileID: 4800000, guid: ea18ca9826385e943979c46cf98968cc, type: 3} - m_FXAACS: {fileID: 7200000, guid: 1535d29f35ea86b4282b6ca652002e2a, type: 3} - m_FinalPassPS: {fileID: 4800000, guid: 5ac9ef0c50282754b93c7692488e7ee7, type: 3} - m_ClearBlackPS: {fileID: 4800000, guid: 3330c1503ea8c6d4d9408df3f64227eb, type: 3} - m_SMAAPS: {fileID: 4800000, guid: 9655f4aa89a469c49aceaceabf9bc77b, type: 3} - m_TemporalAntialiasingPS: {fileID: 4800000, guid: 3dd9fd928fdb83743b1f27d15df22179, type: 3} - m_SharpeningCS: {fileID: 7200000, guid: 667941138a753f447bad3bf94052f590, type: 3} - m_LensFlareDataDrivenPS: {fileID: 4800000, guid: 85330b3de0cfebc4ba78b2d61b1a2899, type: 3} - m_LensFlareScreenSpacePS: {fileID: 4800000, guid: 97abfc9f0525e1849b417eaae10f0329, type: 3} - m_LensFlareMergeOcclusionCS: {fileID: 7200000, guid: 07492750f384d9a4da9aaf5d2feeed4a, type: 3} - m_DLSSBiasColorMaskPS: {fileID: 4800000, guid: 017a05924c0b0484ca29717ed0c60343, type: 3} - m_CompositeUIAndOETFApplyPS: {fileID: 4800000, guid: 08b7ad21d2b8e9142b730b22d7355821, type: 3} - m_ContrastAdaptiveSharpenCS: {fileID: 7200000, guid: 560896aec2f412c48995be35551a4ac6, type: 3} - m_EdgeAdaptiveSpatialUpsamplingCS: {fileID: 7200000, guid: f054fa9fe2c85bb42b9489e2f9ffb643, type: 3} - m_VTFeedbackDownsample: {fileID: 7200000, guid: 32d963548086c2c439aeb23a93e9a00a, type: 3} - m_AccumulationCS: {fileID: 7200000, guid: ed80add7a217efa468d137d6f7c668f3, type: 3} - m_BlitAndExposeCS: {fileID: 7200000, guid: 4b9a355e064de034dbfafe4583ba766b, type: 3} - m_AlphaInjectionPS: {fileID: 4800000, guid: 4edd96259a5e8b44c90479928f0cd11e, type: 3} - m_ChromaKeyingPS: {fileID: 4800000, guid: 49feb6b111e82ec4eb6d3d08e4b6903e, type: 3} - m_CustomClearPS: {fileID: 4800000, guid: 9cef3686fa32c8840947ed99b561195c, type: 3} - - rid: 3368384739993452879 - type: {class: LookDevVolumeProfileSettings, ns: UnityEngine.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Runtime} - data: - m_Version: 0 - m_VolumeProfile: {fileID: 11400000, guid: a3837bee00f735443a9ca15a1f874148, type: 2} - - rid: 3368384739993452880 - type: {class: HDRenderingLayersLimitSettings, ns: UnityEditor.Rendering.HighDefinition, asm: Unity.RenderPipelines.HighDefinition.Editor} - data: - m_Version: 0 - - rid: 3368384739993452881 - type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime} - data: - m_Version: 0 - m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, type: 3} - m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, type: 3} - m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, type: 3} - m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, type: 3} - m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, type: 3} - m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, type: 3} - m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, type: 3} - m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, type: 3} - m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, type: 3} - - rid: 3368384739993452882 - type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_version: 0 - m_EnableCompilationCaching: 1 - m_EnableValidityChecks: 1 - - rid: 3368384739993452883 - type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 1 - probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3} - probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, type: 3} - probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, type: 3} - - rid: 3368384739993452884 - type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_version: 0 - m_IncludeReferencedInScenes: 1 - m_IncludeAssetsByLabel: 1 - m_LabelToInclude: HDRP:IncludeInBuild - - rid: 3368384739993452885 - type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 1 - dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, type: 3} - subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, type: 3} - voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, type: 3} - traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} - traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} - skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} - skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} - renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} - renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} - - rid: 3368384739993452886 - type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 0 - m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3} - - rid: 3368384739993452887 - type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 1 - probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} - probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3} - probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, type: 3} - probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3} - probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, type: 3} - numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, type: 3} - - rid: 3368384739993452888 - type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 1 - m_ProbeVolumeDisableStreamingAssets: 0 - - rid: 3368384739993452889 - type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_Version: 0 - m_ExportShaderVariants: 1 - m_ShaderVariantLogLevel: 0 - m_StripRuntimeDebugShaders: 1 - - rid: 3368384739993452890 - type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} - data: - m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3} - m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3} - m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3} diff --git a/Assets/Scripts.meta b/Assets/Scripts.meta new file mode 100644 index 00000000..c836f9e5 --- /dev/null +++ b/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7fada4f5486aa344a348dfe4282d0d3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor.meta b/Assets/Scripts/Editor.meta new file mode 100644 index 00000000..1a0f6b6d --- /dev/null +++ b/Assets/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d8aa05c8ccefb441b81891b4fc33723 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Editor.asmdef b/Assets/Scripts/Editor/Editor.asmdef new file mode 100644 index 00000000..abdea20f --- /dev/null +++ b/Assets/Scripts/Editor/Editor.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Unity.InternalAPIEditorBridge.011", + "rootNamespace": "", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Scripts/Editor/Editor.asmdef.meta b/Assets/Scripts/Editor/Editor.asmdef.meta new file mode 100644 index 00000000..c604c1f5 --- /dev/null +++ b/Assets/Scripts/Editor/Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9f9cf16b14b3d0347905ab8b0f1a303e +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/PackageExporter.cs b/Assets/Scripts/Editor/PackageExporter.cs new file mode 100644 index 00000000..1788d1fe --- /dev/null +++ b/Assets/Scripts/Editor/PackageExporter.cs @@ -0,0 +1,19 @@ +using System; +using UnityEditor; +using UnityEngine; + +public static class PackageExporter +{ + public static void ExportPackage() + { + string packageName = "com.mygamedevtools.scene-loader"; + + string rootGuid = AssetDatabase.AssetPathToGUID("Packages/" + packageName); + + string[] collection = Array.Empty(); + collection = AssetDatabase.CollectAllChildren(rootGuid, collection); + + PackageUtility.ExportPackage(collection, packageName + ".unitypackage"); + Console.WriteLine($"Exported package to: \"{Application.dataPath}/../{packageName}.unitypackage\""); + } +} diff --git a/Assets/Scripts/Editor/PackageExporter.cs.meta b/Assets/Scripts/Editor/PackageExporter.cs.meta new file mode 100644 index 00000000..a4786f44 --- /dev/null +++ b/Assets/Scripts/Editor/PackageExporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4cfbd3e1010eb7f4fb1e9aab4b796286 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json index 7479a455..993b6ed0 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,6 +1,6 @@ { "dependencies": { - "com.unity.addressables": "2.2.2", + "com.unity.addressables": "1.19.19", "com.unity.feature.development": "1.0.2", "com.unity.ide.visualstudio": "2.0.22", "com.unity.render-pipelines.core": "17.0.4", @@ -8,7 +8,6 @@ "com.unity.render-pipelines.universal": "17.0.4", "com.unity.timeline": "1.8.7", "com.unity.ugui": "2.0.0", - "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", "com.unity.modules.animation": "1.0.0", @@ -46,8 +45,6 @@ "name": "Open UPM", "url": "https://package.openupm.com", "scopes": [ - "com.cysharp.unitask", - "com.openupm", "com.mygamedevtools" ] } diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index b81600a2..2b6b0c19 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -7,16 +7,15 @@ "dependencies": {} }, "com.unity.addressables": { - "version": "2.2.2", + "version": "1.19.19", "depth": 0, "source": "registry", "dependencies": { - "com.unity.profiling.core": "1.0.2", "com.unity.modules.assetbundle": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", "com.unity.modules.imageconversion": "1.0.0", "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.scriptablebuildpipeline": "2.1.4", + "com.unity.scriptablebuildpipeline": "1.19.6", "com.unity.modules.unitywebrequestassetbundle": "1.0.0" }, "url": "https://packages.unity.com" @@ -30,7 +29,7 @@ } }, "com.unity.burst": { - "version": "1.8.19", + "version": "1.8.18", "depth": 1, "source": "registry", "dependencies": { @@ -39,18 +38,6 @@ }, "url": "https://packages.unity.com" }, - "com.unity.collections": { - "version": "2.5.1", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.burst": "1.8.17", - "com.unity.test-framework": "1.4.5", - "com.unity.nuget.mono-cecil": "1.11.4", - "com.unity.test-framework.performance": "3.0.3" - }, - "url": "https://packages.unity.com" - }, "com.unity.editorcoroutines": { "version": "1.0.0", "depth": 1, @@ -59,7 +46,7 @@ "url": "https://packages.unity.com" }, "com.unity.ext.nunit": { - "version": "2.0.5", + "version": "1.0.6", "depth": 2, "source": "registry", "dependencies": {}, @@ -72,9 +59,10 @@ "dependencies": { "com.unity.ide.visualstudio": "2.0.22", "com.unity.ide.rider": "3.0.31", + "com.unity.ide.vscode": "1.2.5", "com.unity.editorcoroutines": "1.0.0", - "com.unity.performance.profile-analyzer": "1.2.3", - "com.unity.test-framework": "1.4.6", + "com.unity.performance.profile-analyzer": "1.2.2", + "com.unity.test-framework": "1.1.33", "com.unity.testtools.codecoverage": "1.2.6" } }, @@ -96,16 +84,16 @@ }, "url": "https://packages.unity.com" }, - "com.unity.mathematics": { - "version": "1.3.2", + "com.unity.ide.vscode": { + "version": "1.2.5", "depth": 1, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, - "com.unity.nuget.mono-cecil": { - "version": "1.11.4", - "depth": 2, + "com.unity.mathematics": { + "version": "1.2.6", + "depth": 1, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" @@ -118,14 +106,7 @@ "url": "https://packages.unity.com" }, "com.unity.performance.profile-analyzer": { - "version": "1.2.3", - "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.profiling.core": { - "version": "1.0.2", + "version": "1.2.2", "depth": 1, "source": "registry", "dependencies": {}, @@ -136,14 +117,9 @@ "depth": 0, "source": "builtin", "dependencies": { - "com.unity.burst": "1.8.14", - "com.unity.mathematics": "1.3.2", - "com.unity.ugui": "2.0.0", - "com.unity.collections": "2.4.3", + "com.unity.ugui": "1.0.0", "com.unity.modules.physics": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.rendering.light-transport": "1.0.1" + "com.unity.modules.jsonserialize": "1.0.0" } }, "com.unity.render-pipelines.high-definition": { @@ -151,21 +127,24 @@ "depth": 0, "source": "builtin", "dependencies": { + "com.unity.mathematics": "1.2.4", + "com.unity.burst": "1.8.9", "com.unity.modules.video": "1.0.0", "com.unity.modules.animation": "1.0.0", "com.unity.modules.imageconversion": "1.0.0", - "com.unity.render-pipelines.core": "17.0.4", - "com.unity.shadergraph": "17.0.4", - "com.unity.visualeffectgraph": "17.0.4", - "com.unity.render-pipelines.high-definition-config": "17.0.4" + "com.unity.modules.terrain": "1.0.0", + "com.unity.render-pipelines.core": "12.1.15", + "com.unity.shadergraph": "12.1.15", + "com.unity.visualeffectgraph": "12.1.15", + "com.unity.render-pipelines.high-definition-config": "12.1.15" } }, "com.unity.render-pipelines.high-definition-config": { - "version": "17.0.4", + "version": "12.1.15", "depth": 1, "source": "builtin", "dependencies": { - "com.unity.render-pipelines.core": "17.0.4" + "com.unity.render-pipelines.core": "12.1.15" } }, "com.unity.render-pipelines.universal": { @@ -173,80 +152,53 @@ "depth": 0, "source": "builtin", "dependencies": { - "com.unity.render-pipelines.core": "17.0.4", - "com.unity.shadergraph": "17.0.4", - "com.unity.render-pipelines.universal-config": "17.0.3" - } - }, - "com.unity.render-pipelines.universal-config": { - "version": "17.0.3", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.render-pipelines.core": "17.0.3" - } - }, - "com.unity.rendering.light-transport": { - "version": "1.0.1", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.collections": "2.2.0", - "com.unity.mathematics": "1.2.4", - "com.unity.modules.terrain": "1.0.0" + "com.unity.mathematics": "1.2.1", + "com.unity.burst": "1.8.9", + "com.unity.render-pipelines.core": "12.1.15", + "com.unity.shadergraph": "12.1.15" } }, "com.unity.scriptablebuildpipeline": { - "version": "2.1.4", + "version": "1.20.1", "depth": 1, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.searcher": { - "version": "4.9.3", + "version": "4.9.1", "depth": 2, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.settings-manager": { - "version": "2.0.1", + "version": "1.0.3", "depth": 2, "source": "registry", "dependencies": {}, "url": "https://packages.unity.com" }, "com.unity.shadergraph": { - "version": "17.0.4", + "version": "12.1.15", "depth": 1, "source": "builtin", "dependencies": { - "com.unity.render-pipelines.core": "17.0.4", - "com.unity.searcher": "4.9.3" + "com.unity.render-pipelines.core": "12.1.15", + "com.unity.searcher": "4.9.1" } }, "com.unity.test-framework": { - "version": "1.4.6", + "version": "1.1.33", "depth": 1, "source": "registry", "dependencies": { - "com.unity.ext.nunit": "2.0.3", + "com.unity.ext.nunit": "1.0.6", "com.unity.modules.imgui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0" }, "url": "https://packages.unity.com" }, - "com.unity.test-framework.performance": { - "version": "3.0.3", - "depth": 2, - "source": "registry", - "dependencies": { - "com.unity.test-framework": "1.1.31", - "com.unity.modules.jsonserialize": "1.0.0" - }, - "url": "https://packages.unity.com" - }, "com.unity.testtools.codecoverage": { "version": "1.2.6", "depth": 1, @@ -279,20 +231,14 @@ } }, "com.unity.visualeffectgraph": { - "version": "17.0.4", + "version": "12.1.15", "depth": 1, "source": "builtin", "dependencies": { - "com.unity.shadergraph": "17.0.4", - "com.unity.render-pipelines.core": "17.0.4" + "com.unity.shadergraph": "12.1.15", + "com.unity.render-pipelines.core": "12.1.15" } }, - "com.unity.modules.accessibility": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, "com.unity.modules.ai": { "version": "1.0.0", "depth": 0, @@ -340,12 +286,6 @@ "com.unity.modules.animation": "1.0.0" } }, - "com.unity.modules.hierarchycore": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": {} - }, "com.unity.modules.imageconversion": { "version": "1.0.0", "depth": 0, @@ -435,7 +375,17 @@ "com.unity.modules.ui": "1.0.0", "com.unity.modules.imgui": "1.0.0", "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.hierarchycore": "1.0.0" + "com.unity.modules.uielementsnative": "1.0.0" + } + }, + "com.unity.modules.uielementsnative": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" } }, "com.unity.modules.umbra": { diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index d98609d4..db5a809f 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -3,7 +3,7 @@ --- !u!30 &1 GraphicsSettings: m_ObjectHideFlags: 0 - serializedVersion: 16 + serializedVersion: 14 m_Deferred: m_Mode: 1 m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} @@ -13,6 +13,9 @@ GraphicsSettings: m_ScreenSpaceShadows: m_Mode: 1 m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} m_DepthNormals: m_Mode: 1 m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} @@ -45,7 +48,6 @@ GraphicsSettings: m_LightmapStripping: 0 m_FogStripping: 0 m_InstancingStripping: 0 - m_BrgStripping: 0 m_LightmapKeepPlain: 1 m_LightmapKeepDirCombined: 1 m_LightmapKeepDynamicPlain: 1 @@ -56,12 +58,12 @@ GraphicsSettings: m_FogKeepExp: 1 m_FogKeepExp2: 1 m_AlbedoSwatchInfos: [] - m_RenderPipelineGlobalSettingsMap: - UnityEngine.Rendering.HighDefinition.HDRenderPipeline: {fileID: 11400000, guid: 6c116788356e21a4888de895681c22f7, type: 2} - UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: ec72006901959cd4791a67f23cef8143, type: 2} m_LightsUseLinearIntensity: 1 m_LightsUseColorTemperature: 1 + m_DefaultRenderingLayerMask: 1 m_LogWhenShaderIsCompiled: 0 - m_LightProbeOutsideHullStrategy: 0 + m_SRPDefaultSettings: + UnityEngine.Rendering.HighDefinition.HDRenderPipeline: {fileID: 11400000, guid: 6c116788356e21a4888de895681c22f7, type: 2} + UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: ec72006901959cd4791a67f23cef8143, type: 2} m_CameraRelativeLightCulling: 0 m_CameraRelativeShadowCulling: 0 diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset index c0898fc1..bc7d6779 100644 --- a/ProjectSettings/PackageManagerSettings.asset +++ b/ProjectSettings/PackageManagerSettings.asset @@ -31,8 +31,6 @@ MonoBehaviour: m_Name: Open UPM m_Url: https://package.openupm.com m_Scopes: - - com.cysharp.unitask - - com.openupm - com.mygamedevtools m_IsDefault: 0 m_Capabilities: 0 diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json index e0fe6fa9..c29a5e6f 100644 --- a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -1,4 +1,6 @@ { + "m_Name": "Settings", + "m_Path": "ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json", "m_Dictionary": { "m_DictionaryValues": [ { diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index a1aff48d..8386a052 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 6000.0.40f1 -m_EditorVersionWithRevision: 6000.0.40f1 (157d81624ddf) +m_EditorVersion: 2021.3.45f1 +m_EditorVersionWithRevision: 2021.3.45f1 (0da89fac8e79) diff --git a/ProjectSettings/URPProjectSettings.asset b/ProjectSettings/URPProjectSettings.asset index 08faf033..c1f118ad 100644 --- a/ProjectSettings/URPProjectSettings.asset +++ b/ProjectSettings/URPProjectSettings.asset @@ -12,4 +12,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} m_Name: m_EditorClassIdentifier: - m_LastMaterialVersion: 9 + m_LastMaterialVersion: 5 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset index f99437bb..a4f68812 100644 --- a/ProjectSettings/VFXManager.asset +++ b/ProjectSettings/VFXManager.asset @@ -7,13 +7,10 @@ VFXManager: m_CopyBufferShader: {fileID: 7200000, guid: 23c51f21a3503f6428b527b01f8a2f4e, type: 3} m_SortShader: {fileID: 7200000, guid: ea257ca3cfb12a642a5025e612af6b2a, type: 3} m_StripUpdateShader: {fileID: 7200000, guid: 8fa6c4009fe2a4d4486c62736fc30ad8, type: 3} - m_EmptyShader: {fileID: 4800000, guid: 33a2079f6a2db4c4eb2e44b33f4ddf6b, type: 3} + m_EmptyShader: {fileID: 4800000, guid: 43905ce367a8805429f76287d9f95e29, type: 3} m_RenderPipeSettingsPath: m_FixedTimeStep: 0.016666668 m_MaxDeltaTime: 0.05 - m_MaxScrubTime: 30 - m_MaxCapacity: 100000000 - m_CompiledVersion: 7 - m_RuntimeVersion: 38 + m_CompiledVersion: 5 + m_RuntimeVersion: 23 m_RuntimeResources: {fileID: 11400000, guid: bc10b42afe3813544bffd38ae2cd893d, type: 2} - m_BatchEmptyLifetime: 300 From 3263b18857512f31f4cd955612756b9759ba4bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 21:11:20 -0300 Subject: [PATCH 44/53] fix: update pipeline --- .github/workflows/release-template.yml | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 572aee61..68151762 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -99,11 +99,26 @@ jobs: run: | git push -f -u origin upm + - name: 🏷️ Create UPM Tag + run: | + git tag $TAG upm + git push origin --tags + env: + TAG: upm/${{ env.releaseVersion }} + + - name: πŸ—ƒοΈ Cache Library + uses: actions/cache@v4 + with: + path: Library + key: Library-StandaloneLinux64 + restore-keys: Library- + - name: πŸ“¦ Export Unity Package uses: game-ci/unity-builder@v4 with: targetPlatform: StandaloneLinux64 buildMethod: PackageExporter.ExportPackage + projectPath: "." env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} @@ -111,11 +126,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} - path: com.mygamedevtools.scene-loader.unitypackage - - - name: 🏷️ Create UPM Tag - run: | - git tag $TAG upm - git push origin --tags - env: - TAG: upm/${{ env.releaseVersion }} \ No newline at end of file + path: com.mygamedevtools.scene-loader.unitypackage \ No newline at end of file From b5d80236d40a8d937252d86f4368e7e52ca3ba02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 21:19:04 -0300 Subject: [PATCH 45/53] fix: update pipeline --- .github/workflows/release-template.yml | 37 ++++++++++++-------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 68151762..24053c9d 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -80,32 +80,13 @@ jobs: jq '.version = "${{ env.releaseVersion }}"' $PACKAGE_PATH/package.json > package.json.tmp && mv package.json.tmp $PACKAGE_PATH/package.json git commit --amend -a --no-edit - - name: πŸ“¦ Package UPM Branch - id: package_upm - run: | - git branch -d upm &> /dev/null || echo upm branch not found - git subtree split -P "$PACKAGE_PATH" -b upm - git checkout upm - - name: πŸ”„ Rename Samples Folder run: | if [[ -d "$PACKAGE_PATH/Samples" ]]; then mv "$PACKAGE_PATH/Samples" "$PACKAGE_PATH/Samples~" rm -f "$PACKAGE_PATH/Samples.meta" - git commit --amend -a --no-edit fi - - name: πŸš€ Push UPM Branch - run: | - git push -f -u origin upm - - - name: 🏷️ Create UPM Tag - run: | - git tag $TAG upm - git push origin --tags - env: - TAG: upm/${{ env.releaseVersion }} - - name: πŸ—ƒοΈ Cache Library uses: actions/cache@v4 with: @@ -126,4 +107,20 @@ jobs: uses: actions/upload-artifact@v4 with: name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} - path: com.mygamedevtools.scene-loader.unitypackage \ No newline at end of file + path: com.mygamedevtools.scene-loader.unitypackage + + - name: πŸ“¦ Package UPM Branch + id: package_upm + run: | + git branch -d upm &> /dev/null || echo upm branch not found + git subtree split -P "$PACKAGE_PATH" -b upm + git checkout upm + git commit --amend -a --no-edit + git push -f -u origin upm + + - name: 🏷️ Create UPM Tag + run: | + git tag $TAG upm + git push origin --tags + env: + TAG: upm/${{ env.releaseVersion }} \ No newline at end of file From 62df854262ae91b9280fa35e9cae01837ed54685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 21:21:45 -0300 Subject: [PATCH 46/53] fix: allow dirty builds (Samples folder rename) --- .github/workflows/release-template.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 24053c9d..a34e60db 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -100,6 +100,7 @@ jobs: targetPlatform: StandaloneLinux64 buildMethod: PackageExporter.ExportPackage projectPath: "." + allowDirtyBuild: true env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} From 3fc611bd2ced4fd4021e1cfada9506b1060a5da8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 21:32:18 -0300 Subject: [PATCH 47/53] fix: add unity secrets to reusable workflow --- .github/workflows/release-pre.yml | 3 +-- .github/workflows/release-template.yml | 12 ++++++++++-- .github/workflows/release.yml | 3 +-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-pre.yml b/.github/workflows/release-pre.yml index 69f7f30c..3bc8cc48 100644 --- a/.github/workflows/release-pre.yml +++ b/.github/workflows/release-pre.yml @@ -14,6 +14,5 @@ jobs: with: blockPullRequestRelease: false blockReleaseCommit: true - secrets: - githubToken: ${{ secrets.GH_TOKEN }} + secrets: inherit diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index a34e60db..a0014d1d 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -13,7 +13,13 @@ on: required: false type: boolean secrets: - githubToken: + GH_TOKEN: + required: true + UNITY_LICENSE: + required: true + UNITY_EMAIL: + required: true + UNITY_PASSWORD: required: true jobs: @@ -42,7 +48,7 @@ jobs: dry_run: ${{ inputs.dryRun }} ci: ${{ inputs.blockPullRequestRelease }} env: - GH_TOKEN: ${{ secrets.githubToken }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} - name: πŸ“„ Summary run: | @@ -103,6 +109,8 @@ jobs: allowDirtyBuild: true env: UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} - name: πŸ—‚οΈ Upload Unity Package Artifact uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03263536..713bdd97 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,5 +10,4 @@ jobs: create-release: name: Release uses: ./.github/workflows/release-template.yml - secrets: - githubToken: ${{ secrets.GH_TOKEN }} + secrets: inherit From 8b1b23033ad9d3c38febd5b12682141702789eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Sat, 22 Mar 2025 21:56:22 -0300 Subject: [PATCH 48/53] fix: isolate package generation to its own job --- .github/workflows/release-template.yml | 60 ++++++++++++++++++-------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index a0014d1d..775dd7d9 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -76,15 +76,53 @@ jobs: PACKAGE_PATH=$(jq -r '.plugins[] | select(type == "array" and .[0] == "@semantic-release/npm") | .[1].pkgRoot' .releaserc.json) echo "PACKAGE_PATH=$PACKAGE_PATH" >> $GITHUB_ENV - - name: βš™οΈ Git Setup + - name: ✏️ Update package.json + run: | + jq '.version = "${{ env.releaseVersion }}"' $PACKAGE_PATH/package.json > package.json.tmp && mv package.json.tmp $PACKAGE_PATH/package.json + + - name: πŸ“¦ Package UPM Branch + id: package_upm run: | git config --global user.name 'semantic-release-bot' git config --global user.email 'semantic-release-bot@martynus.net' + git branch -d upm &> /dev/null || echo upm branch not found + git subtree split -P "$PACKAGE_PATH" -b upm + git checkout upm + if [[ -d "Samples" ]]; then + mv "Samples" "Samples~" + rm -f "Samples.meta" + fi + git commit --amend -a --no-edit + git push -f -u origin upm + + - name: 🏷️ Create UPM Tag + run: | + git tag $TAG upm + git push origin --tags + env: + TAG: upm/${{ env.releaseVersion }} + + export-unity-package: + runs-on: ubuntu-latest + needs: 'semantic-release' + if: ${{ needs.semantic-release.outputs.new_release_published == 'true' && inputs.dryRun == false }} + env: + releaseVersion: ${{ needs.semantic-release.outputs.new_release_version }} + steps: + - name: πŸ“‚ Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: πŸ“€ Extract Path + id: extract-path + run: | + PACKAGE_PATH=$(jq -r '.plugins[] | select(type == "array" and .[0] == "@semantic-release/npm") | .[1].pkgRoot' .releaserc.json) + echo "PACKAGE_PATH=$PACKAGE_PATH" >> $GITHUB_ENV + - name: ✏️ Update package.json run: | jq '.version = "${{ env.releaseVersion }}"' $PACKAGE_PATH/package.json > package.json.tmp && mv package.json.tmp $PACKAGE_PATH/package.json - git commit --amend -a --no-edit - name: πŸ”„ Rename Samples Folder run: | @@ -116,20 +154,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} - path: com.mygamedevtools.scene-loader.unitypackage - - - name: πŸ“¦ Package UPM Branch - id: package_upm - run: | - git branch -d upm &> /dev/null || echo upm branch not found - git subtree split -P "$PACKAGE_PATH" -b upm - git checkout upm - git commit --amend -a --no-edit - git push -f -u origin upm - - - name: 🏷️ Create UPM Tag - run: | - git tag $TAG upm - git push origin --tags - env: - TAG: upm/${{ env.releaseVersion }} \ No newline at end of file + path: "./*.unitypackage" \ No newline at end of file From c1cd3dd2b27f5739f55c2317d039e5ff3f10cabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 24 Mar 2025 11:50:56 -0300 Subject: [PATCH 49/53] fix: debug list files --- .github/workflows/release-template.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 775dd7d9..e40eb0c6 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -85,14 +85,15 @@ jobs: run: | git config --global user.name 'semantic-release-bot' git config --global user.email 'semantic-release-bot@martynus.net' + git commit --amend -a --no-edit git branch -d upm &> /dev/null || echo upm branch not found git subtree split -P "$PACKAGE_PATH" -b upm git checkout upm if [[ -d "Samples" ]]; then - mv "Samples" "Samples~" - rm -f "Samples.meta" + mv Samples Samples~ + rm -f Samples.meta + git commit --amend -a --no-edit fi - git commit --amend -a --no-edit git push -f -u origin upm - name: 🏷️ Create UPM Tag @@ -138,6 +139,11 @@ jobs: key: Library-StandaloneLinux64 restore-keys: Library- + - name: πŸ“‚ List files before export + run: | + echo "Listing files before export" + ls -R + - name: πŸ“¦ Export Unity Package uses: game-ci/unity-builder@v4 with: @@ -150,6 +156,11 @@ jobs: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + - name: πŸ“‚ List files after export + run: | + echo "Listing files after export" + ls -R + - name: πŸ—‚οΈ Upload Unity Package Artifact uses: actions/upload-artifact@v4 with: From f7fe38f21296b0b7b70b7a78c8e1eeafd63334af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 24 Mar 2025 12:29:43 -0300 Subject: [PATCH 50/53] fix: export unity package to assets folder --- .github/workflows/release-template.yml | 4 ++-- Assets/Scripts/Editor/PackageExporter.cs | 5 +++-- .../Scripts/Editor/Sample.LoadingScene.Editor.asmdef | 4 +++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index e40eb0c6..74598e78 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -90,7 +90,7 @@ jobs: git subtree split -P "$PACKAGE_PATH" -b upm git checkout upm if [[ -d "Samples" ]]; then - mv Samples Samples~ + git mv Samples Samples~ rm -f Samples.meta git commit --amend -a --no-edit fi @@ -165,4 +165,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} - path: "./*.unitypackage" \ No newline at end of file + path: "./Assets/*.unitypackage" \ No newline at end of file diff --git a/Assets/Scripts/Editor/PackageExporter.cs b/Assets/Scripts/Editor/PackageExporter.cs index 1788d1fe..31255508 100644 --- a/Assets/Scripts/Editor/PackageExporter.cs +++ b/Assets/Scripts/Editor/PackageExporter.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using UnityEditor; using UnityEngine; @@ -13,7 +14,7 @@ public static void ExportPackage() string[] collection = Array.Empty(); collection = AssetDatabase.CollectAllChildren(rootGuid, collection); - PackageUtility.ExportPackage(collection, packageName + ".unitypackage"); - Console.WriteLine($"Exported package to: \"{Application.dataPath}/../{packageName}.unitypackage\""); + PackageUtility.ExportPackage(collection, Path.Combine(Application.dataPath, packageName + ".unitypackage")); + Console.WriteLine($"Exported package to: \"{Application.dataPath}/{packageName}.unitypackage\""); } } diff --git a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef index b1648e03..7d1c687c 100644 --- a/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef +++ b/Packages/com.mygamedevtools.scene-loader/Samples/LoadingSceneExamples/Scripts/Editor/Sample.LoadingScene.Editor.asmdef @@ -8,7 +8,9 @@ "GUID:78bd2ddd6e276394a9615c203e574844", "GUID:457756d89b35d2941b3e7b37b4ece6f1" ], - "includePlatforms": [], + "includePlatforms": [ + "Editor" + ], "excludePlatforms": [], "allowUnsafeCode": false, "overrideReferences": false, From 1b6cfa8bb29cfe239d6b19408485e299e34e2441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 24 Mar 2025 14:13:36 -0300 Subject: [PATCH 51/53] fix: update package export api --- .github/workflows/release-template.yml | 5 ----- Assets/Scripts/Editor/PackageExporter.cs | 10 +++------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 74598e78..328f2676 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -139,11 +139,6 @@ jobs: key: Library-StandaloneLinux64 restore-keys: Library- - - name: πŸ“‚ List files before export - run: | - echo "Listing files before export" - ls -R - - name: πŸ“¦ Export Unity Package uses: game-ci/unity-builder@v4 with: diff --git a/Assets/Scripts/Editor/PackageExporter.cs b/Assets/Scripts/Editor/PackageExporter.cs index 31255508..0819206d 100644 --- a/Assets/Scripts/Editor/PackageExporter.cs +++ b/Assets/Scripts/Editor/PackageExporter.cs @@ -8,13 +8,9 @@ public static class PackageExporter public static void ExportPackage() { string packageName = "com.mygamedevtools.scene-loader"; + string exportPath = Path.Combine(Application.dataPath, packageName + ".unitypackage"); - string rootGuid = AssetDatabase.AssetPathToGUID("Packages/" + packageName); - - string[] collection = Array.Empty(); - collection = AssetDatabase.CollectAllChildren(rootGuid, collection); - - PackageUtility.ExportPackage(collection, Path.Combine(Application.dataPath, packageName + ".unitypackage")); - Console.WriteLine($"Exported package to: \"{Application.dataPath}/{packageName}.unitypackage\""); + AssetDatabase.ExportPackage("Packages/" + packageName, exportPath, ExportPackageOptions.Recurse); + Console.WriteLine($"Exported package to: \"{exportPath}\""); } } From d494017662585a1ed322e73c8ce8cd57f640df9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 24 Mar 2025 16:08:20 -0300 Subject: [PATCH 52/53] fix: ensure Samples are included in the unitypackage --- .github/workflows/release-template.yml | 7 +- Assets/Scripts/Editor/Editor.asmdef | 6 +- Assets/Scripts/Editor/PackageExporter.cs | 11 +- .../Changelog.md | 58 ++ .../Changelog.md.meta | 7 + .../Editor.meta | 8 + .../Editor/AssetStoreToolsExtension.cs | 684 ++++++++++++++++++ .../Editor/AssetStoreToolsExtension.cs.meta | 11 + .../Editor/AssetStoreUploadConfig.cs | 190 +++++ .../Editor/AssetStoreUploadConfig.cs.meta | 11 + .../Needle.PackageTools.AssetStore.asmdef | 26 + ...Needle.PackageTools.AssetStore.asmdef.meta | 7 + .../Editor/Plugins.meta | 8 + .../Editor/Plugins/Harmony-License.md | 21 + .../Editor/Plugins/Harmony-License.md.meta | 7 + .../Editor/Plugins/Ignore-License.md | 21 + .../Editor/Plugins/Ignore-License.md.meta | 7 + .../Needle.PackageTools.AST.Harmony.dll | Bin 0 -> 769536 bytes .../Needle.PackageTools.AST.Harmony.dll.meta | 89 +++ .../Needle.PackageTools.AST.Ignore.dll | Bin 0 -> 10240 bytes .../Needle.PackageTools.AST.Ignore.dll.meta | 89 +++ .../Editor/UnitypackageExport.cs | 273 +++++++ .../Editor/UnitypackageExport.cs.meta | 11 + .../Editor/Zipper.cs | 123 ++++ .../Editor/Zipper.cs.meta | 3 + .../com.needle.upm-in-unitypackage/LICENSE.md | 21 + .../LICENSE.md.meta | 7 + .../com.needle.upm-in-unitypackage/Readme.md | 367 ++++++++++ .../Readme.md.meta | 7 + .../Samples~/Asset Store Upload Config.meta | 8 + .../Hybrid Packages Upload Config.asset | 17 + .../Hybrid Packages Upload Config.asset.meta | 8 + .../Samples~/Package with Samples.meta | 8 + .../Package with Samples/Changelog.md | 5 + .../Package with Samples/Changelog.md.meta | 7 + .../Samples~/Package with Samples/Editor.meta | 8 + .../Editor/MySampleComponentEditor.cs | 14 + .../Editor/MySampleComponentEditor.cs.meta | 11 + .../Editor/Needle.MyPackage.Editor.asmdef | 18 + .../Needle.MyPackage.Editor.asmdef.meta | 7 + ...eadme - Move me to the Packages folder.txt | 0 ... - Move me to the Packages folder.txt.meta | 7 + .../Package with Samples/Runtime.meta | 8 + .../Runtime/MySampleComponent.cs | 10 + .../Runtime/MySampleComponent.cs.meta | 11 + .../Runtime/Needle.MyPackage.asmdef | 14 + .../Runtime/Needle.MyPackage.asmdef.meta | 7 + .../Samples~/Complex Sample.meta | 8 + ...bly complex sample with TWO files - 01.txt | 0 ...omplex sample with TWO files - 01.txt.meta | 7 + ...bly complex sample with TWO files - 02.txt | 0 ...omplex sample with TWO files - 02.txt.meta | 7 + .../Samples~/Simple Sample.meta | 8 + ... very simple sample with just one file.txt | 0 ... simple sample with just one file.txt.meta | 7 + .../Package with Samples/package.json | 28 + .../Package with Samples/package.json.meta | 7 + .../package.json | 30 + .../package.json.meta | 7 + Packages/packages-lock.json | 6 + 60 files changed, 2348 insertions(+), 15 deletions(-) create mode 100644 Packages/com.needle.upm-in-unitypackage/Changelog.md create mode 100644 Packages/com.needle.upm-in-unitypackage/Changelog.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Harmony.dll create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Harmony.dll.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Ignore.dll create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Ignore.dll.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/LICENSE.md create mode 100644 Packages/com.needle.upm-in-unitypackage/LICENSE.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Readme.md create mode 100644 Packages/com.needle.upm-in-unitypackage/Readme.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json create mode 100644 Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json.meta create mode 100644 Packages/com.needle.upm-in-unitypackage/package.json create mode 100644 Packages/com.needle.upm-in-unitypackage/package.json.meta diff --git a/.github/workflows/release-template.yml b/.github/workflows/release-template.yml index 328f2676..312729bf 100644 --- a/.github/workflows/release-template.yml +++ b/.github/workflows/release-template.yml @@ -151,13 +151,8 @@ jobs: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} - - name: πŸ“‚ List files after export - run: | - echo "Listing files after export" - ls -R - - name: πŸ—‚οΈ Upload Unity Package Artifact uses: actions/upload-artifact@v4 with: name: com.mygamedevtools.scene-loader-${{ env.releaseVersion }} - path: "./Assets/*.unitypackage" \ No newline at end of file + path: "./*.unitypackage" \ No newline at end of file diff --git a/Assets/Scripts/Editor/Editor.asmdef b/Assets/Scripts/Editor/Editor.asmdef index abdea20f..72e60dfc 100644 --- a/Assets/Scripts/Editor/Editor.asmdef +++ b/Assets/Scripts/Editor/Editor.asmdef @@ -1,7 +1,9 @@ { - "name": "Unity.InternalAPIEditorBridge.011", + "name": "Editor", "rootNamespace": "", - "references": [], + "references": [ + "GUID:1ef0bbeee4c5c164fadb7031fd63e223" + ], "includePlatforms": [ "Editor" ], diff --git a/Assets/Scripts/Editor/PackageExporter.cs b/Assets/Scripts/Editor/PackageExporter.cs index 0819206d..cb56d6c0 100644 --- a/Assets/Scripts/Editor/PackageExporter.cs +++ b/Assets/Scripts/Editor/PackageExporter.cs @@ -1,16 +1,13 @@ -using System; -using System.IO; +using System.Linq; +using Needle.HybridPackages; using UnityEditor; -using UnityEngine; public static class PackageExporter { public static void ExportPackage() { string packageName = "com.mygamedevtools.scene-loader"; - string exportPath = Path.Combine(Application.dataPath, packageName + ".unitypackage"); - - AssetDatabase.ExportPackage("Packages/" + packageName, exportPath, ExportPackageOptions.Recurse); - Console.WriteLine($"Exported package to: \"{exportPath}\""); + string[] guids = AssetDatabase.GetAllAssetPaths().Where(p => p.StartsWith("Packages/" + packageName + "/")).Select(p => AssetDatabase.AssetPathToGUID(p)).ToArray(); + AssetStoreToolsPatchProvider.PackagerExportPatch.ExportPackage(guids, packageName + ".unitypackage"); } } diff --git a/Packages/com.needle.upm-in-unitypackage/Changelog.md b/Packages/com.needle.upm-in-unitypackage/Changelog.md new file mode 100644 index 00000000..ce6247fe --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Changelog.md @@ -0,0 +1,58 @@ +# Changelog +All notable changes to this package will be documented in this file. +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [0.6.3] - 2023-08-22 +- catch patching exception +- disable patching on Apple Silicon (unsupported) + +## [0.6.2] - 2022-10-30 +- fixed compilation issue on 2020.x + +## [0.6.1] - 2022-10-30 +- updated Readme + +## [0.6.0] - 2022-10-30 +- added support for the new Asset Store tools and the integrated Hybrid Packages workflow +- added automatically enabling the new flow in the Asset Store tools when this package is present +- added button to open export folder from upload config +- fix new AssetStore tools not allowing file:.. referenced packages for some reason +- ensure namespace is Needle.HybridPackages everywhere + +## [0.5.3] - 2021-05-25 +- added: default npmignore excludes will now be excluded when exporting hidden folders (Samples~, Documentation~ etc.) +- added: new sample, Package with Samples +- fixed: in very rare cases GUIDs can collide between assets. We're now properly avoiding these collisions. + +## [0.5.2] - 2021-05-20 +- fixed: exporting a package that has samples but not using an upload config threw a nullref exception + +## [0.5.1] - 2021-05-18 +- fixed: packing performance was low because compression strength was "Ultra", now defaults to "Normal" +- changed: disabled gitignore/npmignore option by default (it's experimental), can be turned on in the upload config +- added: ProgressBars to see what actually happens +- added: ability to export one or many upload configs directly for local testing (without upload) + +## [0.5.0] - 2021-05-18 +- added: ability to export hidden folders (Samples~, Documentation~ etc) in .unitypackage +- added: file ignore checks for content from hidden folders based on .gitignore/.npmignore + +## [0.4.0] - 2021-05-13 +- added: ability to create UploadConfigs that can specify multiple folders/packages for store upload +- added: prevent packages that start with "com.unity." from being uploaded +- added: prevent packages in the Library from being uploaded (only local/embedded packages should be) +- added: sample UploadConfig, import via PackMan samples. + +## [0.3.0] - 2021-05-03 +- embedded Harmony plugin to simplify dependencies +- fixed: DLLs were not exported in some cases because Unity treats them as DefaultAssets, same as folders + +## [0.2.0] - 2021-04-28 +- initial OpenUPM release +- Readme adjustments + +## [0.1.0-exp] - 2021-04-10 +- initial package version +- supports `Asset Store Tools 5.0` +- supports `Assets/Export Package` +- tested against Unity 2018.4, 2019.4, 2020.3 \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Changelog.md.meta b/Packages/com.needle.upm-in-unitypackage/Changelog.md.meta new file mode 100644 index 00000000..699e1552 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Changelog.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1b913e9ab8afdf644995371b558185be +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor.meta b/Packages/com.needle.upm-in-unitypackage/Editor.meta new file mode 100644 index 00000000..7f44348e --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3695b9f4542e8d24fa3b6b1b06189fbc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs new file mode 100644 index 00000000..3fad0e17 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs @@ -0,0 +1,684 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using HarmonyLib; +using UnityEditor; +using UnityEngine; +using UnityEngine.Profiling; +using Assembly = System.Reflection.Assembly; +using Debug = UnityEngine.Debug; + +// ReSharper disable InconsistentNaming + +namespace Needle.HybridPackages +{ + using Ignore = Ignore.Ignore; + +#if UNITY_2019_1_OR_NEWER + internal class PackagePathValidationPatchProvider + { + [InitializeOnLoadMethod] + static void OnGetPatches() + { + var harmony = new Harmony(nameof(PackagerPatchProvider)); + var asms = AppDomain.CurrentDomain.GetAssemblies(); + var asm = asms.FirstOrDefault(x => x.FullName.StartsWith("asset-store-tools-editor")); + if (asm == null) return; + var type = asm.GetType("AssetStoreTools.Uploader.HybridPackageUploadWorkflowView"); + var method = type?.GetMethod("IsValidLocalPackage", (BindingFlags)(-1)); + if (method == null) + { + //Debug.LogError($"Null method returned from {typeof(PackagePathValidationPatchProvider)}.IsValidLocalPackage. Please report a bug and note your Unity and package versions."); + return; + } + + try + { + harmony.Patch(method, new HarmonyMethod(AccessTools.Method(typeof(IsValidPatch), "Prefix"))); + } + catch (Exception e) + { + Debug.LogError($"Method patching failed from {typeof(PackagePathValidationPatchProvider)}.IsValidLocalPackage. Please report a bug and note your Unity and package versions.\n{e}"); + } + } + + private class IsValidPatch + { + private static bool Prefix(ref bool __result, string packageFolderPath, out string assetDatabasePackagePath) + { +#if UNITY_2022_1_OR_NEWER + var allPackages = UnityEditor.PackageManager.PackageInfo.GetAllRegisteredPackages(); +#else + var allPackages = UnityEditor.PackageManager.PackageInfo.GetAll(); +#endif + var packageInfo = allPackages.FirstOrDefault( + x => x.resolvedPath.Replace("\\", "/") == packageFolderPath.Replace("\\", "/")); + if (packageInfo != null) + { + assetDatabasePackagePath = packageInfo.assetPath; + __result = true; + return false; + } + + assetDatabasePackagePath = ""; + __result = false; + return true; + } + } + } +#endif + + internal class PackagerPatchProvider + { + [InitializeOnLoadMethod] + static void OnGetPatches() + { + if (!Helpers.PatchingSupported()) return; + + var harmony = new Harmony(nameof(PackagerPatchProvider)); + var type = typeof(EditorWindow).Assembly.GetType("UnityEditor.PackageExport"); + var method = type?.GetMethod("GetAssetItemsForExport", (BindingFlags)(-1)); + if (method == null) return; + harmony.Patch(method, new HarmonyMethod(AccessTools.Method(typeof(PackagerPatch), "Prefix"))); + } + + private class PackagerPatch + { + // ReSharper disable once UnusedMember.Local + // ReSharper disable once RedundantAssignment + private static bool Prefix(ref IEnumerable __result, ICollection guids, bool includeDependencies) + { + // check if this is an attempt to export from Packages, otherwise use original method + var someGuidsAreInsidePackages = guids + .Select(AssetDatabase.GUIDToAssetPath) + .Any(x => !string.IsNullOrEmpty(x) && x.StartsWith("Packages/", StringComparison.OrdinalIgnoreCase)); + if (!someGuidsAreInsidePackages) + return true; + + string[] resultingGuids = new string[0]; + foreach (var guid in guids) + resultingGuids = AssetDatabase.CollectAllChildren(guid, resultingGuids); + + // if (includeDependencies) + // Helpers.Log("You're exporting a package. If your package has dependencies and you want to export them, they need to be manually selected."); + + var rootsAndChildGuids = resultingGuids.Union(guids).Distinct().ToList(); + if (includeDependencies) + rootsAndChildGuids = rootsAndChildGuids.Union(AssetDatabase + .GetDependencies(rootsAndChildGuids.Select(AssetDatabase.GUIDToAssetPath).ToArray(), true) + .Select(AssetDatabase.AssetPathToGUID)) + .Distinct().ToList(); + + __result = rootsAndChildGuids + .Select(x => new ExportPackageItem() + { + assetPath = AssetDatabase.GUIDToAssetPath(x), + enabledStatus = (int)PackageExportTreeView.EnabledState.All, + guid = x, + isFolder = AssetDatabase.IsValidFolder(AssetDatabase.GUIDToAssetPath(x)) + }) + .Where(x => !x.isFolder); // ignore folders, otherwise these seem to end up being separate assets and ignored on import + + // this just doesn't warn, but still does not include the right items + // __result = PackageUtility.BuildExportPackageItemsList(resultingGuids, false); + return false; + } + } + } + + public class AssetStoreToolsPatchProvider + { + private const string outputSubFolder = "Temp"; // NB: this is Unity's "project's Temp folder" so you shouldn't change it + private static AssetStoreUploadConfig currentUploadConfig; + + [InitializeOnLoadMethod] + static void OnGetPatches() + { + // safeguard, should be prevented by OnWillEnablePatch + if (Helpers.GetAssetStoreToolsAssembly() == null) return; + if (!Helpers.PatchingSupported()) return; + + var harmony = new Harmony(nameof(AssetStoreToolsPatchProvider)); + PathValidationPatch.Patch(harmony); + RootPathPatch.Patch(harmony); + GetGUIDsPatch.Patch(harmony); + PackagerExportPatch.Patch(harmony); + } + + internal static void ExportPackageForConfig(AssetStoreUploadConfig uploadConfig) + { + var results = new List(); + + if (!uploadConfig.IsValid) + throw new ArgumentException("The selected upload config " + uploadConfig + " is not valid."); + + currentUploadConfig = uploadConfig; + + foreach (var path in uploadConfig.GetExportPaths()) + GetGUIDsPatch.AddChildrenToResults(results, path); + + var exportFilename = uploadConfig.GetExportFilename(outputSubFolder); + PackagerExportPatch.ExportPackage(results.ToArray(), exportFilename); + } + + private class PathValidationPatch + { + public static void Patch(Harmony harmony) + { + var asm = Helpers.GetAssetStoreToolsAssembly(); + if (asm == null) return; + var m = asm.GetType("AssetStorePackageController").GetMethod("IsValidProjectFolder", (BindingFlags)(-1)); + harmony.Patch(m, new HarmonyMethod(AccessTools.Method(typeof(PathValidationPatch), "Prefix"))); + } + + // ReSharper disable once UnusedMember.Local + // ReSharper disable once UnusedParameter.Local + // ReSharper disable once RedundantAssignment + private static bool Prefix(ref bool __result, string directory) + { + if (Path.GetFullPath(directory).Replace("\\", "/").StartsWith(Application.dataPath, StringComparison.Ordinal)) + return true; + + __result = true; + return false; + } + } + + private class RootPathPatch + { + public static void Patch(Harmony harmony) + { + var asm = Helpers.GetAssetStoreToolsAssembly(); + if (asm == null) return; + var m = asm.GetType("AssetStorePackageController").GetMethod("SetRootPath", (BindingFlags)(-1)); + harmony.Patch(m, new HarmonyMethod(AccessTools.Method(typeof(RootPathPatch), "Prefix"))); + } + + // ReSharper disable once UnusedMember.Local + private static bool Prefix(object __instance, string path) + { + if (__instance == null) return true; + // Helpers.Log(path); + if (path.StartsWith(Application.dataPath, StringComparison.Ordinal)) + return true; + + var m_UnsavedChanges = __instance.GetType().GetField("m_UnsavedChanges", (BindingFlags)(-1)); + if (m_UnsavedChanges == null) return true; + m_UnsavedChanges.SetValue(__instance, true); + + // project-relative path: + var directoryName = Application.dataPath; + if (string.IsNullOrEmpty(directoryName)) return true; + + var relative = "/../" + new Uri(directoryName).MakeRelativeUri(new Uri(path)); + // Helpers.Log(directoryName + " + " + path + " = " + relative); + + var m_LocalRootPath = __instance.GetType().GetField("m_LocalRootPath", (BindingFlags)(-1)); + if (m_LocalRootPath == null) return true; + m_LocalRootPath.SetValue(__instance, relative); + + var m_MainAssets = __instance.GetType().GetField("m_MainAssets", (BindingFlags)(-1)); + if (m_MainAssets == null) return true; + + var mainAssets = m_MainAssets.GetValue(__instance) as List; + if (mainAssets == null) return true; + mainAssets.Clear(); + return false; + } + } + + private class GetGUIDsPatch + { + public static void Patch(Harmony harmony) + { + var asm = Helpers.GetAssetStoreToolsAssembly(); + if (asm == null) return; + var m = asm.GetType("AssetStorePackageController").GetMethod("GetGUIDS", (BindingFlags)(-1)); + harmony.Patch(m, new HarmonyMethod(AccessTools.Method(typeof(GetGUIDsPatch), "Prefix"))); + } + + class PackageInfoMock + { + public string name; + public string resolvedPath; + } + + internal static void AddChildrenToResults(List results, string assetPath) + { + if (File.Exists(assetPath)) + { + results.Add(AssetDatabase.AssetPathToGUID(assetPath)); + return; + } + + string[] collection = new string[0]; + var children = AssetDatabase.CollectAllChildren(AssetDatabase.AssetPathToGUID(assetPath), collection); + + if (!children.Any()) + throw new NullReferenceException(Helpers.LogPrefix + "Seems you're trying to export something that's not in your AssetDatabase: " + assetPath + " - this can't be exported as .unitypackage."); + + results.AddRange(children); + } + + // ReSharper disable once UnusedMember.Local + private static bool Prefix(ref string[] __result, object __instance, bool includeProjectSettings) + { + var m_LocalRootPath = __instance.GetType().GetField("m_LocalRootPath", (BindingFlags)(-1)); + if (m_LocalRootPath == null) return true; + var localRootPath = m_LocalRootPath.GetValue(__instance) as string; + + if (string.IsNullOrEmpty(localRootPath) || localRootPath.Equals("/", StringComparison.Ordinal)) + return true; + + List results = new List(); + + // seems there's some weird path behaviour on 2018.4 with double // + if (localRootPath.StartsWith("/", StringComparison.Ordinal) && !localRootPath.StartsWith("/.", StringComparison.Ordinal)) + localRootPath = localRootPath.Substring("/".Length); + + currentUploadConfig = null; + + if (Directory.Exists("Assets/" + localRootPath) && !localRootPath.StartsWith("/..")) + { + // find the config inside this folder + var configs = AssetDatabase.FindAssets("t:AssetStoreUploadConfig", new[] { "Assets/" + localRootPath }); + if (configs.Any()) + { + var configPath = AssetDatabase.GUIDToAssetPath(configs.First()); + var uploadConfig = AssetDatabase.LoadAssetAtPath(configPath); + Debug.Log("Upload Config detected. The selected path will be ignored, and the upload config will be used instead.", uploadConfig); + + if (uploadConfig) + { + if (!uploadConfig.IsValid) + throw new ArgumentException("The selected upload config at " + configPath + " is not valid."); + currentUploadConfig = uploadConfig; + + foreach (var path in uploadConfig.GetExportPaths()) + { + AddChildrenToResults(results, path); + } + + __result = results.ToArray(); + + // Debug.Log("Included files: " + string.Join("\n", __result.Select(AssetDatabase.GUIDToAssetPath))); + return false; + } + } + } + + if (!string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID("Assets/" + localRootPath))) + return true; + + // localRootPath is now project-relative, so not a package folder... + // We need to figure out if it's a proper package folder here, or already convert the path way earlier + // For now, we'll just check if any project package has this as resolved path + PackageInfoMock packageInfo = null; + var packageInfos = AssetDatabase + .FindAssets("package") + .Select(AssetDatabase.GUIDToAssetPath) + .Where(x => x.StartsWith("Packages/") && x.EndsWith("/package.json")) + .Select(x => + { + if (string.IsNullOrEmpty(x)) return null; + var parts = x.Split('/'); + if (parts.Length != 3) return null; + + return new PackageInfoMock() + { + name = parts[1], + resolvedPath = Path.GetDirectoryName(Path.GetFullPath(x))?.Replace("\\", "/") + }; + }) + .Where(x => x != null) + .Distinct(); + + foreach (var x in packageInfos) + { + var localFullPath = Path.GetFullPath(Application.dataPath + localRootPath); + var packageFullPath = Path.GetFullPath(x.resolvedPath); + // Debug.Log("Checking paths: " + localFullPath + " <== " + packageFullPath); + + if (localFullPath == packageFullPath) + { + packageInfo = x; + break; + } + } + + var assetDbPath = localRootPath; + if (packageInfo != null) + { + assetDbPath = "Packages/" + packageInfo.name; + + if (!Unsupported.IsDeveloperMode()) + { + // sanitize: do not allow uploading packages that are in the Library + var libraryRoot = Path.GetFullPath(Application.dataPath + "/../Library"); + if (Path.GetFullPath(assetDbPath).StartsWith(libraryRoot, StringComparison.Ordinal)) + throw new ArgumentException("You're trying to export a package from your Libary folder. This is not allowed. Only local/embedded packages can be exported."); + + // sanitize: do not allow re-uploading of Unity-scoped packages + if (packageInfo.name.StartsWith("com.unity.", StringComparison.OrdinalIgnoreCase)) + throw new ArgumentException("You're trying to export a package from the Unity registry. This is not allowed."); + } + + if (includeProjectSettings) + { + Helpers.LogWarning("You're exporting a package - please note that project settings won't be included!"); + } + } + + AddChildrenToResults(results, assetDbPath); + + __result = results.Distinct().ToArray(); + // Debug.Log("Included files: " + string.Join("\n", __result.Select(AssetDatabase.GUIDToAssetPath))); + return false; + } + } + + // https://npm.github.io/publishing-pkgs-docs/publishing/the-npmignore-file.html + private static readonly HashSet defaultNpmIgnore = new HashSet() + { + ".*.swp", + "._*", + ".DS_Store", + ".git", + ".hg", + ".npmrc", + ".lock-wscript", + ".svn", + ".wafpickle-*", + "config.gypi", + "CVS", + "npm-debug.log", + }; + + public class PackagerExportPatch + { + public static void Patch(Harmony harmony) + { + var asm = Helpers.GetAssetStoreToolsAssembly(); + if (asm == null) return; + var m = asm.GetType("Packager").GetMethod("ExportPackage", (BindingFlags)(-1)); + harmony.Patch(m, new HarmonyMethod(AccessTools.Method(typeof(PackagerExportPatch), "Prefix"))); + } + + public static bool ExportPackage(string[] guids, string fileName) + { + var result = Prefix(guids, fileName, false); + if (result) + { + Debug.LogWarning("Couldn't export a Hybrid Package: no files selected that are in packages."); + } + return result; + } + + // ReSharper disable once UnusedMember.Local + // ReSharper disable once UnusedParameter.Local + // ReSharper disable once RedundantAssignment + public static bool Prefix(string[] guids, string fileName, bool needsPackageManagerManifest) + { + // we want to patch this if there's packages in here + var anyFileInPackages = guids.Select(AssetDatabase.GUIDToAssetPath).Any(x => x.StartsWith("Packages/", StringComparison.Ordinal)); + + if (anyFileInPackages && needsPackageManagerManifest) + throw new ArgumentException("When exporting Hybrid Packages, please don't enable the \"Include Dependencies\" option. Specify dependencies via package.json."); + + // custom package export - constructing .unitypackage while respecting AssetDatabase, + // hidden top-level folders (end with ~) and .npmignore/.gitignore + if (anyFileInPackages) + { + var sw = new Stopwatch(); + sw.Start(); + + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Collecting Packages", 0f); + Profiler.BeginSample("Collecting Packages"); + + // get all packages we want to export + var packageRoots = new HashSet(); + + // the resulting project-relative paths (not absolute paths) + var exportPaths = new HashSet(); + + // all the currently selected files from AssetDB should be exported anyways + var assetDatabasePaths = guids.Select(AssetDatabase.GUIDToAssetPath).ToList(); + foreach (var p in assetDatabasePaths) + exportPaths.Add(p); + + foreach (var path0 in assetDatabasePaths) + { + var path = path0; + if (!path.StartsWith("Packages/", StringComparison.Ordinal)) continue; + + path = path.Substring("Packages/".Length); + var indexOfSlash = path.IndexOf("/", StringComparison.Ordinal); + var packageName = path.Substring(0, indexOfSlash); + path = "Packages/" + packageName; + + if (!packageRoots.Contains(path)) + packageRoots.Add(path); + } + Profiler.EndSample(); + + #region Handle file ignore + + var ignoreFiles = new List<(string dir, Ignore ignore)>(); + + // collect npm and gitignore files in all subdirectories + void CollectIgnoreFiles(string directory) + { + Profiler.BeginSample(nameof(CollectIgnoreFiles)); + ignoreFiles.Clear(); + + var di = new DirectoryInfo(directory); + + void AddToIgnore(List<(string dir, Ignore ignore)> ignoreList, string searchPattern, SearchOption searchOption) + { + try + { + foreach (var file in di.GetFiles(searchPattern, searchOption)) + { + var ignore = new Ignore(); + ignore.Add(File.ReadAllLines(file.FullName).Where(x => !string.IsNullOrWhiteSpace(x.Trim()) && !x.TrimStart().StartsWith("#", StringComparison.Ordinal))); + var fileDirectory = file.Directory; + if (fileDirectory != null) + ignoreFiles.Add((fileDirectory.FullName.Replace("\\", "/"), ignore)); + } + } + catch (IOException) + { + // ignore + } + } + + // find all ignore files in subdirectories + AddToIgnore(ignoreFiles, ".gitignore", SearchOption.AllDirectories); + AddToIgnore(ignoreFiles, ".npmignore", SearchOption.AllDirectories); + + var upwardsIgnoreFiles = new List<(string, Ignore)>(); + bool folderIsInsideGitRepository = false; + + try + { + // find ignore files up to directory root or until a .git folder is found + while (di.Parent != null) + { + di = di.Parent; + + AddToIgnore(upwardsIgnoreFiles, ".gitignore", SearchOption.TopDirectoryOnly); + AddToIgnore(upwardsIgnoreFiles, ".npmignore", SearchOption.TopDirectoryOnly); + + // we should stop at a git repo (.git folder) or a submodule (.git file) + if (di.GetDirectories(".git", SearchOption.TopDirectoryOnly).Any() || + di.GetFiles(".git", SearchOption.TopDirectoryOnly).Any()) + { + folderIsInsideGitRepository = true; + break; + } + } + } + catch (IOException) + { + folderIsInsideGitRepository = false; + upwardsIgnoreFiles.Clear(); + } + + // if we found any upwards git folder we add those ignore files to our list here, otherwise + // let's assume this isn't inside a git repo and we shouldn't look at those. + if (folderIsInsideGitRepository) + ignoreFiles.AddRange(upwardsIgnoreFiles); + + Profiler.EndSample(); + } + + bool IsIgnored(string filePath) + { + Profiler.BeginSample(nameof(IsIgnored)); + + filePath = filePath.Replace("\\", "/"); + foreach (var ig in ignoreFiles) + { + var dirLength = ig.dir.Length + 1; + // check if the file is a sub file of the ignore file + // because we dont want to apply ignore patterns to external files + // e.g. a file in "stuff/material" should not be affected from "myFolder/.gitignore" + if (filePath.StartsWith(ig.dir)) + { + var checkedPath = filePath.Substring(dirLength); + if (ig.ignore.IsIgnored(checkedPath)) + { + Debug.Log("File will be ignored: " + filePath + ", location of .ignore: " + ig.dir); + Profiler.EndSample(); + return true; + } + } + } + + Profiler.EndSample(); + return false; + } + + #endregion + + int counter = 0; + int length = packageRoots.Count; + foreach (var root in packageRoots) + { + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Collecting Files for Package: " + root, counter / (float)length); + counter++; + Profiler.BeginSample("Collecting Files for Package: " + root); + + var fullPath = Path.GetFullPath(root); + CollectIgnoreFiles(root); + + // include all hidden directories (end with ~) + foreach (var directory in new DirectoryInfo(root).GetDirectories("*", SearchOption.AllDirectories)) + { + try + { + if (directory.Name.StartsWith(".", StringComparison.Ordinal)) + continue; + + // this is a hidden folder. We want to include it in our export to catch + // - Samples~ + // - Documentation~ + // - Templates~ + // and so on. + if (directory.Name.EndsWith("~", StringComparison.Ordinal)) + { + // add all files in this directory + foreach (var file in directory.GetFiles("*", SearchOption.AllDirectories)) + { + if (defaultNpmIgnore.Contains(file.Name)) + continue; + + if (file.Extension.EndsWith(".meta", StringComparison.OrdinalIgnoreCase)) + continue; + + if (currentUploadConfig && currentUploadConfig.respectIgnoreFiles && IsIgnored(file.FullName)) continue; + + var projectRelativePath = file.FullName.Replace(fullPath, root); + exportPaths.Add(projectRelativePath); + } + } + } + catch (IOException) + { + // + } + } + + Profiler.EndSample(); + } + + // Debug.Log("" + fileName + "" + "\n" + string.Join("\n", exportPaths)); + + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Start Packing to " + fileName, 0.2f); + Profiler.BeginSample("Create .unitypackage"); + var dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Unity/AssetStoreTools/Export"; + + var guidToFile = new Dictionary(); + foreach (var path in exportPaths.OrderByDescending(x => AssetDatabase.GetMainAssetTypeAtPath(x) != null)) + UnitypackageExporter.AddToUnityPackage(path, dir, ref guidToFile); + + var compressionStrength = currentUploadConfig ? currentUploadConfig.compressionStrength : Zipper.CompressionStrength.Normal; + if (!Zipper.TryCreateTgz(dir, fileName, compressionStrength)) + { + Profiler.EndSample(); + throw new Exception("Failed creating .unitypackage " + fileName); + } + EditorUtility.RevealInFinder(fileName); + Directory.Delete(dir, true); + Profiler.EndSample(); + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Done", 1f); + EditorUtility.ClearProgressBar(); + + // Note: "filename" is actually "relative-folder + filename" (it's wrongly named), so we introduce "outputPreDir" as the (folder containing the folder with the file) + var outputPreDir = Path.GetDirectoryName(Application.dataPath); + Debug.Log("Created .unitypackage in " + (sw.ElapsedMilliseconds / 1000f).ToString("F2") + "s at: \"" + outputPreDir + "/" + fileName + "\""); + return false; + } + + // Debug.Log("" + fileName + "" + "\n" + string.Join("\n", guids.Select(AssetDatabase.GUIDToAssetPath))); + return true; + } + } + } + internal static class Helpers + { + internal static string LogPrefix => "[AssetStoreToolsExtension] "; + + internal static void Log(object obj) + { + Debug.Log(LogPrefix + obj); + } + + internal static void LogWarning(object obj) + { + Debug.LogWarning(LogPrefix + obj); + } + + internal static Assembly GetAssetStoreToolsAssembly() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + var assembly = assemblies.FirstOrDefault(x => x.FullName == @"AssetStoreTools, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); + return assembly; + } + + internal static bool PatchingSupported() + { + // Harmony is not supported on Apple Silicon right now; see + // https://github.com/pardeike/Harmony/issues/424 + // blocked by https://github.com/MonoMod/MonoMod/issues/90 + var isAppleSilicon = RuntimeInformation.ProcessArchitecture == Architecture.Arm64 + && RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + + return !isAppleSilicon; + } + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs.meta b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs.meta new file mode 100644 index 00000000..48b31ce1 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreToolsExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ebd00d677f4f42e4194adbc4ea008310 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs new file mode 100644 index 00000000..890c66f9 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Needle.HybridPackages +{ + [CreateAssetMenu(menuName = "Needle/Asset Store Upload Config")] + public class AssetStoreUploadConfig : ScriptableObject + { + public List items; + public Zipper.CompressionStrength compressionStrength = Zipper.CompressionStrength.Normal; + public bool respectIgnoreFiles = false; + + public bool IsValid => items != null && items.Any(x => GetActualExportObject(x)); + + public string[] GetExportPaths() + { + if (items == null || !items.Any()) return new string[] { }; + + HashSet exportPaths = new HashSet(); + foreach (var folder in items) + { + var actualExport = GetActualExportObject(folder); + if(actualExport) + exportPaths.Add(AssetDatabase.GetAssetPath(actualExport)); + } + + return exportPaths.ToArray(); + } + + public Object GetActualExportObject(Object obj) + { + if (!obj) return null; + + var path = AssetDatabase.GetAssetPath(obj); + + if(path.StartsWith("Packages/", StringComparison.Ordinal)) + { + path = path.Substring("Packages/".Length); + var indexOfSlash = path.IndexOf("/", StringComparison.Ordinal); + var packageName = path.Substring(0, indexOfSlash); + path = "Packages/" + packageName; + + if(!Unsupported.IsDeveloperMode()) + { + // sanitize: do not allow uploading packages that are in the Library + var libraryRoot = Path.GetFullPath(Application.dataPath + "/../Library"); + if (Path.GetFullPath(path).StartsWith(libraryRoot, StringComparison.Ordinal)) + return null; + + // sanitize: do not allow re-uploading of Unity-scoped packages + if (packageName.StartsWith("com.unity.", StringComparison.OrdinalIgnoreCase)) + return null; + } + return AssetDatabase.LoadAssetAtPath(path); + } + + return obj; + } + + public string GetExportFilename(string outputSubFolder) + { + if (!this) return null; + return outputSubFolder+"/HybridPackage_" + Path.GetDirectoryName(AssetDatabase.GetAssetPath(this)) + .Replace("\\", "/") + .Replace("Assets/", "") + .Replace("Packages/", "") + .Replace("/", "_") + .Trim('_') + + ".unitypackage"; + } + } + + [CanEditMultipleObjects] + [CustomEditor(typeof(AssetStoreUploadConfig))] + internal class AssetStoreUploadConfigEditor : Editor + { + private ReorderableList itemList; + + private void OnEnable() + { + var t = target as AssetStoreUploadConfig; + if (!t) return; + + itemList = new ReorderableList(serializedObject, serializedObject.FindProperty(nameof(AssetStoreUploadConfig.items)), true, false, true, true); + itemList.elementHeight = 60; + itemList.drawElementCallback += (rect, index, active, focused) => + { + var selectedObject = itemList.serializedProperty.GetArrayElementAtIndex(index); + rect.height = 20; + EditorGUI.PropertyField(rect, selectedObject, new GUIContent("Item")); + rect.y += 20; + var actuallyExportedObject = t.GetActualExportObject(itemList.serializedProperty.GetArrayElementAtIndex(index).objectReferenceValue); + if(selectedObject.objectReferenceValue != actuallyExportedObject) + { + if (!actuallyExportedObject) + { + EditorGUI.HelpBox(rect, "This file/package can't be exported.", MessageType.Error); + } + else + { + EditorGUI.ObjectField(rect, "Exported", actuallyExportedObject, typeof(Object), false); + rect.y += 20; + EditorGUI.LabelField(rect, "The entire Package will be exported.", EditorStyles.miniLabel); + } + } + else + { + EditorGUI.HelpBox(rect, "This file is not part of a package.", MessageType.Warning); + rect.y += 20; + EditorGUI.LabelField(rect, "Please export a regular .unitypackage.", EditorStyles.miniLabel); + } + }; + } + + private static readonly GUIContent RespectIgnoreFilesContent = new GUIContent("Respect Ignore Files (experimental)", "Uses .gitignore and .npmignore to filter which files should be part of the package."); + + private static GUIStyle wordWrapLabel; + + public override void OnInspectorGUI() + { + var t = target as AssetStoreUploadConfig; + if (!t) return; + + if(targets.Length <= 1) + { + EditorGUILayout.LabelField(new GUIContent("Selection", "Select all root folders and assets that should be exported. For packages, select the package.json."), EditorStyles.boldLabel); + itemList.DoLayoutList(); + EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(t.respectIgnoreFiles)), RespectIgnoreFilesContent); + serializedObject.ApplyModifiedProperties(); + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField(new GUIContent("Export to folder:"), EditorStyles.boldLabel); + + EditorGUI.indentLevel++; + if (wordWrapLabel == null) wordWrapLabel = new GUIStyle( GUI.skin.GetStyle( "label" )){ wordWrap = true }; + var outputLocation = Path.GetDirectoryName( Application.dataPath ) + "/Temp"; + EditorGUILayout.LabelField(new GUIContent(outputLocation), wordWrapLabel); + + if (GUILayout.Button("Export for Local Testing" + (targets.Length > 1 ? " [" + targets.Length + "]" : ""))) + { + foreach (var o in targets) + { + var config = (AssetStoreUploadConfig) o; + if(!config) continue; + AssetStoreToolsPatchProvider.ExportPackageForConfig(config); + } + } + + if( GUILayout.Button( "Open Export Folder" ) ) + { + Application.OpenURL( outputLocation ); + } + + #if HAVE_AS_TOOLS_PACKAGE + if (GUILayout.Button("Open Asset Store Uploader")) + { + EditorApplication.ExecuteMenuItem("Asset Store Tools/Asset Store Uploader"); + } + #endif + + EditorGUI.indentLevel--; + + + EditorGUILayout.Space(); + EditorGUI.BeginDisabled(true); + EditorGUILayout.Space(); + foreach(var o in targets) + { + var c = (AssetStoreUploadConfig) o; + EditorGUILayout.LabelField(new GUIContent("Export Roots for " + c.name, "All content from these folders will be included when exporting with this configuration."), EditorStyles.boldLabel); + EditorGUI.indentLevel++; + var paths = c.GetExportPaths(); + foreach (var p in paths) + { + EditorGUILayout.LabelField(p); + } + EditorGUI.indentLevel--; + EditorGUILayout.Space(); + } + EditorGUI.EndDisabled(); + } + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs.meta b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs.meta new file mode 100644 index 00000000..7e024c89 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/AssetStoreUploadConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 72b48b51417c2fb4390f04d9a1d34a86 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef b/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef new file mode 100644 index 00000000..0ca9819b --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef @@ -0,0 +1,26 @@ +{ + "name": "Unity.InternalAPIEditorBridge.011", + "rootNamespace": "", + "references": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "AssetStoreTools.dll", + "Needle.PackageTools.AST.Harmony.dll", + "Needle.PackageTools.AST.Ignore.dll" + ], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.asset-store-tools", + "expression": "0.0.0", + "define": "HAVE_AS_TOOLS_PACKAGE" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef.meta new file mode 100644 index 00000000..5f2028ca --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Needle.PackageTools.AssetStore.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1ef0bbeee4c5c164fadb7031fd63e223 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins.meta new file mode 100644 index 00000000..b6edb59b --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: defd0bc4cc87c174cb50775754c25271 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md new file mode 100644 index 00000000..edeae8e5 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Andreas Pardeike + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md.meta new file mode 100644 index 00000000..ec2711b5 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Harmony-License.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ffa94b56840075044abe40a4d27101b4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md new file mode 100644 index 00000000..662ec0a5 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Hardik Goel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md.meta new file mode 100644 index 00000000..4749e298 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Ignore-License.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d99054c7a8b9f0418ae1cf68d10841a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Harmony.dll b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Harmony.dll new file mode 100644 index 0000000000000000000000000000000000000000..0601685c8ba7f4651b62f4ab37f87d8812d0764f GIT binary patch literal 769536 zcmeFad6*nk)%agi)m_zH-7`tgOnN4nkPMIxMK1$MSdxGcc3CBW7#1OfeM@0?qL8NB z78Mke2)IWS45GfMsDQiTzHbrN7a=O{+xxn`zOUQx{hV{Fx~nJS!t?z8{LM36b?-gr zo_p@O=iYnnTBn|So8?%RmE!m0la}=X-txCbpa1;P0X($$Lqpa>*{|&Vfq_%LviDh6 zT-lhst{z@qzv$Y@i!a)^G2Aq{;nKOl8oasMD^{a6IC$6wxp;#2>dv@CMa{mbBgde>)JQ=2ZmeiQz0zBkI3 zIVH=_w-j}{}e}3rkbV3Ty&wKS7AV2w85_ZBYA(^1; zSZ)Y?e=s{ggq~j%&+pj}AQFc6Ltwn@AQTX;MR9uZ){9t-CK^6hW|FDcYYOm;%Z z2(40kAx}5li|5P~$Y(MI@v00?fxi6xbGnP5XorjcZMu$i4m2tAg6$V`m6Kg>N4_VO zO#7_^Rw|r?++eoqWksfy@=SQJH*hJoD#aPVaHZ^xt;=~XrTDHc0!L3py6aJQDaQV zPSq^o%eB@hSC&;rgnjXs##Jg=gH-61<0v|H zdPf+5I+8A=!~MnK7TjtU4_aVCE8_49Zo#{-T6Ah7UV8~4hBn%RD!H=+L1j_Ft1a-_ zRj@??4f6pt$XzMTgV&}-G;|8ysuvML9LK3$=e4H*6w-=H*fn1JfL?&tJ}{1!sg4%& zUXOM$Tn1>V*IpiDc{#E5^w^nq&T+Kt(#Kdd))pDPT}uO`UjTHeS`+eLSHAUF}2 z?F`!?neuBxjgxuhZ6_1bF#DO*uoIptfH~>#G~R=mR5pADj_gQkx9?S5H#i;NV+HM- z2k5hGTEjKRS|UD8?|R;Jp?jtWBa+@3yfnQtacFwa;)Mov+4WtgHHS9bO|@V@ z<)&M7t|_}oqFJPPSQm%g$8w6 z)1|YPbm^BR-Fdw1CXE)v6w*|{v`bBQ8|O;802Aqwhnc9TbRR0|x>kpDbCNDKU(=hL=jZmnBgnNbnYFTY0sS zl{!V7A>{$jf)f*0sdp-mdzN##mIKg6$}-vkgTa@S`Xi z!!0_&WpEJ@aH8ntNA2+>dBwdw8F6gg?Ta?7zaok^ZsNhB@`#e^pS|GUA(A9JzV7zL zb2qF{2F)jEoFJ3M1#wCui~C50rlDXj`u{GSKJhGA*O%!D&2*Bvg?sY5m*IEg;>iu} z#+dCzG21F1`W5|aUykT&qloDcin0`3fwvf3DOxd$=oBzh471W()JN|srMIVu0s%zy zV*XG@(I01>$>jDcm${9rLEEBr@wA9O*KeO zyC+MHxfbM7M<9VueFWMdP`GKXsji=?>6d^S|B(! z?cffBY33zSU=-=tKWerRGGc~^5+8>}aw7^r~iZ|Q@g`78Ug`R^6{8}fr&V`?0)`mR^wWwMAl*vA$Y9;rIU_CrZ0Gbj;f=7A4iH{t#7jFpx@Ye} zw|W9#A=*XTgDSut)salWD`aGRTv5b;CbLqU9w=v4@06@4pQ)m!ERYk7j3_5G)RmEJ zAzN+5;6gTh0gR6L-bgN0@C&(u-^Y4BU36kP*d;UR92|qYbexe~I!R|_u#hhd8fIfY z$I27*Mi{DZY_w~wqwcqmwPoG0 zcv{RXw`8}Li!M4X@|P;5S}Wz1ZqZt$$~W8LE1*&xizI>0`1Qld!h-OXILk#Dn>rR; zTSyRjWe9DTghH=+8MFq3SWkKu+wFO~F z(mYyTc2io!)*2qBQH0W^LTLw-!q@X~n*!X7u*h9usqyx*n6sPG5LYKWw<#2Lq+Rub z@6bqA28zMSO!Il@v90s1NV3qL6tp`b?N|05wt_d{%GnG|-iRZ(i$~SRcQ=mw?gz9B&VMaZ{<~+V{0epxZ%f%Fj{u%XG#C}2|U$;doM{31SddZ ztGLQ8iP+lHkskDf?y0=x&({9VvHQC^yV>pP?EbC}BcZ>mv$anP7?@Q4f7(&^pOndE zUCVt6C9s1}Qbw%=BtR zpq?>q-Z)@cG$&EKoX3RE*kMZvEc%b1#mk=8()8@+GUx^*W4hYbD&b;YYqh-Wruf27 z3rmMdz~aAatd&0z&A3s5g3kcV+fBhAN!x`q!wPX{?B)tyqdmiG&~6?qfMH`Xt-1vo zU}-|lLxGso3|6p)tc|$YppH5-S(gewOFAQ&%3<_qpA%=c;MPWlv%%-_sLd680ataR z;6;Jq3y6yQiv)))+)Ii2B|No{&?04~i|A?GB4t|#2m@o9yD@+F!EsKbOn#YYt8+}> z7@3>U>3LLwiJ~thajukvbQVX^{n_N~Yy6(hZwy&ee)^Y+-j@<4KP@c6E{h98B|2Rc zvf5NK0B#Cnq>uX$aZ4GwGV)$emdcAHy$uoHj&!7E)-(J%{8Wc+?X2vkbcW$0 z1eKj#bndg_&{D-X+I&^f&BF<^n@4sbi)@+mc>(F6kc>s`<{Du1B*(%`OWdP5S0akD zr?hlsM-c$}(Yzw)aYV^GqnYp<@TFFc+Ay+;U}u$CQ@vW;n%whNNV&qA3V6NH>UAL&r%qFtyz9TOym~c2gpR zr;Z}oEa}17=9OEe$GJfpS-Jn zoeJYfqWv(m83LS1HOY24dcn(yumz6X|JUHcaVp?`*_ z+CbUJrs>W_K!*<@vfFvcq^Pl=j>j?WZiVf}V^At}1R}G<^eU3a8>mnC3UL^m7M0*(QN3WY;RryYCcmvYGPX&SE-l@9~Z7!P;$wP zMj%5Ov#e%9=hvC-yl!V{K}OeNb_TnNQFeDx_oMXzDwkhfQvW?@_Pr83IP6Rp#SwlV zP(lIRUDV>Fp?YjRA?P%|F`Kc=MJ4L2rd}7+L1V z8<*3}VS||k@7WTGa-vw_X_B3YvBUl~{cE}@&EPy@{25P;+>QT&+}fu`4g+#_xklWb zA>{rNS*0ruin6`;Kg#xnJN)j?d2A9qj6I*Xa zObMA0bKPt)PuU};gv^L}$!swhLd-~0LT1D~XSSHBJz`48jF{(1Ol?ChrfrbFIRm<; z8T^boUt5R|gT^<$A$+5;ugWSKnsW=~L#;iQ=EU^8$D>A4c~ zDQNLUPZ9swPZ9s}*>ZCF9yyVa896y$Vyeusw=6muY>L_Cm#(JL+iT8f#Z3qM(I|_^ z-M-424zEyZ#zr}7R(f04_HmWg*)Z*ghf+#5_&J3tv=wtk0<1b-B}vG-+Vf_oKevy5 z-0z!o5?y|j8kS6C1S}Xb*)sjTG9aY(U|=X6UMVb0$t0cI5i3S)>a=wR{K#MZVcN&o zZYrwnN4ie@Xl_kc4=8MaS?E%x5TYs|rI@S4xm<_9mw5&Lp=J7rzh_$BeTWa{g1 z>)d6j&YIPA;jaiT)pGUiU7XSI*M!|GdFaq&r0Tn4yumDpzw9Dr4Q4H$9c}!EDB*wc zhyph;Oquw{>(?3U&NrL2Vj1&(iTvzMej3YsCM1jDKJsdRVGb7MfjE6-+712#cW&|p z7!!Fl1vNO+_*o8YFWdk$ye7}%HUb8{@EQWL;eQKH;oSsjJ{A|fUBa5#>*nUPo&TD%(0+D?$*wQlRfVpJt zgB*kHp!jaSIG7oBboYU42LLL$-F~*}X3Ty9uV#;yy}*@aNHR<{uwiw0VO%b@RfXQZ zJ$gCzxD4BdUid#S833#d?)EcP*E2M;(Ov-GVkqJhUG;T}_Y&whL7K#TWiRI?*z;^R z{1XI|>~(o6Si}1oTE{mid%trMxt^!0N%ed+S?!4M%4ay?{{pU;)2Q|T;gVUnbDi+d zIK#gPM0NkKxXNF&8-L^7qV;0A`|sj>rZ{yYC5y2%Uot+VvdfEd)4dlmrap?il*o(S zRGg;3v}^b68zm%|hS{jIhlU25&aV{R zMLg%a3wZkOI8Uam*7;pt8BkhKENJbcO|oSs*>&sdka)!Z0K}rUU6ZKUZrRngR|gZx ztjQSkKy;_Tdunavip=8N)M#e$oD~;9StBd?$`ui_E6HlEI9OSfEiTKuI=C`4hb=F= zLvgcX>jtwPdj}t@EO+Y{2wR2_GBKknzcQa2K>keAl8h|rj3Iw9v2 z8xC>u!&at|!qGY#kVor&7lQN#cQ10A5>m~Xw`okMUK!)c(ylNeU{fpe2gs6(xQkZp z7*jt)pPGchLcvi&VVXpke4M_$Q-@${s`1=<=LeLr$^al<47(q5=9sZAc=U!O# zoZxPFB5U%>Vc*}wJNz^7V!krZ4*!HJ3Va0VX2#a#Ggo;Vm;XfU49B`0J}U5GC;6D{ z5PG5N1nJj`u5PWmaM6YY*7~wLc_cG-7qTND5p1>$h;TGdY)nW1*PApiggR|jUz!n? ziyY=%H5Pijm)e@A(%8khF_`g4@Z-W4GYE4si`Pu~8Rc`zV@KZNHRqJQNo&%w^vzy` zb4*$&fz&4UUf+#eO5>OK^Di9C9_J7&6)?}Q$gi?!lBeyi&sS&>scz!Ri)%t$b}^q} z5=<1t3p4PhYXdhxfi|-*AMV&W$4Ru&0n1v$?__>w^Sg-OHT<5(?iNn&{t(QF8{R&8%Y&M zTtRpfY%DFHxUyUHszPex@?UwGkQo4Y8KAEzjkOM^wS^^Nxb-yS7ENv)fjdGf{&S>y zTPpw7_5k^&Wc)@R`dfOtJ^_(bV9Bo6-d2-KrYR`!RM7Z@wX3HDpEOnUf-8uk0)TPDhgdGl&aj`{* zcn5QMjIS%5xM=;?&y+f0TL*zpmr{_WMRWxdq~>|yT<|FBw-Vq)0BqD4fHm?qAn1Kc z(lTQcC%9LmR~OccE{(X(0M?h{bahj5qX5kq#&u61bJt%p9WV6}34- zkl6b_V>dpQlE`2wl}_?@4*V?_S>DXB!VXwoU|Xy_g*_(ACcN-YAil!g;3c??Gkjy$ z8N9UTytV5L-+)v1%1ghqgmhMrjx)N}4)9chmjjkUW1F>~+nvojnYG2Ma=R^0Z8gxX z`SYzTUE+Y0p~R;g3&DKQ!v#EuJHGV_z|%!}h7*K!M9SJ$9V-O*i}nkhOSrM39L5Sa zBEZH%@F}ZQ;{n9cLJrLH$uk|kj{xHi--}ar2?@XnAMEoz6#0a9w1epE2-9v#Af!Gh zI3nlm@NzKx+a!NSH+f;^EnOdq^9cA9z|+y696OF0Z^xg{c;P#FJHdSfv)*uolWo$r zrh*c3EQ)1^=`T&wJWeaH^I|U%(fx$RO;qZD9NS@1;UWObzn2*u9d^Ta0Wa_DXTY&l z7^P7aK}mDpyo{WP9q(9|(8L}hc`)W^s&yV9tWw$*ULno3-=gh67^357Y;M>#I-aR4 zbbCtP4UCmMk5Y<~*B04D-6+_gsNELr1y=B+kQF8>M;ICm_lot0keZ|QPmQF;-e7I9 zvx$goP#;@2eqLjrIKHFv>`dKHdS?5`xb5jinbvx!@23A9H7?Hi>`SETIGI`^v1!gC zxVnI2Zu&L$E;l|Uj9x5^nmrn=OT?`v8A2`*J2L2`fvA*f?$QRUrhbc>8=<*wxSyf{ zLa=`8Qb1*~r!4CW*3fq>`Xp>&W~_()*SOjG-lFAB$sYI??Y0a8q+O&OtV1cE$_l$F zvNIbq?cn3^I4V0r+>+Z8D=}w#!H4nMTDV@gKglMdM9v8?u~{FqgZB$=@ByCX-F8z- zoyN$iW=Ni@mnyUBrTLk5KM78w47mUaRf2$rL6PzFTj39D8T&zsGpvB-S8k*UsN%|b zy>W`3yvY|*Sl*L7=d5^^XM1WL>+ruAe1v3l6jXVd3E#AarYg@Nt8H*?Yd<}YLmGCb zkbb2>-x*g1If?aSFRRf>yGGipug9=6+e(gvPXAarZ*6_8S#p&+Kr3Ud(mY5pg;SD; zmA@xrZg_y^B4o0JLu27GUX1qT<%P?6%4WBeoiW_#h^si-cs(^bTmjVPT!m&!ArlFR z7t)*PNfTYfcp7Qh{PyAZTz)8mRoR3lV1Um`YONa)2 ziTwiMD!@7ludIsF5$zlC3w||7(qoUHp_o&O*+NdI^ffA3Q5D?ZsGvPv?5SW>LG7kg z@&+aEwywb?JMuq+N4I7LjON(nCE+GXyGc8cl2afq!!;4DjwRGp|0B(2h@7D;El9OE z7F@(^s===n1x!8f_369MFUX!-0!zKNm2C~XX4C@8_9&uPb zM(f|rZ!>O?tqhOn+;?a@{zPdOW7m1 zPG=OgeT?xW%@Nlrpf(auJC-Dxqq9zW0LkpzV{1Yp0naITTTg*OCF(e)DVG2fdL}gE zq=coBj8n*Lothaz0!(N!g7TJi3fUgpaS9?66Pk=b)8mf#PQl-L^2`(@z=S3vpl9w# z&Y{+#PyKn2027*wKnLND90VyaU58sjzEGM z)vryTlEnF{;2f_w0tqOCN`2NeHcA?E%#4#HEk-N@ETadS!MSXx(HzbVPXv~f%O>=E zU=KAPDa0|b8P=1$-Molrcv3gEYSN}fM0Rczp#&d--@ZhLV-mxCBu?&Fa?0vgdCX;dh&r?}MqfcQVi zBib`f_3GP`e2@6w+=IVG{Mh+1{(a(qd(VHr_!)Y}aK_$!d!*kdeuf({oX)UsPxd>+ z|IQx#-Qs^w&yV@rw@3OR@xM2QcdjJ+lRrd2+e924k;dZ1#x3&NwU|(yC0jfmu0{BA zfxwwuAP}uRN+cPpo&jil>JVH{LV9e)sLB=ZnE*0x7PQK^mOvCX37&PKfpjktcx#!7 z4|HU3gy^c zEBH9&dZgGVYJ1tu>%fT5E`AQY#<@f-4Ynja8yrBZ?lf68KxHrj!5r69j-MCI^8|Aw z)e->b*$-4)GL-V2CIiz{&NVjQU1XwKvzr?MX}*jxoz^|;oX=I87t2L$!n9h#Z7C3! z6UgV2M%B*9d=UDphwLY&as_vBcB;7Yr3lYf`_+{rQ0_{!kbrJFx_6SHwP_{1TA_Xx zGBS%Frfz$iPjxJNblRzn)o%vo>1IB&|IuJX^t}+Bz{das~iOAeIj zG?hW6GnX9#U*gpvTB>}!lQ7MtnAk1)RS}VP651qjN*?ZqoU83SE|*KSGx5Ad2!zDCVi({FVwf&dJ%6Yps8?&Ja*gtQAVj$TjcQi-nGv8Ef5)8!GhZ;;Q=fd={hU5{c~u?`M9!b&F!x z2YfM(B&uocZSp?k1z(4Y)=LDXDNiQh=7AU~f(g^>B3fvk>{^%Ckk`0EqTPy{a**>_ z@4#p|O4`oH0LU4h?Sih@c2mS5hk)#+$VVska&F@S^t`o=fKm3i3tz=$i%CG(9Sgnz z84ltJxc+Py%7hn!&hAd#$~emGK~tpLzJrIFakt}`cAp?xW4%<;jzEIt$gO&Uz3YOw zF)J!%i7w2y={|j}N0I*`qSC894>DpbNoKX?20sPSBxyILID-{XwwqFt>I@FT&j9Xm zVPJ<)rDya<*|u+RFjFekr|-!~I?5wg=v-&-I-{RW&9mVwnjabVRljW$i;D4G9p5QQ`11=#1nl z!^64Ya&hLF7s%@@Dg=R!Sbr2G9o~6NvWLA_t*Y46@ zWRaGM9AS(p#z;0%a-~%s)rF&v`|Oco6tD-CV(_S>6M<*dv$V3D(6SNE7O7eawS;1X z%y9b=vcjc23v;5P{I_CUD-@)|FewmOWunQAnTf37xkk4P3nJ5h#)2x@o;iq%Dr!*}6e%y-f{Y{z%QSjsmfYNZQ%UQMJBi}ZTo;nD+97!|jiGD>a|@aE)wxj; zMP#dyX`v*|@JbNYnrd2|U%!Q>#BAQygW0mf+Vm#c!0RnCaxlH3^Xj(stAWM7JtUo* zZLPNVeYSDSyv}xX{%Gl2=@b&Zovz6E=BA){hX(DSU%y@2Fx{%}=n`PgtG|jM-HH-k zM}D|+C<9`?@fF_`m}42RROqb5;!qtIkTCkL5L z3dKO^sAZ@h+#o5i+RCuPBj>sh?ww*BZ<%QC(C za}iYkl1xMoo54C3dX8RfRn4Vp8Aq?RnmgcxEhtqpPSEC!Klq`jB2A67UQWnFCi}s( zCh9d#$$G7=s5S;JV^~$;WyyF90kqZVK*LKk8toSl;AqYFh{&lMch$$FiYC&`JGrZs=CxhW`W#w-|N^ijYJErhmc+G2v7FT)FL+nDF&8!(VE`FPa&Cs|lZxJGcEZ6OO5ol&;&}YQj&O8NSVg zr)Gvn`RbQvHKO0%F0o{-64TW>PTE;Dk2jA%h6XY2P+kt28)EFbl_e3zd@$GvmBi4? z3|uxVF)<=Wc6b}na?#>$TsA_=Q>BW^W+8=TaB5!rWkjQE+A6UnxiP8+wtd=KMx%W^ z{0(uoKhc}9cN4YO#H3ZvdF@vbHPI~n1R{;wNwd@uNU&O(rNun*W_>s~4EJEVdX%|K zve#S(cMz#s&W5kxU0k+zwivz=R~V3t!8Q7x$ri`LR{_a}uja`;b=P_s;M zy?nC%3u#b3LEP%39efL>Rx@c!RZ<5txHF%SU@^=})dLE-8ebhQvE zfI{xVRX1q*8tZjnnaa2FVnXBG>`iXWbr7q@2Ks}8?@0PPL|&|1jZV9)!upLndB|Np zmFkg+L<{-gjRJThtr0hK4A#!C?+@h!hMpnNL2M!4xC`7Z2_Vtm5Xao7e#5_t$=v_l zP^eao1dFT*W!=dO#OsmY%IBoJg*roeGvY2H%f!7W5%*x?#?ty=T=vy-XG9d+ zl!($;bM2a$iP9_&&k5g5VB9bkhOnbLyHD5;N z7Um{u1YJ4@utL3KWLT(7!kOiHNMa#ZduDjq1_q?*f^{^Fe>H6vDdM(0j?Q;-p|) zNQr1e(eyFeIJ=tfAUc^Bwe`F)8sFd0LqUv#AQdB5$QlFy6yfDIA zx~k4j2t@Jguc81<1+HF{4C~e2VK2CsG)6`Xqs>Lkb&eE=i@{qY(ZRxKvGG=1 zEeS7-1}nkSer#l3Vcx1g(}YGjpZ$W;!B`h|hHrz)$XH=))u(&yt~8`0P;mZ-*Lpri!!MThPeUf3Vjg zZNP;{l3KSTV7B1J;}$b>6Axm1c4%Z*#OB&Ngjrv0v&spDOm)1F<<>K!&eC(lu(%IO z;2W$iXTdkgp7vUFw(lhB>RbL#cMYYci)VHxXlQh-c>l{z+#NdDeKNf}8^rcGmT>ut zE=KLn)0x`LyEYl;7KiT^8&pK85cBHFDxP5d{=tJr#@lDSDd)9$Z@%zAhU zj(`gSe$z+SZ3?!?Lh`$Y_lZLPzm&e+x=VoRD`U+-Fo`twk*_@b*_mvpOD@GjWvh=Df)w_6{3xLiog;M26tJ559}3Auwo_@@Vu zdtVEU-4Xw{36oCi#DhmTY zgldmncfYXF>3-u)Y2r4k+KoB z#?Z3qiP{xW_W&YlV`C&kji?oCrl@;SjSM8kSw%fl&>Z)ZDjpm~m1VE-h{?96bwwL^ zdNy{>j%j;Z_Ns+?ZBGAUW&N8o0_64_kX1A#-~&x*K41zTH$L5lg&| zG7!ym3jiU$NkCm8cCq!$yU|w_Vh@lMVlUJPQT@+{Vp3mwNJfZ~;=d(C6l~VGvSQTJ zbuK0{ordQ4xI~D+kGnSd;4+zDmd>~9D&I7L>0Mmi2Hi&V)y|7!EZqcj+3CPY}8@%Cc2-hY;`S$ zABy2D{w968@9{{uI$d-?4(rm{%VAkJWKPQsK1{rtXFP;45#zEg#yFhqS00e%`ZfvN z!IYHd@k(gX_ZMWH3Q|t%Eih|~9p%{DuPh!Y?9dJUJRwE= zm{g5}?c)bzIYHJOU>IS)i@ z&gK{i4ssVfJ-HuX4^_$#{i7k8aaB!_3ApY#WL}QeUL>bO+VW~nloTaQPSLpBcj#I4$Z|fPe$$r@&T9{1 zax>x1#*XGuI9)x$!CA)U(On;B3!2AteS`Rp?fO{B9rZG7^K=_ugJVWoyLidm4+kTD z0<-2|k~tXhFj}$2;v%&G9^KuUf*X7S#uz(C=WLpm|6(g6tFXfBFm244S~j`*z6BZ; zb4;c=LF)9cD|$gUE+HuRm?~X2M|wLi6TJHZ8%d9ixWnn-eRi>|a>j+ni(> z@nm0U?<9*6L-QdQ4O>7~3%khOA2-^paWOqA!8=9!})6DG%skeDBcvaP|{fLh3= zQq2E-%)zZ5ww~VNZrG(1uQ|Sjh$u=Ckx4bHr@1)ds%OzH>$BD&e>3uuc48T2dzO@~ z)C#-#DVTTIknw5WwFQmO@Zt*7&+?+XR-hYx4xd~8w(*Cb$JhRX;K|jbU&Jx(eu-z} z%M#WRh#YON1Sg5w^~L&%VDw^rRbnxtLM(vRjhEC2s7N$i`iq zwlQd%-;=nKC(3V{_t}xYuNCEf4B!^dBugvIa@;U_;RbosK~Ca{e6;x+5`>Mw;@bU^T4oMuL1Z;-aQ?e`%!Ex7mMn053a{j~ zr05Zb$l^X^@hs5?+3}YoJSv30uY?5>&}mfKAL_@!faB^g#SutAgHmby5Wk)z+`s@? z_UWa#U7>PRCi_an$GDje(A@bYjhC$rXl>N3e+GfkV4-t<_yi=X$ev31Bb*gq57W!a z;0L|({S(`SL}}OmN?Y_};2lXsZcB?k81f=$bRHs%=6xc5gwlgV30FCLK*(V66_ygZ64l=0O62Ryykfwn$neGVC}6MYJ(H8k+;&q7$s z`ZGBAZh(mCrzBhI2qd8Gs038PO6$XT*+%toc{Rlo{tPs~@~p;w#L3BN{GSuh`ZOS~ zDNlpuO}nJ!HhuvxK$R=uB;FYq`}bp@hc5JfNtD{%=HS!S-6@PH^oF2xxso z@EiXn&WFVrCH&t6G=3|gA60@Pi^lKp=T>5cTVD8k-1*7{?5+F*uEA{c6JWT_FY=WA zbS|kL80S|uE(!qkp;#)_g?2We7P#5wCkYMz2mxlWg9QXt=w^hEtlT!>L;X*@YOg~) z9Ll+_CmuP1N|!IFhAra`(LsiD|HpInIu7%Y9pS%?MkE!WCY=2lq*6y90fMaPLC%&4 zjw6UFl~E&+QKJ>HESE{#8L~to=8lw>b@k6p8A)BHidyGN87(J{l+l-jx)Nfuz^EE0 zT;VLCRa$RJd;68fzx_(N08~N{Cncp0CCOpoMzd$j!0nHT5sG>OS7isyEBCc{;M?cz{Tl2>z<=5~`w% z)K{cfZ8};Wrc_p3%NYudCeIZYa@K?Q_A67-d&Q|v^UNs3yjL7%a16$@OZBU0k1O{! zSE_p%{FKI;38e&?$@{)^SvT9-c^LhWG#%qq?uBMQhNQg*##Ez1J?%)B23;8=$V{Qq zVI#5Klnx<0Ky>XSyD8m*)_6y2yaY+J)6aw+68Boe@*l zR>P!_Z|)TutB5FV+E+ld&8Kg2;L%*I24d!=QA!!B?&~%MOHGR2rmVajeFrd4v>Zna z)&3cU{(7nJjX{Eay$;JA3x|XSDSP^A{j-CI$Xc60muc7;gweAfAxX~xx6~0x0H>Aq z*ZXmf6r8z=Band9D#1k}0kItz;aPZSQx_q0vBzblY1IJ1xC=z%+NCrs$Zt76@@U=4 z?=F5TALYR%{=}?#qxr}GtX@in`Y(Z8>d$jDxEI#*kAJTp8Hp3OhaB7mmig*q{_%J9 zRa*fdm^wIv4ZE z@1ELSriDM5w%rcD0b2cboN80Eb9qFf$SI~&<6&T1M)@Fstii;8MFc26irKn}?o#%) zS8+qX;22BaZhlpHF&}q2Oc;3{8RFwk67B|~s+F-Ary5TqLPyj@++>(4%DIG6{Cju4YP z$+`67c_XSq`*8vjckij+W-f&61PD$*2)XudnDN4KNm|fO6v+s`X`N@d z6j~ZpKW^Cm!3@r6tx~n~iXF*!;}oJU-E|~ts^@d+-$$yWMw=6%fA59nGdk*DDhC{0 z6}6E!Q!MV%v5pW==DDrXZ9g%ChaW~fNa^gs1N$Ur;o;O?=%AT-*n@|o3=cxQj|bHO z6cpXHsq)vfjqGi{7JH4&Sq3d@+q#DJu!alh^8{ZE&Ro`ehF#b1fZD-GBLo}6b+ zqAbL1P6{vd+V7y1Ydr~<-U3~h*Bk0q{x7+Vu=na>&*d|dcocgj`X6H~A!CLf7=msv z9t6Xw?h}!jNFqrLgCw1GgdvtBPt(0)f6ghmNhX)NShQvTA?c=TQny%(8xM`~*WT7KsTU6)h{nLqjxD%<)i z9y{Rr2EG|$2d5FliA8+UevdE%Pqm~^_-AnGsmk~NmD*lo^k;NTW3Zqhs|$1M&!@Sq|Cxu`d#Bs%Wps6z!*`!k-YdEME(M)oes=WB z@vh9x=x(Tdg^Ss;RB8D(7AN6+9h5$;G1 zm!5EU4&jEobH!zNI!~O+#`)c7JvPp@14fB)#pqJoU>8%t1+xGy1CS0boCP8btS8(s zaFMuX=u#O0xAv9H&(MO&S;Cm4+5>MN3F{*|)?j|XZ^>eWG)ht9)cl*YTQJm8$0ED= z_c%Zu1Wd;P>fkHFqruA}=0}6A;;I{RCQl% z6n(v2wL6xV&W^c0=?AcfMAw-d)4zWnQ9DoVwOA06*h&JoBotszRrE$z0&EGuNT_JS z<>%Us?QmVvBWa3L>aitX`+T`T9VMOc8U|(US^5;}5#Lau@Z}SsEIl4rUp(5oY}%H4 zrrAqrF4E>=>G($L?~#3TKbI~oyLv6H*sWrROTHtz!CMX4BfI-F?}I#4p*&vyrn=`l zdQG=%(EP0iOhn1)afv-sIbM^rgUi_-V$$t~Ae;UWnwl9QS9N1)zbbQTSE>wjUKj}s z*E91Nl0*lIQCNRVit9sl6EEw0i^zFp!tC2+A@*+Igx&(BJGist6vY13HYaDZR)f@Z$o4_MNCky z7H+?c`N7vkPU)H-wrZA)?d98mt69@Sc{#7`){jRL1@}fD#hWgkM{8@o?r|Eyy@9ux z)7KO@=S$4mM@b<)U2Jz#aKq(`}GKSk0T|1r}fT57%wlFx+S zK`dOvtH*EjlaDgrDD`c`8}<@kqRDtVd=x#5?d_E(88gbZF11d0hjDN3)>+Az&453* zbQdxUU&eGkMuDY&rNJTF4j21i?fn#Nx+oca7 z23L_C%4;xK$y1ADB-Oh_(Fg_2H=pO>gW85mPN=Q|zp-afyd1&~zC}frBeiB*+@+C2KUgWNu!f;1rD6OtlRB{|s-$zi^=olw z&2+BNuD=+6z_%X#ty`rO=+pi9~xOX=_&ee=bb&&OMtKiDb)1!~x+3^&=)357Ee38%4J7CoS0@I}9%> z)HW-dW)5!z$F%!lVdhvED0KuP-_MebnC#eb8^?)sP$4#A+QG$Ah8HLebm3hBKVIMz zVWqqvxKO~LT`KR@aP=lIM9pFH0<-%eJPn^6+$n$)h>Eq*lrrZUA)QDzKCS%aG5T*U zw5F&7Ul`|Urk8`a5nr~UD7B_!%ut(Zdz-l%fV;2ECIW747025WKU3~amys~7 z@YTGlI{@rpH~#YWK0^IBz@iyn796F06tv~ikkFIxh4Rb%0UEZd<3+|&9wOJrHMbC-?MgMJb z5N$;eh;BvDqrnJG%6=JqJV)At?}&JGY9nXsC5c`j--m3ms&-tTP6kjM?QHSq0|o8)d1$oJfiA7erySL6~}CwwCBeX zlEHI=vUt^^9_$@u&X23r&9`C3>kHLApX164>MPYf!8iC8)}OBKz3Bgw$Cc6GZ;{=O z6oYJykgJV#rQT3Q={0as- zB0Mnr$I4OR~E?C|gKGgx6ewrtnH zwNL#m(i}L_9p#+hrJ|B@D#qLzn1_okvQ{Q*w>ObqQ_?fJ3jPYI#_wJ7X9vH<9qu;n z-;4VP#{Ea!kBpu3NcaSP_BZ}XV4o(DTxBta@Mm!4-SEc%os1#)Kd>5Nd&+0gzYMtc zU9+bJDj0k$mxjkvtm^fK$G31ILR88&AH5f4vU^7>TB1u`!$)+Ayr@pab47OZ2vFj} z=7gVkXVWc4uJzIR(!;UI>2Q$f4Hx0(bG1t~cz$#*#{xb>+@+C@uJvHIG2Mna39Nc{ zEPTkHp;cW(-yyM7sc;Jyrs)30eJb)<^x2^<1xxRVW$boD(V;yc-=Ebyc6B(fyNn&J zD`itvC~jT<-H&%m%J&kq!*4L~V4xFTCa>^vo_u1fcSSd?wUNJT&6|kVcg=S-n1?B7 z?2_!oaKkHzYd5as38AZaZKAT-rms4JG@lQ?=_yL}DdcB5W~`WsUtiPb&!yZce-1s- z)lj*#JZHdDm$tVlOX_O}TJyI_^H3`8l4NwLmjc_hl}tvS@m+Ll5k%(s$GM&{&t|e0 zN#*KzeDN8vw~yzctqrTjv^K0H znjvzjBai^=rLvkC7SN9t^b`8gSuBjv1)}J+XYtKW!F_r^E{ldSu0RZKh0h-f?uq@l zlRaF4C@zD-GnkAudKKe7Gc5dl2{l_JF$SZ(oB{$v z@(jk3Sug|yhHwuC>$7{%5D*x`2N*2f?tx)gR30yYNBW>bg9Q+s<2aRQ&i0y}D!VL{ zwNAmCa@r^HO6WJM(y>V-5H(Rqi&-_dv5`s=V2V}(DxAqyRA;2#Qwa)<{iC!_Bd*(& zXZ-@In^wcxxC12?d}eZ8E^d<=%$FpLL)A8Rt5l+J&41*UoJQ^cRAV7TJ5oV0U7Baf zn+XtBfmp+mk_nz8)%$Fz8u^lFOsdA;LKH|aiFDfM_Tw<)>Ne`IQR)aJz}l`bPsH@K+t?&>#dND+mGc!a zz~OTV+B8DD*OJ5y3o2_{?mD(!EPOczW`N=Ih#_~wih@WS{rF0FJ)vwHn=W1sE$t=b z&e*6;Fz1*dN9)OCqwkm#Qxo+K6q)&yO8o;;dOrskowrQ2o*`+ZTc^uwC^c`2FEdoq zlea;jwN}H@a>->;Z`Np?p&^)b-HiGSfgx6%9|emTwW~0vT;)4|<`y$`Wr&&c z0xZMI*c2gN(Of&wJ0jkTHafPAZ0c-x_;TXuXp`hi%GQ~s;Q06&;?SCeUBJ}8+Y$9cr}w%79rn|Sk;+OQokQ|>cnk)*PwUuKNNCyH3e z=bB52!P&L21s2F{UbQb`#4rRvay=t^^DLDz%07uod|+Q!6&#g+G!4)T3-=b3%^m zU&%YGD-5$)i{PtH;Z1NO*H3p6Bh2&a%|r~*hrdh-4)Wqu5KzTq>56Yd~KF{QL7$@cTPtoAJfltMn(4` zQa*BXZ?FBi*62q4M2wD~o{tLC1{WGH1`WGz&IB!xg`op-ZCm zX4|S&);bpnL78W(E~+n?kTXkAlEAG@A5550B5fNN6}dX`mSkqJ#FZ~u&rF5mhv7@0 zNzOz`S1&M2A*{mo^wexpQI$FJJ8TkT5DRK}D-Z5mT)@RRFB4}bRme2A;#zBS#PMmA z50Gv6YmcM(tcJd(tNCuYo$y%yE7otujn3QFF$4Qu73;rkeFU9)S+|@L#gVI=Kw}|g z!I#_;8swZ_o2;)yI3}=n@=~YMjQm~46mQ04e8AMscblS zY)}H4G5SD0=d}Q4q}emID7=%}<1}B6h{D_CkpnyfczYKpCiD#89bKTy;!yQ=@I9eAV!+ z-!*NG%@<`K_+C7YOk3}v>TW}RrVTe6tlJyVceSD}!ZGc#S{9#q6iC1rrJ@(LMZJ&I zRZjOVsc%JfcAX+dON#oc-AR21VTl8kjaR`~Da$qj-CR!N^B~j%hQpQc)e6!L`@Mi{ z@Lmu`Ql&zweQ`fuEXBEv*GQy}Kmx|Y6}b&0$vcZ^=8!?DBM`j;r$=0fUfLhw#2!(B z7^0W;iYo>?6(s~~cqwy)?Xeu~64n!s}z>>bDU|$Fwp+AXO-1_v+Lkz=mFbQ--${uEp{G*Xnny# zChfGpP)#?pWV$wAuLDZyqK>&rO&2hpkX61B3f17;rqR!ryz3lW7vki+%}fu-Dj=MW zz$yD1zDvBpN+DZ+h-msj8oh0I&;;n$G-^*|$8>G7R9x)8A$&a%+gJ9>g*8gIai_{f zAm+n1Ou=)%u5Q6l&Kym>YCBu%ACi3ZPMJIAyn*cXV7kV_NJQtwzS)J(Ojxki_Xg;% z8YW~2B@)XR=Rn-57=i5!UO=J&1Gq|#N%)6hi zbxv%Te}CmC3v(&H!WT2wwW*G`%GX)So2(t43~%zM z`%Fu_)^-~v#>{?6F0+psD&s$MhX1TSe@6`G@)LH=t?xiqWxIWOzkZ%9`bkqsYb20> zQFo>4*5541ql^oV1KyDawR>R&V_1Jib7=+<`*6}_KESd#m>pu6!W9++PZJKc3UL%m=b%QAASg!e$Jbrp%Qo2M5bndUndy#UD-!{l2Ep%wl<4jc9S%|BEuTv6~J@*0mdtU=k)`OR{+=d1B@3t z+~Im=PC4x7&JGvp?F_~8njJ1e+!>1TWthsU?G?Ml@*3f^Po_%yu45y< z7lrnjdH4&h503ZF_aG4q{5{Gbky#e6Ts1HAPL&Trt?)9baFC?MH?F?9k#D~G=rt9# zKz+q7lNn`lsiB-v`_TS}XTj=Q;&Qg--jIKvN3IngdumBWa>-anofxN?(lc(ajOCJ4 z0=2j~^wblsxfjXI(3)9TGt;WGsSUOw_14KUEIODps2S#K%G&lhdd})qq}K?+_w5;* zEPGol*Sd{2OFOUy4bZJ$OnhEPl*YY;2Fw;z+{Rl3p$UT96f`h43&vXogE2Z^@DyPA z;rhEo;fvIdfAMi|{XmUbhoQZdIqHI~GgPc_=6fq=71vWcg2Q<-_tn0MRMZUb;Fxxq zOL80Jkq$;6K@nDhTY2Q8i%bSH@y7?KQhxnwaAz(>(TdEO396O(zJOuqG)F&r6I>2q zyBNG1wP(_m4cPeCI;Y1$r)d{%f@w?lKuejR&qf%*d!W;PVL$K8Ke>&!A;3~cAOXYD zO8EiOQsfu)BQrY{BMZbJPmw3f@5pq9EDOmxDXXd$14dK#5<2G0qGPIFcJoF}$($U0 zjwExm@HE(x@NB?9lEOV2x7}7H4z&9S4ByT}F6mDy5L3=> z;~kRWjz9v&eKI0pZB_J{nC}GUhKES}`+3mkF?a2DMEy{V@Lhz}e}Pt+t9}X6Pl=i@ zA2!}CG3wnOaXXRd5nnE^bn7-DA$*?T>ob` z1sqK+%Pp8ftvt+`3&xr?V8%$Kn&)OtN&4raVYUR>$QOY?jN{Jl>2 zV>(CIq}~98J5}E(ucmmI0Gh+e z`(EOZ_C35ft)#047!R+&YX_ecdAv#>YBx;4&ybdZfPHuI->10Lb%k&3_Uzym$UPRX zIT!dsvgLuU@&3YlM>if9CJuRHhkb~^qW}00c(M0T(`&vOvbDMOL*c)ErDWnRgp3XG z+C+Gx7tZCF0Kx~zTkB3-_Ts-Qp~{t904b0MfpB?;g?lrlF<@&7QmlTpk}-5crU~T4 z26Mu4)M8Y!%!EoR0-M7(nbs?X{+N;<^LN+cq@sjwBUbHJBLuE@k;IF>NQIeB_p!Ji zLVvB_{m#f`V>i=+TxI``a*UB9tJh6QPVLuc5a;z>*)5)yYg?p5v}{)7xE@hO=U2R< zY7=VQ6m@EeXmE>8wM4GCMX_2UOWh{S?4cZgQay6Q_lZoHdKDFN!uR8I66!!X#Om-S zob;VyNA~nV;E_JekMx0wtl9O!wf;n&j6O&_?mG~{h_)=}cNM?;_@NuScp)ZDy!`=K zvYR`JpeK4-cjKZ!1UTkDes2<0igMSR;!#-r1~i6aLlbVm`>t1>SSk3{P}Tw)dl6zV5u&A#STOO=z_#Fx^SCFB&iF(`Att3dIUrl zG`Uz8B&Vti$B@Z8RTl)?=zVnj6(FLjAEy)*dspBn?pqBru!7#SPZs@)N zx{be>NUi$?rzy{3@ImCBORSW>n@}|_-i2e@eUd1RKOpc@MKsIykpdG!}i;D-I) z)RRnn$$H7zgynN1{e3dIXQ0!I76er9Z8M))mt1QJl% z6)_tstlq?BOA=N#Yn@CwdM;%@{CAP2V}~D=MBS~JBolfGX803YxVe^H`w`a`&68jl zm2vAD;@mxZ9JAMw`6D0OrBd`VI~*Cg(IqS0n$J1&d`3QC|6^HOP4(_Hsg0P-`t>s> z>5C+nTz1(Dy{8w-t!8f{f8nHLwKg6L=?`FF%Y9o4Ork6O=fEq~tiF7vzaSYi?skWC%w^+~YL%Jq%B5~4{{7Jo#zeJLW{Mi9* z8=GnwZ6zsg6N=`u!AXk$KwgvkcC(O>*K>QJvAp)~m)DoU=#v+lSoGo*^ZDOsx@Kme zPTiQiiEMX@Z1a(9KhiJTYnOBxbDIL|$@ak>NMt)Gvb{uP%ba6U5`P8{*-GSuB!nks zQCQ@V?-VB(O$Hi9Wgj+%xpfbGCd%N}QkS)a%pU877Prw-5AaE>JkKm^YkGJf(&aSE-Rbb-TFJy_Nn12c)|*9sLy`PGN;a{f zKGrYB-#|8^;Wh=OC&mNz>wyf%t%rq1Q%KZ~7tziU(SCwd1BR}Z-0oxZ5<0g()T@ox zp93vKEeWWoGmTFYYs>Bt!7t3jUuH5L)W6h=W|ECB%$+6wp2@#lcx2X#&#~rhw3gkZ zZBbh9jH9zmmeZD?n?bufnZDXgru**pE61ni)*l6@e)j&cN#+)J1T0aw?${2F^D_jN zrjNSl$Q}CnXV=CI_kO)iG?lHMS1m_3D?Nk^68(rHng0~RD0Ku9FkUsEdMocpklHna zlx{!|7$5$#^vmTL=}UXies6#JDM|m+n!Z2+n)q4L-!g-gNuPn!KTH3S8Ig2hs{OwH z^wX05XEc3*1dLB-Nk6FcXT_w?&@4({PPJOrTcmtLhNCQ^EI82j#-|G2f~kqhG2Wu7 zeZ9qVr>d2e_NEYx2tP}Te&t~M|MB)F@R3zz-hcJIm0Ojnq`NCgS7qt$3f&}qsY(K! z&=3f_Y$6~aVj6@-HltvE4@m6!&Qn6&&~7aoiPLaTx`7McNI;eVI|m8J+h3 z{XOU2s$1!_6-hXRB}V%udNIDb$C&tLf#d zqR(2&;=*%5A>PqNd$bY9CQGrCnO4EBK!+hTj$H^oZxlZ5l-OQ}OuOn6oJoj-nJ#jW zxt+ufad#7{A#RW%j?Ee+3TATMs5F_8T5FK|A(pBttIOtyZ|dajp@|l6`KQWdTJ z7Ho8@{>P4b-nss~15>R5-*xb4Erf8ok?8qmU^e<_AdPKz(K;z1cTKy1U{P_CJ%KC6 zQU)sOjRd=*%=PCT%{v8zF5jYsNMUG7};MbU6?uukRnsayuzdWbS!uicia)#PN0 zY@X8tib{Ow@^sJJC*8j)9TS#Lcn|KA?riZ1%B-$CZddBqsdl;7u#>TBqS#*Ms-^f6 zy~Evq`Bu@X9JkFUMb+u#uTj#FN|OF)`mWCSS#+y)jbDz075$RRBh zQVm5pBP!=&5!u!#Og5{Wcc`58aXFvqEa%B>V8No|+U0z<9Tk@obJ7NtW1NJx8=t#W zIqy_C8{=|5+gZ+*tu3U3Ma8wtc}hDfE=LSSeX1(w%W5GsX=57Rzf^B#L+$;5NDU={ zlHNm7u2Ci?d@UJFMR)xxn|T)ay-WCw#`t}XWI?c~&(a4vf#ur36yt#10L13qc;f}v z4|e9sE00@nRg5jTQiTH)e6Om2vg|g3rK4msC}o*$y%z$w<($ktl5@6;Ip&^y zDlYt3u?Ntq*Lfkt2+AS4Aybbnm<3K_L($67-U;?hKgu<}Lc!Ms@m}nj%*0$~%Q=uw zIufYr&dXRvgGAfJPzHy8FG_w2C2sJeyuzMiiwmCwvEiG*Ocwtw1ZDBxmDEq?G)(xj zhwZyd23iP%o6}=9Wv0)~9P4n-%8obl-k4@>8^~qoqQbH{g4 zKZaLsJGjd{gYvuq`2@NkPF=U z?PqYtn;}?f6xuv%H%lc?QU$lW=a+4Ngl!cy;>7B_J>%#_RWjDc^X_qMmN^RkL{EO{ z>#z_vaNy0`bulhoeyL1Iq*V5z^*u0=69Um7VOPtmHk8~ri|_km9$T@KIw7Gu5}k~= zhsw08+pf!gWW?Z>wv1>{)_W*xSr2PNbG_fn@}h58=RdKyaPqdltMflua$&y`!1ez% znT?Z~6O;aRN~-QD=JfOeM&0{gSGm4s>-DzcLrF zKgX}eoo%|uYzm$KXEsgcx*85mGwoQLJI7M&xSSgi5ovCew{~(HtQVr|oBkyJJQ1uv zApUe>cx;&z4$;-?(Kn4%HWnB5P=ypECu3W~fa8Ho=D-8nGWKNPizhX1rrO5~QP}Iz zw+t{NXV+j4RBhJ*)vJA;e7*tZNJU)ZyuxbXQ7@Se@KQ+R7ClTH$IZgISC9fKB;abRUK2j-|!#;^1>XA1`Dk zRNuWelP_i`E{`*HBAIuPrZBKH2)uD`S@{T1457aelnSY;In8LYkL}Stq)Np&<+r!{ z<|}0uSeZ9F=oz5b!pbuhe4+ zN<9?F^UtNOn^_DePCG+hw1NM4S_3Vm97!pGjj*mkvlIOROlvj%9tFD4oF9E3&t!_t zFhx*&y5-z;$4r1S3%~EIWRU0!YItX$7|YVdR<~=0`z=%|MtrsHQ3kCS zF593`se4;+?Zw$>ovOMzRn=ar>hfbxu6n=}Fn9Hr7xhwR|C+uv;SZ?bje>l;UU7_R zVg26CT|Pp8X|u9Drdx1lBwA;SSQKgBB^tEf(H)x{Ug(=k%V%sVF*f-wWnafi=@|1T z9)k^;hU*SJq7mx9N~z+-`RA+9md5@7r0xqu{}TXssjTwE26R0w`*jN%=X8F9XHU^Z{1*3j zOW7mPIx@b|7%>q&7qrT|`*XZz>|HZQKZ$N6q`$jY(N607o3&+QUe!8nDm3t50n@jKOmCwBN8@jBJSIbUv0#=%1WTJP#Z zRF8~A0Qcv|a-meZG20RY*95dTZ<@Prf4P64erDf*tKYh1^;_3jzjdyDZ9e=aeML$=ZXFAQf1fXC)VT_E|dRH_{B7STdG=z znDqTR7Z5PE1-)K33ov71fPV*4_##~0wbGhe=J?auH>Bdo6uVF7i+ovDvOk4G0o?TH>wLgWkdY;)#7^+Sy{Q?I>g$s78$jN}q@+C_G@Ag5L;AAgE9P;d-7a|b@AfCKjJk-u? z_iVeMNN*cDxVHlrwly91YAEV-9=C%~2sR$Fk;iPzMgz&38RvH%ziEEK#;J1stbiSb znV>p4b!0HQi_od*`cdB1AiK&vkKnc%Li#pG#ob1O=Et}87f!AVMlK2FgX+ko^N5G<5&oD$ zy+1c{Np3!u4lHVmBJP_X-&5$G2)bQ|405BFzhM5t^XH+z<~3fXlsV}Hd?RSHR z{zi{FiVHKeXJA_hgBS18mi)pGsexT{K@0BE__XjBg=jxcH-TKP;hE`( z^-~4G2^~RGjlH0{OZFpJ#M@n)I`XV!oamoG$$Gw=?cU5aV{XW>@Mp%Bb%*L`5zU3! zl6#K#<}10_8YaLL)vOHMCeo;2DM?ivrP;Ru-)$dXr=QOWP-Z&1|W^ENR&`ANx%^x%b%jRS1#@=df;QH@)Z zSgb#dV(T0Ump|YZPc}LW#V&TKbyHd#Y(hV|Ax$zVtGDMepHf{|%|{ewn=Hg@`;E1A z22cH;91E5h($OJ!QxnS*-qgf=q##2HMtH?oV$ZY~>W}?HK~?~T@a%FL!0$61__>E(8dx9jqL&H73E+Q3-5ouZ>p3HKDd}Xng)gSU z*qXGk@3+D@pr|u_?qW|Bnq(K_Ppn5s%i+?XuDN4@Nt!%SOJD7z`C+2@Ek<+2xGFQP z!oJK+9IdJH?MuNNFn4Z{HH@XNb;3Jb@LoniW4jdN?BHpy)_xzeNWJaIdKD-7*dj%% z2x_v+(nf{ZW%-!{Npp9S=33Qkjnj@fpy?Fkwjr1Lq_pDCDZS}>gY(*}grAXNe8)Y; znAuZE!knBvNZvWDZrXNg_erZM1;r#oZ(i}Ip2*Osoql^9idA8|E$fwh0Wmc;`vG%p znJRQwA3e2Y_RV;?5xmt{vtP1+KeYp-00j$s+W~L0fb1~|AI!eW0t)Sb8!UhqVq#9I zUmq-#+rF!Uh4pRU#lga+w(p!^fzz)^z7vCmskZO1?&|3Dn(pe-Aq7TE_FfC)^-aOT zp{*1_x9+@LIFf+SgFhTCok4(+`PjGXynIaKz|N7@-r)Nd*Sd5Z;lpMul8Rl|LN;Q< z)T!NAud_c|*u~B!7qYJ5dSYbWhyya!I20z@C7DoL@ZEdwEvEO~qthk}xWCWK?1Da@ zr|q?7ejLcgdX?ED>q#Xy(18I;Cbx;fOvS+TIC@Kn#vAZzrNxD8q!xVp&j=Toj<-)5 zc1TI1|Dsra=XRM;d{Ax>49Ns`f@_MdF9m23k8qC;^7XhW@J>(j|%L{L)V ztknb!nMerPn7WLNg&E++88)_n{7)HpDO2ryvLgi-hC!9=5@yzg@M!+2`7ER=h!#St zCrGT@7YQ0JnF}m~Iog7dz&xN8@^`@8z4Uch%wZETE9cT?*iZ9o$6v-KmD=v5Z~Q&U zzO?ks&SVpVF`$1s6_u&+6Wa6{%nwE?HQs`gqikz8$H#OMJGR$WV;X5`u9IqqwL(C) zgP~7e`c@|bt{u7%q+gJ%HL4f-jP-HaT{BOOCmn-sA<0 zE_(r^ke%f4g31kCZ(W;iw+Z@KE7u)h5xQ0fuYagL8IP4G$F zlPUL9%6%ENNYd;|xerdIp_DkyE=hv8B)VoR=hjw=v8CyhdnV<6ObR*!VFFP?BZl~q z6hu^z7W5CL+;^nhC@`%wZ%MgPty|&mNxA$y> z0xEG!FePpYq{Mw($}ItugiG)wZV8;kEkTpGC1nz~giPX=j7i**C5c;7#JP7#7$>q~ z6MW243G<&-taveP!l1Or=Ww9d1q~dtmlpwj@|QZ~t^=U;tj==sJSf?hAB|ZLp_&wS$)!QcLXR!+v~er1Z^>P%J%qxnR~@Gs{Oyx-2j=iG{o-&^j_)=%I{v)wU-^$tRRSHMMM2BK>p z5Z_IM&<>gQ$=EKNem{0t>$UFFo7ob-h3sV>p5YS40#&keD$@S%N#T7gm=)`rxPIw4 zTs?swV;&ukH$nddxmSe`;WPPlce4`XVe8glx7O5~Iru0Y<8w5G#WMGbhEX34IyTue z&fS9RSVSHP>LXGAK4BayX$%mmmuuJYOd)oDsvOZt~&MuG4X`jLO348Mp{I zlh5Q&_6+I?Dg;N&teo=CyRPQ|FnTVdRjB?mli7H-<7H9%@Exw6dc*XI*CciJGl;y* z*H^;1jb=XGyuxhHKpTbJ1b3F7MZ@cStM%KFO#f87tV3qoWvM@{)aDDj;b+I;ON{@8 z8+Xt??zqj_`_yf%>Xy$Ov^9a7&7jU?zOh0byzlqe0#|Q^OW`i-wka-4PoJSQ?n(L* zpZqB|PN^)EjDoRmZz)$fL>EfbOSz2~PIQ%W{>yK z&2#@^&foe9|0cog=TK+`A;8Umes~Vm2p_>e+V)&N{av=E)E}@dRzIM`J%XkD3zchO zkGl3FN#Z8%C1A^(!FK7tx$pq7JPc*%UPhl=nJ0hwdq*3VCU=sk_9ZVm4~W+=2(Mxl zeBn<(aeD^QqX-|HEG<0iSnbpbuG{Km1PUdsIPN@85?%;c)Hg!MsB>YmdHfqcDV}Uf zd8^&F^b?qQZ}19yjqN1e^<(@?-{T+8nr~tKWS875mo}~uPA8;xT%M!=BCgeUngb9_ z?_H`k7T;IqXSR^~0bbAUrRVgTRtK7v;D`H9plcbj;X43rNjXOUL&4~3J|M`qcV^7m z0goi%k5UOcY|a)1;u@yutGEl*Jhp}7Eebt*!GXD%r9rf;nh4`G^0+j%zRlc2IE3em zz`R<;?$4r%)FlE|w1IPp>>4WKRRBlB7FBEZcVKEA8GtM;R*_TMH| zoIFh{MjbL4sYVty90v!Rr+q(JT&LQ9r7>X&EVSCEdZ1gojgnZkk)7+oP(bv&f%<$? z^mL@>J*rmSxb7i-+>k@!MsCN+DX^GP59OkZ)WCEF9VYKcXH^(-*sqwtnpsDJQrVo2 zf;Qsr$fp?}2?>&QH09umoU7HP9DDfT2Vj0UAr6hZ82NQR=rX?FqJEk`rr?B6H|{b1 zN-|of4lKwomm}Ce;B0aXHD_jUldA(qr=%?NxehyiMdEl&C8{GeHYvtucSKKe0oq6h~LclDQ+)(E2Xlx^p7I< zg=mHL0F-o7{TVq(iOu_n93f8aF zuwK0)EY<6Kf_0n0@|(X&!TPP`f4i&KYgWv!dVOE{UmN4{yHx&vlRK{0zo%inZoja8 zAXvA@uzsI{^@kL!Kc->b(Fu!NEYyVVRw9iB?$C0wX8&?Rc4_FY9m#r);^P6GHEuPj zx2VR9-{ZMh{q@D(qT0$^R4cg%Z&9rjCwhz$z1&+=Be3)-`X{MG|2WkpN(D=byxyV+ z>kmZgnUNL3*d)Sviy~PZ<1LD2Nir+uHg8chp%{^)l}_|X(pf>9yh`IzmAJ_(I|olC zHqoH;yx--Dpg?&|rP08vzzJ69T7jl<*QU!ieG;W-*A>chn76P4k<0!7dLH-rCmPdZ ziS&3v+mbdPC*PulEy_(qc%{O!O|&zqR%P$zD|v5Lo@2bO#uJn%8$MC~^E}ToIRJ!S zrBHZGa!S0q8va~qDW652+I*xY=_yF z)9SA2x3YTS56$0F9lXTz2l=kO!>2%)h8#X0jM>cKtVo4nwbi6Q72Y&WPyFUXadm+L8LE_ikKao>F9 z^tT4cD|@^_blwNZtC>BEU8_K8!weUpf#BfGM#FfrVilO==>5j|@ZIp}=sAx#etN37 zaFYhyCqosgSnZh)-$k6OO%DNU=kw)ZD>xrMj^g_=`S87@XfBAf)q(lmp-b7UvTTdYNW%Uo70l%3DAv%oUn%Sy?m{axhga(NhEERVj}6vuhwi}Q5N_qJ1`d0T3I z+o|PSDK+Z2rPjBdTE3N1GqPK1ecP$!TPZbzprzKgom#$*)G=icO9fTmpQmLH84-~b z)FzUAmT}LT{$SyKG)pOHTu0z_1I2KWZ!s4{*Yn*oIbQD1HJGy$#ws$iC^S$$+R?!{ zbHzQGQf|WAJG>{8tH}mVe|dg)F(bk##BAZtfmalccr#r)4<7~i@me_3XG@2u%uEvg zQNqP<|Bm~|@Ed%#{_okq5 z{8t>hv9;07K0;YPQCa0^7vzgO-OX1Ps{^@t zqfSr0y#CgFW$@PgNcF&5^Bb$@+?ua;S0BOuLiKq57pq%u%?(`=z6bcd`D#yh`4&QZ zyDR#v?jF={~Cvtx+>ep`nztq6|37r9;gl|Tn#ct z;$W=I)E~XMP$m;j$p<;eooD*I_)MbMd3TQKpz(O(uk#k4MX+yjSuc-B`z^$2W|A}v z%FiJMt%4z5Aau zQiL~>a8J*;z2Duq2@lssIKIeb)|4~;r;IOf4`uwP;ARcug;tJNJ1rhymo)e`RV~it z+nDQ@+h|SXeH(Y#?P{lUI_L2YrR4n=IIAv3Snn7qdI=ESkZmM$)h|acC74lIVZ0+` zL&YWUhv?>JbJmsFL|uNW@-4!eHvtzbO({VttLl)XGug=)Odqy3sgDZ}XGAk6E2 zGRJa!Sjc0%|5XI(BJhz?)vmth+8lIl7;YS+Xn7|0nC0 zOjn?bu&-=i)%zmA#{ zpTJ$SrVV#ZpM(3i4y-KaR600XuOv%GFXvLJYMDPU8gKeKNySXI@a@>j8D3g zyUWbSjStd*4mM*1!SoiD%i8JSgJ3Z8iBE7V-Xx10PIGUnV2pRxH4P!H>KcA!^Vk09 z08EZ}PZmyA7h6p=Q{~3LkQwBKTU?UF(^On5=28PzhuVvm7`Y1*fqiOEm#6Uo{tbj5 zgzd&%FlZplKSXeCr~CS>8GRT(gSh5IA5qi|`$SnU@U6x!$<1CiC8g=Zs(v}^x?I)? z=wV0rDQ_b1Zk7zKFteJV79Ueu^VeXwkgfN+#|!F{eVzNN+&WkD&^0RaA(MhSUU{~= zP1pEN9Vh>dp9aD^feQi90<&!G-i2=+hF8%iaCp%tRcN{KDLzDg+9HS2kuFD)!esji z02Uu`(C(@=oRf$?L$>J8tGPwEQmBu((4ZaapEU)OxcQCch(1e(>2JzrO7~bi5qR2r z!S2{!;=-Ej*|ltRJFjl0_67a3maz5CPI-Gy%7znJZ0u@C)TMF4%-nYj2e;i5(YPDn zW4ja+p*_{l-qRmL?c9-|PuYIWK<3O#+@8c|cmz$5xA@-DmQKKr5a7=lV8ukJh;>${ z+#K&X5t_dkv5-0c68jZt#LiXz&s%=QL?2Urzwre^2Evcy8TZeEww}6r=4TocqNDOg zfcgM88h(*<(R~ES6vsWF8T~6^(?4=J_;y#I^7&?O99yZjU~I{ixAypUy3IxT3DA20 z>Vnc>@A1tB*+taSbUCQAUXN70zGU@MOmt_OE{RT)rc13e|9Q&)Wy`Oa=q{s+*BAw@ zf$$SCVbTcHI{`dO0PZmWiisF7)G(iSW$O5WT4SO!)4Vd>Ync?IcYW(f0DniB6~yW6 z1lu_V=eXk`~ zywcx`wiKPGMx@`(^Hpbe?dNQ@es1k|A1BF@_ItEaU*JU-^3`$4Q)sqpQ3-pNw`V?D zRiq(L=^;H0eK@*f+|Y5%KJ9!RV5Z;Yn-zB4&e}`RxcCe4-{iWD_FN%i(mhb`bW!oA z_;iNvFO5$xa~-ul3~pb6raUnf4np9Gu5AA77Po$tnCbho181A@Fty8YM|L@-mMGNBw!erHoz< zR=)j@&yrGRwA%vpUynN14N~+<3)KHq$~Re{{)c7$DP_g_>`|2QE74-{13BHN8@-M9 zgeTVcIwUR;*_BN zO;v3gV;BHAX1zJfn)#RuxHy{AJI0CkihFms04jMt{4)Z#xwboka(-jwh`%Pib)-l* zY$)ci6hC>nMC2IH>{;h{po3S+`{$Ka8P&^p%Iroa)-6x`W+tXgwP>?_(^i%N{#$7W z|3=yrUk@!yW^*j=#EZTKdG)~fxA`&wJ6;noo5?HkJDrg?wIdDh6#U^8;a|jQU>T*a z*q=IRxqij`&~RD*9QixbZPf)$ZNW_efde5q0JMf!ykc$C2*el+LxkH&kO5S|OIJ zr?U|5}rZs8{zq0?U zPLR8z|M2yxpew1aIkEVjH7>^1A5!?0jUVy9II8RE-9k#eJC`r>s5`-4zMQ}L%IL>9 z#|o1_%|$=K)iDrGb`B}qkqC_km3)_CqR+T-h&Jo8`cpKaBHo1Q2bdzI^@H=3{il{) zG0|t0-EaJikb&@SJc)j=4LHBII=mKvuQ6eS9{Y3Baf1F$JoG-vk(9gmCVlo7L`{F! zEoYEd?IC&f2ZQk{U}%i=qFZBV>w)%5gBH$$lkZOIwVv&cekE}C4Y1%bxV>6DEXR`f z_KG{q`VKFeVf=B%VHM}GQ&V2_CFG19Fry^7Iq+#;_lPRz)-0zh%!Wk6lSL%mIgVUC zvdiu%U$gzBKEev|uZORGiC^C&Ed5Qw)9K_6s>e@t1=W)@I+S&~_feqFW|Y_X88}`C z&$zwB|1er5;~Z}%yMc};Gs0t`QA#JXQSN)bjdG%OHpBX%{UKp#dpEks6~b$&E%+UF%%b#m}4%>^}jU=U~@iw#RFz)wNA7 z%+BVQeglS$9Fu{9H<{zOA}*SmRc7v?<%SXL_&g4&$&Uze!M4$qWB;SFJ-9vBSfwl! zSaJo5PiHCbKdml*Wjqw0q8My&`GehDJCG&Mq7Yz!Pc~3u=-Ne@_7?6?wSEh7^1NLh zB#btxbk7lV%KVq$4^@U5zatTrji*v?-e3$c9dmYU@qN7P5wmt|tY&Kz)8zfL;U-x! zywj$^(Z30Z*T^!WNB@p{^n^#8cEa9O#XWg1h<;DNcL5jAJNh&0LX%_0C)Wax=?H64 zr`P#3=ffilL*ZS6qU2hh}rG>Mf1A~F9~{-HQ!wm2Ka&U|t9&y*~vmE!Dgarz^aU#$uOt*nr)g}^v&?M|wv zoWf5%bUVMx_(lA#qJu@k)L z+ZIZ_E{&bkc0P83?HRGNyEuD7>?{;#568*tx^SlDUR|6Wi=EVJICc&cXV=8eQgJpL zJBN$2{|Tjq3KT?Mm~*r^%NS?Q&Ba;N8*`2qXPG;ib4ziSWdL)A#aR|d%vmeWzAbi6 z6lY%-JL|<+7K<}}1_m6IGPQR0hB%sPKP7fj!6zu?{(0b$aZ0FiLhOWshsRFP zo>2ZFO4^_%RP(LWgtNVEI2@NZ?~I*L z{q-xP!~`&b`JC8E<6XBx%B$jNXmde3(^*Qnf7%=or=*!!!?2QQyph;Ri>+1ugf@dy z-T5J!!H?sqCF&(FzEfX|*SL~!zS-ui*C@esARWPJZv__i=ve zi(lsVO@80w_aMLD@SA0b%8c>@l^@4W8sIyzld34!C_m8tRP2OhQOqrrKKYK=2?g)K z33+afL+F#Y#7?;5xv_JgSYH~&T`JbE)pxj9ze?YcV*LtzM~n4~^xa&npQrD5v3{n$ zTZ;9Q^$m;lWAv>R>xbz(QLIntTQAnf^*y9m->C02mviYmQ>?Gn_t0WJ(03bK$c+z6 z2UxlRO$l*s^861$CiCB5Ro3y%_Y*zIx#+fVKaOOJ{E+;a9sG9lQ!hG*PBqW(dHf_D z7#TCi!8;MZ+1CIwhQ|1U>jS_o=0<_DYHG;7-c+xBN2YpbpG5MYd@+lE{01-9Axa^# zJZpApon^^$Q zbrO}GV+fD)&ixYS?43!f!nScsou7LkNzy$hv2US;xo;@-i<8u==f0FgmFDhEoC9-r zDb*8_RGYUw)N&7R8?kR?PHg3Z=3c9$$0tcg=3bUWjn2I=ac-V_zEX`Oslsg=Ecf`- z)9kxt>RS7TQ;pd_(pu)JO+DVe^{FS?cVg<|*>4k>ZkAw(<{9QU!f!pl4g5Cpt9I*O zLH~;S*Q0;E`nOvD*680_{VVBTpZ@jh-+=zDYqfV}S)*lR7RgU_+gO<3vLE*FV)h7P z_85gdSc2)OLY#GISxMeD$62eUrmXhf)TUW!D&`5M4zTZV41Z*5-7Kr{9dHxU#PFBb zWFW3dg_^L~-^#k5PjEeD$)DQ{a|UF%cQ6=h3Nbap}wZ z{O}2%Ou9sV+rzD3Z`%R6BVL{WBmNSxjrt5%s=>;)Z$*||#+XE67O#F?L)S1MW2 z7`WAO_wSxNF$pTn9i2E=&mF1MFG>6ZafdF=u`1#K49txxiN-<$SeYv(&f&Q=ih5+? zuWfsRCD|O8IWort-{l&eV?EG0H_w^ESxs_niOU?H`+AaO%iNc7&i*CwhjX7woV7W2 z95S;%Nc@MyW!2~2l>|+g2r^6#nR|^=zc-1RiOZUvyRj8C_gp2Bl5ANHom#T*wyDMX zQkvhA{`3F4XbGwsSE?FVs$$lvWLOm;mRjq`WWCU9YNMhmL~+(X zGg7FQ<814RBYu#qLx312-AJ|j*0J@~!mVQ)tE+Dv!)}L2>~;qDU#yn+-%}+^wU?sC zs;jG`{9jYu%>T93asHR8Tln8s4f)?+t?_@LI>G;S)jH+B4%91!!MJ#bT53g7j5_2Mfavxr)d#s60cW^!tfx*HrDJQeH?Vtvqyjw7Hi!&2^K%KT`bIVDmrtnB}3&sYI)Dj1`A&$F8T{0XJ^lnz5dN*{%resmo}&y@I_&l_JEyB zd%k*#8?1L}i?_B3i=p$osH7Y_634}fV>WRdkvJZkI3AZcb|#L;%W-mc@f-kGH%F^` z87MIi!C(TFn4++QFb4r!lK^vE)O*hM5#W~E2)cM#km#XR7GGtAmx~_3!e6O-%}yS&Xxa6UWdD){?rqxa z3{sodm>&t{oE6{0YGhe;wNnFbC)2jFQ#en5l~V1=b_6$Cpc;piObJb>Oz-7F1YhhE&E==Gf^1 zk}VVGi{3_2wdql4Gg@hU1mswQ?#f(^Uw_`>Hejf&^`#LwjUDePa0XHy?|Q{}OROQd z-Gx~kdxM(*+weeoY?or9FTe*im$uUI6&}N4If?y-FFH1{LO@)ASw3~8MFOb@VCgZ$^LQAyI$$ySc*3ghsPlFje=z$W?~SE zj6uj5gE&;N81QHfQ~jdLcvtAtIUU;92vIL=kWzalYgxk2QAVWj*zh5bfBHf8=>5i4 zLdUYvCO+YkfV)0?nzaJ$z~*2#9O`z&bt-Lh%a;vnWXMJbkauXNxNwAG4q!d_Iu1y@ znLyhI;GGa=({`Zr9V+Bm^62Q4pqPzPCUEg#cThkW=?{gl_m65pJOQ zFh#}G5x;h29tE8P>kEpTJT{eY683rv`3f6t>$4cJPqT4*uDsDq)%1Oa4IIjt8wgq5 z(7+*I8y_`EN1?J~)SeB>9plpJBp&s5v09b4G@ZXGIe_1&LBy_ z+f!$7)9VlpZ7;kXFcX8F_`SMa%=N0g8^Z=dCVXlbqldM*Cb!+96;kQrWQr}w-TeX_ zS5T0NqlUU-q5W{=gnKwr7aMXlK!&ILq93D+_2#+zvO9VOiD&;z+jh5JnmpQN(A_9{ zYqGfT-!0hOE3iB2fz)~l;0R4ZOThwyG~S5hQh|k$6BFMSeD#*^s97z11)L??-RMCho!g( zzi~A}ym^+=F6w`_iCtuti+Y_mdJy=C?C`^UZG7|W+-m{e@uQy*h&=}va4G9h6I(fS z%SA$USV=>di^(-H5y{dam8@xs0`<|p_v`tx;(`7Y+fLbu9wOvue$m3-uCPABIXecyM`41cK+?@9(N*c@36OsxokG7 zFx%k9ap&_IA7O_(dK)Qe3)!V+I6<*yd#3vwywYnPN=TJ{$0mW8H4VlYD(-uoUzrMgwvRBiYupKKYF^{3`Z%2e)~JNZ}1fY8*9}yna{*`uzHz)0KZ3_HSg;Z@0akBN7(aGU0?;9JC5^Z&w{q!O=9V`K*uu>(8WbmA`IT`K-vd%h&E+$?`l2oUQyP3wdu*?13Ld)`3WcOwkfCM!UEs zQvauaNZHO-sn6gXnbhM5)nhrFLBRfh zlCC@YP8@V!66AHKTOLb;!m&FsA#wcY*?kv3H`>X9RqcNS2%8;pKDyt!W( znHc5_FxMH(+hdp;fw{rK+`MulZ4`iSb3}0wD}C{2EP$Lpyhq(py6CaME(05xvNaYd z7$TW;=w-P@(jjZ9bCLD?yqC*{_mVp;b3jzE9tJFQE$SZgLjACW5%STAYNSp1>nB0S z_Dm<%y_kDkpa)08*vGHSHxyO?_MJ_@BtdVfMVBgY3di8&aF+%I!5i#qidAByMha^7qN@ zGG<-IY${_{^HIvfyiB0|Xf0s4*?yRVi{Wpy9^!?+(#Pm`2>1;`KbLs%(`F>dMaH~i zfOBxZsgIjGu_Sdr^^L9;Jjs;}E9MR2)V@nd8l}}Zvb-EGnDhthJU)AzX!0GAnzUWq zX2#m}J~;Ja_};ZTTOKQ(n>)7_aNoh|Y;=uqxh+QiQ=kgss`aAWZMe~gmF}XIBU|}D zo60YDD*v06|I9eQAFaXb5I)EE7-_x@?&c3qvs$=1Pf`!|%@f+H`Tgi)WaR|%tEe(# zVX(LxhY{I@!8%5RIld!*BQM%fHk&(4>xd3Uuy`wwvX$-UyEfxskm!CSa4^m;dDYSI z0dSKAVB@7YFkmxoh~9~Z5&z%$5Og1(=#4Ju_X^@raXHTE*Dz}Q8LXp+zm)DP2q)Y> zkb7Qkm6^@Fnljn4px$ES#Tj^i0%1_yY;YKM6dc^d{-Zb6(^Pc6$ol;iHl5O3XcPdO zS-m%V4Abd7?n@Ac4ngK8+2}UB6TGL!+(h`+xj+D?rY1@(+)G?iWA%AAo*ePF+m66h z!OrQIIy!sy#^FZc8vax{+ZZ>hNCR+HzYM8VFhPCfiB6-YLG)JWVEpRV%a~us@vg6b zl*SgV`&e;Qu6AhnL2`OrAt@t{@C>b=Q(eij7x5hhj$2Qpfn0f7Q1q(fM!aIBr~WwC zaIOt{U8fwMJhM>+FBT!KG|f|@d@4X%cT{c%L>J?Zdici~bjGe<8og}oEK-3sQM)R) zbL)$P+FN2oq^YxB#zKaU4H_*Jq-hqnub-^NZ)^X@P!HzEN&6p~wEu8t`?FiD_E)sE zKXOT2)%d0%<+xzD#RUvK+0Hh+hYlV7s@-Y=)HncKlD0h7OQLYIfz67eS0u<)`U0$_2 z{E=KiUtsM!xrV86w%coLV8~>~d@bR!_8ArUnNdYHZXv^%$ASL>yl}O8Mf5_!$kk6x zr5>L-!Hann*{YZ*31Y1QLEwPW}n1jYS(8$>CvS{Hkd#2Xz1Lfeaut#geW;I*e%4Z3$rB1Jri z6NG;P#AIFabyV8R3_)AzZGk3_x5_DSA*5gCTe$NAI{E21Eu@TByrv3B1uOi%_{ z;@UlCYPG4Rrp%Tf;xAcHsb|^+K8?KvGNGw}kCeTxU~x*4ftO zx_9%IO1DQX!o8$y%f=r&A~>NpqRW5RNC|V}u#{ZY_t+nYXR zcwFBc2DiF!6TujQ3Utb?e0UNlVwTLE22NLa8|fyLZZPhG)~az` zcZ2#Qb=CDaTw(8dT}F29%9CBD)BU7qWlhoQ^}9{e;<}i2RF_3rI2XIt=bY$6h&xBO zDNx<9deAUT{`F;Y&8-lSTXu5Wo6};4n2(OX*(1S33dkTVx zF|Fum66dJ$jM_E7Ze8P09B}sHHolLGUJjM;9EK-)CGK>t=x{>Ek*m?nMzyY(mHUGnH`t1CdfL~o3$gVlU0^-nOIM7 zR4X4H3p&v`L@qnOB`x8u0gAD@j`E#eRt`_HrR&;FIq*AnRHU6z+Df~h4lv{vtwV8V zsFVnF3VnE=OkHxIaSmuCI`OJhpLH}~DB|pnu5wSbid8c+_@rCU7SeK#8^BuTXb1=~cj|m~Z2ALjr?AxEuJo^2unRb2nHn zm9R7v7M!Lsu(ErU-^rWdsf{LgHqT7#qigqe7Z9M!bvcE`+GcFSSlQ0gZHMP`S261D z)X85)O~WCZISd@OrP@J5uw#uvV9X)Sd2KFV*-ll}^0zw;m&W|L1_O;%T9>f4td6uB z$a7jx*h`-1Wk$?)XPzvXCO4957p!W0uW=IzO~$PQ=3$1{T7q1oNt~CVD#cQ6SLRuK z58qFkNya=5<2AJ2m^Ka1NE{u#QA$~FM2%GI#IZP z9kg=RcP|AW3|5h8QcmM>)v*R!vAK|U(l|bVlJB@Zo8kyp(|lBgqMws>J$JX*?93R|@ZJI5bA~r( zzS83mMcX)ZEMTy8icX@wQpkKe`5F$An)69ML-U+E>pY?;vSY`1`G8ghYR(?HWupBI@idH9=zB3Q0O21 z8_j8CV*lt-5T6y9HMz+4GkCIH`x#QuBv;M_BzDh9e-g!QJl@dRpQKVU9xK|$<7zw( zXT4$TTm4s`hw7GaAm(g1Par;Y;IAFc4Ee;-rC)Th0 zXd@6~u|e;TC8k&HPm6^^F)mB{_Z1Tx!Ln0Ka9?RZxg;nQ**Kj-!*80P09VP+llUHQ zIHzSrT5m1}xyGR_VKI;r7HI)-hUyl>oacLjV7jK`NT_Rz4)Jso;;Mg2xTWQyKYZ->^^c(-izdg8MSp8*C|=z1^dP4DjZszLlv% z>zAdARy!@;MKP1SBi}d=M4R%(fqwKTLh8pPIaItf<;CkLiX2@ohkS8hoTJALx5<*I zjgrfV9L)oo$(jgTdv2@}J6vPaLod=68=DC5X-5i-3!EW=XB&Hd_#LHiW2W@olWAY} z&^B`}eml^)Wn?egY8XPFYqOS5K$Z!5O?+wC`6QYCngi(g@Csm@A|7!vMTncM?^rr2 zH!dI}S+TMSMxraEYXGhYfTitpowC178MOApsxA0A_3bz zF`)Bl%sgJL2yX3ty@}So-rjy)nwp&~Yua)k(3)2Zx60mr-Lc%UoA(7LKXaKT@J8<1JAWDxedRd-9#WB9RE5|<9V*q09*yXgaecQp78<(Gf%> z?!%p16V>R;ly0-2ASL^PmgoztZ^fFj=da&rvWuNBo56S-qu2(O9Ew5I3*fv}aiZ*& zV|tn2gwsmWZA&g48gmf77AALf@Xfvlvme$Wv#FWDR&Qh4i`4`#)_X1}nD@g&fo-JC zI?_IXu8<992u*0Cy*TMtWSmT3x7urC++G{w_QGUoACRAS^D69+GN%EjHHVOT5UMu*#0*qrb9G5=7tOzuhRSp(`7`vW0h7 z<{I)m%*s2Q(3Id$)}T&RZ($U;1nz1tyDeI9bSZ(zt;_g0*0DX+VDWMSY(LetM0ADF zSiFKz5PvM6#v$}_N4qYw3FEX=B4Y&FWX$@`vF>r?L&hjNU##@j&uGb*jZU<5dExir zwtfy7j6125;Rfuf* zXLt$W$$GS#3!k~a^yoOcWUr;;i~__D3_{}oBD6NmoHKuiRx15m$mAv#6)fmK*pdfY zD}1=hsMh=x;~J-)=?F3IK1HwEWAwnU&X;WrQjD8&#(9Hy*VNW^bI~7>v0eG-@le89 zPdFxjGgt6BssGTpMVySN)(~6I0nNq}$PpfetEm(=&$t0R&k~-#YrLTGL=qLDTh1Mt z@9Fa^dJ?o)DTtS75DIHO6v1T zY1v6!??|57ci8%-B)tfzcM^^SFSTjBN@Rv7aCJoClVz+pZW8&&%GuZJ8$F3&x;Sfo z-$f`#PnNgM8*Z)UIIwZ_(cEM#;SF1XNqD0xBYU^AjW00@;xRt9Do&C<%a1@D- zS@mE*>sz^auHqJOI8fi7DcrYw0Y{mW1)Om(NYU~fqs@sOvZTsAhSSU1p7l_+}oDHrR(f$U1 z%o~12Ygy;*Cx2?SlS>#i589AaE3oO0c3QY{vGEFwZM8$XF7K8_8?VNiDnd7R5_f0r zs_7rI>#6;KpHkkVC@=1x+JUVbA1~A7#KIY2UzE2rF=`zmTUm06dWyo^QHk*?& z1j5S5W~7IoZ@f}ZuZcVEZ+AErM8$YT>2qgMrs*s7ltQRFO81q$*#&}^Ubn33(rH_` z95Ws(WP`@fk(0$NmhxN>0_%#VI+ylntM7S)CCIK$*Y_MEATaN>>84-pdT34-L~BSC z>m*sb3Fktq6J{$?vW*`{tV6eVOjRGA&oCV$VL>lpu2oYpFM3l0^_t_UU}{~=Wix|x zJx=U^OmDr<+>bPOTuYmy7E;vdP-?rwH`498U0>fqoo!FTk9TsSQ;B4YCDxyL3Furv zbJ9+FxXYvU`-|E%X0r1(dR1V3i>EWTaEL(NjOPgSX?z+=lV96C9O%%}M)V1SYK=P~ zS~2Hhn0!gKY{?L{r}19gsjY{|EJQum>k1;9&ZSX{_rDj9h{de6jMFTu1ve{U!QX2t zUiHXko<esiY)r>u~fa6(>O&1FfH%=TMSAc!Hj{Ojp2c*L)+H}}> zp8ORyR4XkdR$QeGRg@y;$%|x(u1{p9b{4--+Z&6$QA#Z({UWBaG3p9ZKbG3-sDt%e z-`=ixjL~kMz!c`btq!2oG%1#&vqgv+E3k_~-Ni>s#E!FF@^rqz;x7J&7YOVG;6xh5YV316xd&4Jg6h{41{~Acs@C*o3HGs%rIl$-V;7U z1#sWyGx;))$=VW}AN`{sB|7RuVv0MKsrI0wK9~5Ej;a)Gv0rB9;-<_5hlH zxqh!RD=#MfrADU}(g$|AcrDiGp9O}}=;_c-qtAtpp$w;HpwRy`E-l(bS?L}9l-Z;$|%cB zof%i|g;Ja?)qKI$jJald`oUP9`nKPHh0)NBb?T>Pu3YVDn_3ith7r)K1P#p)9Px5G z`el}C#<$tbm6ZKh!SWa10vO{46cGfK3~ho)Q)aD;y_YV3ogb~zD3Nof{=I>pvl(=> zo7Btl@LD6;^Zxbk1gd}iyZ9g7O0uNR7gFxyRIcme$Hg31?d|O2{{YqK)Ks?v88!|ZF1~UpHGH(v*v3Y;0~{#%v2e1Z@Yn1PIjLR9=3+Da!NS)1*A1O z5Eyax1$H9|#-lf>a!Cg|v9klMrUN~X_*4f{ii8&JK6GUZTg`(uuh56YFIv~Q(%OH8 z^nqQ#oAjZZz-?I{dIDwa+lLOMEcF4617`w%r{Gst@5A$x$;5a#X8oAWbFocRV;9Oz zbTh?vGW*>yo^XFWupbX>fAN)C7euYoI!ZBTLuSqmnboPOZr;KPBVuZ~j=?i$`btl} z@j^=Im91P~cP@G(38NPgl8h%i^H)tj=yx|?O&MzEu1te+pFp`4%b6a|7M{UM-ogiU z>g=%^&z?#Jin)r+L<`MV03f%h{|gV2A~gy|*OQpOv_#pBKcen8{*!;vi&gWSA(IVS zm&NBxNL&kK9&U!NA0mz0gWT89)s`Q$8WS75<_7xn1O457Ij1ib zOT|%gZ=M=(j`68DWXsfQuAeRC!Y6}ge>cx?lSS(`EFQg#axrV=w5h9Csk`wE=_cLL zN&2vfa)y2L(L?$67fJ<{u_bS}JT$*Zm(G<6x|=?+bJZQLFp+e}3rKmD>T6A!T)O90 zPBu>!%rs?uYD2xAHcp90-KYy@EY{1g8qyUSFMzx5o-vg*Hiflve4EEcM%VE~Giqs= zW>yui+$1f2g%lX3QR}f-)Z!VNPxop;Exe0uZ5bk&@L)fgxas?xadZ#ECEQw&QK{BH zUPIlUWOcI*h=(Pz>yQrFb<>>)ab%aGO+Ueo+(Z_l>j%+=>2{Wd47qKK`>h<_Qh(F<^@Sd^RbY4AEw)2Tp~|9i-=~oJ97Y9@Ed+(N?F^RBY@9uclJ481Q)ZJ+xTg z<5jnrgVRgZ>FSKFaHI9fbExw`TeGQyw)VwD%JyMn=`DbHJHVjD%Ut7CloIaIiom4g zAP;Y1^R#p83mpwF0pF{QhS!RQ;r04&@Fb-t$f5CJKyr2lT_w6z(4Iyj4x(qfi}m5$ zBBnOk?(nIEVFVoUI1}g75l+dP$!$2NKPCCA`v`8Mylbqy?}3tT&i10$kfKn(iuuuN zaWMq12F666gXJ6KiEO23&tox$BS!68;hXF5O;7nzp(8f!I|PkhnE8eoutq5Db(A*w ze6*#^-ZD0?v9?sMsV_Kvsgzl~G0~T@vi;6n3+{~pAdUHpx0AmyjJt`QZ8i?@7w;f= z-i2dxnl(P2_7`8T)Mh3tX6DrOKM_zqtdfx1{LvH?Z(`8Jaq2e^Z;Dd+u!nQpy5()W zk%%TXR#{Z4Ehsk@BU_~0e0UwrfUQkWu&4xFK~Gw1^Av!?zu+&vxefdrfVaGjw+J|! zz*z(ddbo=b@b39=5#XA>PV@$gN`e%9E6Gi)q+lF=x7H%EnTONX*orgO&ZOqXiP4j^ zFSqhs%r$snNfX8``izooCZ5oWR6W|7YxOi+2g+%!H1kx0eP|lC7P8Y;cBp%rgfa%p z7^u2>=A4cRtUVk%bvSzt7b5Yma?{$K!Q!Lk+rItE=$9bbpS6hvmni6F1)E&-%)T8Y z2YTF&^1^vXG0Of%n`TE){=}?X?CNLc`djj+|ChQ(cac*j0Hv<#(|3HO@iqu}BPJiK zdg_nPIY@tPLFx~pe*;3}?MlR5e+Skp(*P2Vz%F=Zah!*^4sq~1G89?QTi@gD0+t&$?4`lNfpWtR{nNl;9%=(RDh<*yvv%!);gAy z8f-N9jF-A5MpIciXW)DcFzQy(@f4S6QNi?`+BXj0NwMM6LBM>PKsulFs!?dL|9NM& zHPh5s#2RRZgS4fA!a#ALXQ0@GjUCh(c$Y50Zw5bV%Q8jG2zr$$goc#NcjTRzOev>FEUV zB3HVo`bC`y(%|Y`E!2j-LgsXIu|AOY_QV)tLvgeiGv8zid8j@?^DsW9 zn`ASO0QaZ2Z2T9`OnCCJ4xV(!DHMr#+!XVJyzvMdf6VmFG1l~V+*mjYd^cZu2BeIM z&M0_rJPI=4Ywgx#+b+^Bw)@A!6I>2Y^2@L4Uq7X_)cJ|l1%$FX(R z!AMP;X5UM$Apb%P+ea4PN7&NoP&)h0`xx&Vk z?fs~PLWRLppQ72*^!L<{EEVE3HugpzA+}W9H;4ll&iKk2(<}-IutkB7GD|o|DEF3n zOW3}F6pmu^Waq$c#VXP3D#2ECCjlScs>EkkuEgrnYDc^^rPVg#3~%pWJJ4S$t(ojE ztuC##;ilZUTqu<4i={Q?t*5ub8&~q?MQM%Qn$zD`>N9_Tf4S25sOT_I8YuNgAH%t) zr!+8;D-F2!GD>}w1Yiw-2ahF9t2XZ>^mk#-#>1@eT&ZN0tnW-GUphOf;lx2X6P^14 zh&~S7#!jF(00-sL5cW-P1zJ*OB6pH^6xto01aIX(e3q+ zDRU9VtvXViY;3!2{&DU(b8A`2O4fKhUewM{HpJb8KM9^{JfD8FOD7C#=g^71222hC zeF9vfPx8<1x-`eh-XaePWZUbML+vMG{0eF$5kv|b|bxg6|7eo(X_R~{e6GSJP zBc43AFHGR3g>)0w9>C3w>Lht4)4=(m`dN_D#h#h00 z6i~py)1_R0H_Ht#>o4?m$M=x-72`Y{jv;ei{EVnqP>aPa<=QnD*`(v zHn_@jRzQ<+d)$hZ=%n+yNVK?%0pZ9T-3^(wIPOZYsUnjmKi~LI=seaRG+%;NQeq<$ zGXlMENMFp=E8TG;{eeW$r5fdsAZQgiEp`6TR`qXp^>%y6(gCv(+BTFeV)!Z%{j-T|38wF>UF%!5F&gl%{s^2IzD7kbBY3U8CU-VM z8>Gz|d*$ZS{mYLYk$C@v^<>&ogc&uq7c7rve}u*O^Y^aRyMOyz>=xsuX; zcpE{z^)=bpk?iAgGmW9yUTaO{r~2Wu1pBNB-#d$Y!S1FaV}-MwOwQVwkY`)jS`X5* z>3M&^)@^Gn$@oj3BYEt-$y3Yw(L4!dae*LXa;+-AUNJV4-x*vr{Zl{Za){TCqkR3X zNHO1cQ|tAtYy08rfW%QiSABzfqu{n-9SfX4YAlG~kYlBSS$XIPRrB2hxO7r7mFAk6 ze*&c19IGS-uB!$<=k4ZxN(Pb|61-dQ{fjow^UU2Obn13xZ7a=Xdz`TSnS&tA@nh0s+Lmw*gmkO{S35X%L4C-WTZn=0EjU$MXTY9G;+<=Yz9b1mf0@K`x z2u_7be`;1&2pe4?>;S@YwZ=z)%MoJ-H_y$rf;&!JzSg))Vm*mNvK#y`1&c7lV+ zwZ^ANuVdl{tT)l#ngcS_f+(=51;|OJJQ0DyS!EtCP&)IyK^Q@+?dj3FKhgR@s_fW`;+}Hw*wbx zLuBnLZQ7T6D%jQ8@~ErpPOr5*I&y*St@LM6sb{5;xZG&4UFEIo|3BW|1U#~$>f`R* z+v!d^nI)4E}{i|C-JD7d4d zqM#y+=<5c8`!*`>?6SKse!u^zy0>q4GQ7+8Jzt(DeXCBLI#qRQJ5_b+R99gHW9-UO z1JPv?Cy{ZF^8G*)J?1b?7$2gpl^>S-#gS!QZ6iB!c|5GXXvaa1Kd~tnKV5e|FK0P^ z)_wlLC;ow&#gXm9vmKd4G-H}`^pEQB2_41NorEywt|HOqD3P0^Vk6C#!%=Zcwmicv z6dXHuo5OJ+?eml-o_J1evh#20ge;)2?|{!CTXv{vz*cwOz#VOW-ca#p4ahy6?yNy? zVY0WByHxcPABI%ad)!FJ_yT6dY9~_9`R>)<;VpyOf6=P@mdThWNWA0Wm| zYdl4qACijv4*_)M<6S_Q(LTb>l3j6Op!GTy|1B7@m)M^tY%~X9{f43bgq6 zcoo6F$u$(wENw(_w!HWj`^?y3)x%-}kO z#J^|vZb{`zv*gtp@1%0iM7zyg@q1xeh3$d(S~*6mUnKH6(Wz|d5(v>}if;uv@Sp$i zf{tFrh;GNrxAr3vas4`P`s;2i`!P_NB~s{8`qfYP1~ow$Sp<|8!-O1#@T2#z#!U%H z<{PGr=-M(SIXZnu%f{LQPl3%*2ewCJIklD#n|6JMWImt0RSuI2I7%sq-oTipD<-3u zcG-!S&h^qSMfs`XKNObZe^4J`u=Z#8Yd_~FUQ4wlfL{nODS$_G9})Pa2#{yxeKlY4 z0J;4j_A!1%P(f-(3u^3emHIp4w;0WA0OtouQd#iE1Z>iNP~&*1H1=tw_d8rkdN-!& z*<*wx`FlbO>z6A@4s}cMzpPYQ@E-(rWy^v&-Ixx{v45$YWIIFr&%o!$7r5eN;C}(W z(BMAfe+97TiHupw``_>+c|S7E`_KVo{9%F$>sKh_kKpvxkp(|0u+Mk~`!Rth$cRty zar|R9E43$Zx%JdX(zNW#CCNQWSYbW;2n%X|7Xi)q<-3VT{~(~So(q!;YX8KUsxS9(drYrC+z#g zfzWO06AO~Im4Uxhm&jDKb&1c|o@(OMttm#{exo8z6%qq1o_9yr%XskAGWI12HI)%9;Hl$*b^J^YtdyTp4m5=1?Kf)o zIl$VD*lc{>tDc9YQ|oVDl2lXuWeaQ7_e~|G@h@+`QHM{eQ{QRo6V)1c&Bd<;wV5~* zUT46w0MAd7&%kF3JyX&y{EpX(k+11Dn!}HH-L3C*?Wu==!g?<0EU3-JnWUcqmj(9y zI|IhINZcRFc^<3OpP#eUVw2usU ziNHSZ8Spj&XPPG#2>h72EiTs@@Bvu&44`xaATe$x?BLY<|Ns@1aKU47%LKhII%Y#KY#y) zyt+DCCKE?g(>??i)^jgoL2X|}^36O0UO7E@zv;pIPY*soU_WkWXdfuBD@isd+;U6G zlLa3(Z3ZL+8QdBM2z0=K{lm+L4Ow)5?I4njXAbV4sBy_R-UWUjw+m-FlQ~ z#W6tkta(C2O$*Ah*O=UWnbPDUa1hAlX3eKcqXTYzY9(*cbu8DYQE`xuX z@KspP+|%*9GQ9zpmFcDBwsfp+5-75*$%^z%F-m26X<4AZ@;?^jy)1BMz21+f-p?T4 zh4oxESWtVT3g>%b27IQ#wpMPyj;F^yE5Y_0dK3P!YgL$WT)yqSbiMa)znL;kVNz1> zpGeDOk4#alDv1@=bC+O2Z4J(Jj?Tc(2Hw9@l2j((90e?$Cg5BJ>^M!pn+ZsIOoq^T z3E1=EeEfSJ=euGJ59}}*v}s&gOHg4w3i}Ic?7*h&HUplV9(;kondZ3;zZ;j{g3FCd z%Trzrjlrl)JIw5oWWf?=r*Qt>|3Uw)GdGjSwA7M%eCc+PR$>#mhW&|#@t{eb%g9Hz ze={TL;h6witoqiT0Z+S(v;7s!!_#I$QZ*W`5#i!>B&S7&H;fUApI-`f>dx!JQj2@BiQs?W6 z9+mH%&NnA|OuoyUuP1t3zRR6&ZiKSy(8Lwa*Bf!VIW)1}`4&Wfm+xK9HxxZ3-@EZu zZ==X4g;X!3XH1-~@ajc!zClh8KEt^$7W|Ed@>V&|lvCG0o))#MoNtHd8TqbuzOm?8 z`L1!kr4c99Llf_Dz8$0I<-6ATc8Xq*@4e2qbMz1S-sgO~ME{g;gM85?Bwc-*(tp4F zg{o!iI^5P5x1|aFf7b@9<7yGU30j-0{$E>E^Bf=(Dz>)pNb0|teW~8FKb{OLEG0)bejgDg3Ovfogy`2!-3 zU{h3{Aymw{z(ncVt%}TQt*a+A$*qp~TK({~x@p%9H9H-&dTGzpOMAUu;Kb)Za~!x# z9JrjH?n3(j8QKbC3VQ3?9t-kJ`4KtXa}_e+=8L39eAEwHP2cE>I!|;h6Q1y_L5r)- zQHuO}t4<|1znHC;_zE)Ol3zrR_Q|6fQX2b?lRH~;KO@%qI{i}}{U~a2^q1XCI7zIB z(u_Iza(jF#Iw~Y`3LhH+%F-N0OaF8LQhnVwBt|d)2t;O4aOgF2Xi#g~&_Rlp(Ml$? zxEwloPQKqbw1hB}V1j5DwVieh9C%>{2hsrslJD-Q27z2L?6C zR$<(ac4mB;jh2$%i@9~A@vb@_^_V5~v`vJ@nsvL^!o+J-Pu!>7hsf>m!TiF=6?}}5 zxR=-6(QdEEo*Mpxc#muO#v z;Ykk>SoW9BQrsodl(xKKdd{_BiIFbfDyN zC7A*xrrTQ?;aZL(0Z3qXfH-~Zb59cEx+hJX877Q)7Y?sI3@Gm&F59$&Ft^0#JGAEl z|Jy95ef%n`FMGez<*X1tLNV>_4$3{m4b_M7t5j0+SFSs$d0S<)xmyjgtmiqRsAJzx z`uJf)y4vX5TZFElg?K*AF-w0Qe$nUBqcOqgiyKqvD=PHw4pCiV(9hGXq|!T#qJ(l$ z38UTUsA%GZ(F!q#?>>%6;?cGwa*gU1@LIqosvs*!?v}~-_t3OtAQoeI(cUR<^SLqN z^{X7pB`O9I>GPREPD#5Acw!h>x)xeVo7#bB?@|2dgEV>;ThYEyXJ(P?Uz`)jl2FOr zhB$zLPLjVK#5SJDVV(klWgYcL#)$ipW{-QR#w?8&)%OwK+HYVw57!#c_aa!D!KNPV z*bv$~7pC}S-1FUS=fGRYRU#;B1U3>nd90!AEkR9-v%Cz7_yNA5>?#jszb;eu|F%CJ zM4D6jQ&I1#=H6>Od!O;FriEZ=&rWTQ4ZzoHcHl+HLfIJRTC|yvbdArP)%TOX_yhbb z;U!yfNuB9nVqs<{>1waU3-nNfrv33%=1u$Kk>*Vw-#yN}>EpX6nD=7|MTv)Dd}HF3 zc$n$StK{XL0NJszRD9DNmHHFANcUR((ILC(1@%iR{ua#dRbPeNSBdvN;yL8n^^}rE zsfe`?;_fJvi`Dm$RunQp$i5*0_YfEMhoe>;X0hWuG?aMqocGk?=NYpf;QK6JKC;z_ z!Oi`MAK*f{Nq$a;Hw{lS=QrqXIl#Hq(Lo7^p)xcN=_LrfC=WJ=cD z6dg`UvswDH)nmbQ#jjVK=q5LYX#a>of>Jb$A@uV%L&Bzm>c_;(kBgU#Hei~thJCp( zdNnwqd&F7ZBg}h^nz6jDd)uqe47&c+kdqC^-f|YsvGNw88`a704*C~G2&Y3qO*?2V zvG@u^yXkpSc~8(kJ8HLPpa-NkgO%{=gT|}m4PX;rG|xsykp<5yn@kv6J$zHg zq}gh3E#F{i>cMQg#}o7~j7roIPl?h@!^Li_EW|VM*<4+SXXA{2j9iI*db9CT{gin0 zY4OO7;nG3+h|$&C-1Mb+QHSqKyP>NoOM;mmw8*DnHeX7%eXz)h?-C1as!lo-C(xy_ zuVV!(-bDIN54}H#e}QMDH?TLhM`i`~{5CB<{ylJ%8%mZBlVcPd+l2|>M@lY zbn6_Y;h}JzD=Up<9RaSx)`txzcZRwB$-_sDfA;=&P}BZwroRL=ZHL!K=_Sc%vOqoL zcqscGvQUHapQ-CY?(@*R5t>0w+q+@B3z=;mL~3cCJ}-vcB8HgE$PSMsiP@^7CX{xu zE;%EDK#I27&O>j7=p<+$rX`@>6tov0iF0AR0$21p!+V*4_0h*3G&h{1g(F@%p0wIs zqM6hmx(D6C{17S4h65#MM?`rO%g6qh<>5`nLp{cT2%-J&1|I4xVHzH?;x9!fLe}$e zal*sa+^s1OwS6AOTQm>EVZ570+{{$|1u^oADI@g`x6(C6%F)0`J;QE{T%2-k(1GYf z11W5q6gE4BZ41nCw}Q)acSyj5yOrBp!}w)%y`aA@Vux}lY^`^~{6cG()h{W#w<^1i zkHy^Xl=)-E$6XLRFytDY0&kH0bq+yi)^fPlN%yi9J3*jp)?XH>uNWzf={vDU^>NV| z!PaEOy$e+;?7IczOZ>l||9AZ_|Fs-ayh;C+dzt^2fe-n!bQ8bSsuMiL)qkOXuhH|C zU5SgGQI=pBK+>h6;Tc$5#v59xE9AU?CWG!f$aM62iYiF3hFiq}cD{6<&)sM`FTFe0 zjp#rvl;iI+(R(VvnsvHYCiKlhvT67}5ZE2EJLv=5qu`=KsW5N#z6@!$VbrEF@Xxh3 zrk; zw-`ZndDnXU0#~Z+8W&3Er#WzoT+Q_jYf^?L9q?^-O{zRJtx47JKTUoiA447rI$_fe zz*i|?vIB4?L4I4|4jaXh)O388x21)X=e4?VvHb=>{52>bs)g}JhKkH&tUZS}rDf5a zgfc)Lea7nM4k9KGErn~ilOAy8;4Baa(eiyBzF}kP2F2qXM@N*Q?L=@N zffUY3QgGf>7<1lp(@?cR_rBxJ;)9Vd6&4wJrk}5qz4$*QMH4B@is;Yieenln59347 zuomF3#(rO@9O1LK(B%#ZUAa5G8G0A}*ahw8gV@;;CV2^R8ZSSq@}J$M5^HH#Fsa<% z!{(;9E*Gmr6}O}3%5X06K36ZpV(ta+s)46a>>oJ(K_okwG1^;@nPGekU-syA>$;Pc zFJ`hfQ9&uRrcBFUo1V_q&f~lS3%B|OYzs^ls=C(wJ3Tbws>T;uc?xp-kf+br^Mr-q zol4>GTv-a9H#Erjy}EDbBG!Ue_wCfn(DrZAADUapqb-taiEpHYLq%kun{Y_Bb!)RM zz1pX!_K}(7dA4}kf=FJd6nag`2;j#QF^oT(#(#NJerneth*|uLRA$8=;tGx(Z5&j} z75cVoC;qK2BVqg{BgDfS)(F|irN_p%0j#VXU(ZO*lfD|=wt%ayE;*6U-J-gr8Gn_Q zbAC{}k{mO?+Bb}K#6`Wz_%t;=vtW;@x(sjuHhK%e*s|5sC>goFQ(W3<$F>282RqHN zZ_DV>&OdtS(73tsqbu!O7~R9ZrO{PGN13bF$LSf}+WAKp4mq3!qdf+xjJo~kq0z3P zt&8je+7rGuHp#O;xsBeaoYOK-*Eib^my<31h4CBdCMGq!2b?gDd{csR zFwTZ(C5~6&Kp_NKLvSc{5JfiLq*#D$JW{Lizgejqo~;j1wlILyVP2K(H~+ z>gpXDO1{BQ$(9CV{#eRPspYN6`FJ*TY(;Ph8OXrtx^2zF^l|zs<^<#YiDzf4(Rw&0BXMnO9?=l+PI;Hg`wS@;2++nP{azRCSG2~(xv4plOKCOz1|R69urK79kM*vYTZ@iUvql; zXGuafW6tzbH%(3cOh%kduRU|619+*LKh^U#d^2-+!S2@QYlo7X_Ya@U z*8Z%msHJKRAJn9lWCq=&K0gbsufnHti4z85 zYKk(4%>r~I3|$Gl+*P<;kLQsHwkCkGeg8x9%=P7W(?k;EQ!XriK=txd-EEd8P=}uT zkW~t#Y$=Sj%?X{9jl<@$${Z7}cM59KLu)hPI?^Gt$8R^0Izfh)p==rFzDC}WxtEH6 z65yPZ9Vcg~5)3n;vYfB3U}!jgEC1TY`6>T0^`yJXHCbqkt|X&Ir27O4n^aT(<_%uYT?#SbG+&&dtI_3eY2Q&|k7t6`co5Sr9NaHB`{BLyx1k=&;H z62=2^Kb{0ue+0q!$NX3u2@4Y@NrW~V2eo?Ih4?2RNuFxWvG~q?o%Z5#mCS_&B$;bS zZ=_r-yLk(_E^P@+Ky7Y1EA(D|923-Fx$OfnE!bJL-;R~R2D6?K-G%Tw+zt&j!=c%n z2N6^!lq?uzn(e#p-5%YwdWe1;mR}XPO<2xUoSllHt%J6>mocV)yQQ`tC0{m-rlkmnk z!DMDxA`8uQC$w6wI4x2mq8%#pwB69obMLY|9<6<%Fg}9MFy_%%-QqjS`RNh$K9= zo3JIzXKqrM&rr{Vpu-clg)gLJPG}$dedQ1;UOaK@KBrq?yA{`iXyko+y?{aaZk07z zHzo$Q`sePnePP!zf(!k#R+}VuEp?~=?EvaucB6j7zxvj)ieWBTy|1?PkS=o^o7q1# zkh{_UYs>PCLjS&_uV03$b1qy{hI??}I&x(--BFyoG|?O^x_pLiuQKSLYiM*$owknT z`{!_$-sNBbwKW-~rGu5WUlZECrI@TF5HSr++^U3Yx=9=b$o>T`klEArM#41*D4;cf zqtQnkDxz;71B>y=^k39Q(1QH1LUf>LlnJVnW;mTDk63UciYpZRMjyqK>^V94dKiw~ zLtXG7yd&!Dtyv2Q&FUk%T>p_s#bBY9QbtgfxycpE86!)nTLS&DWU;$#PMevN95!?M zk~4?OgdNimmKQv+9a$W^t?lx>mIe8C_iZinIL6_Hu69Segl=g2oKl?zd&s5h0W>Da zqhyAbLboKxihA|x-lMMXBFXOduJ-n^kNM_a?v|<-kvgunLUnb3!Al)&V-It9ZN>r&vGNwES@> zTd^EIcBv=5&Apl4N?|_wgi=SsjXo)d%@qfdk8hEWSwZwHz_ZWh3KA!(ZNc0~t4H=+ z7#tSi2iUW3phMxO%g(|9fPzbzgn_5in%J;0T2Lyz|%8%BJ(%lj2|ikU#pK;4GZ zR}`!iKVy!(t1Qw`-Ah;bPMb&k-kLw@NKZ7h;$S1uq~0Zbb!xGc|KMZ*xKS6lovGh328ZEsKy6FiR%jK5T!#cSodco==yzvlu{^>o(%cJYNc>`f3VNM9u13Qf50WQOFH*>%@@VZZ&k6Fp=sgJVEm5n`Tw$}PDe7}uk^BG7 zo?YHonDArp|I6CE-VPjI=!|Fbmarc`i*EQ-#aGfgomt>{w;hB2!>pf9t-ki4|4#=t2MCVXO!Swf39O4Wwz&opdz(OLgQg zfaQ;dl_Yi|#5?Uxe#iCG7eFYHX$dj`QkQy+>n-$==jBmDPeKYdGC(6R8~ERa22;~G z8_>oj&yNE72RwN!iaeZb^>4C+os?+%N-&O1#i*cYcTya7G1BIcc<1h|eoyrKM=f(< z?E`FhOYPC^*rGoCE0xg3bFbU`YXQCpRliFk1djfV-jrHk^3eJ#!2QN539{&K7|nIXi3`Xg8N{D#@Nw`Z-Wcl%nkTWseqTP0~T zSDd!TucGg0B?5hbsvB*&Xe_mJ1x_l$a#VqPZuk+OPGc}+eMT~6aJem4#KUqOCl56lXjGccm87{Nfk-tqWQDxhbc=pNMU50~xyJ)tYZb7m z%n5FbnIm+~yjYXf#>6eFjn=NABdd*$=}Usp53EbHF2%e@?mqZGw=|dco7Wzx?E`J^ zTSh`^PYX1f0+Q9T0dT|kOxAJj@wX5k#FY47EQ?K1b97rLVk3uZ;nv;O#(ui%Kmo#6 zN|blR+siv_1smhP6W0^usWFi>&}vJ3NSrpm<77VmC+J*ZD%+^O>T*J>4`J-w;@zMizYc0%G)heDvE7E@+hXmTbzUyRvUT}T6A6? zkv%Aj(_y=pt~~L#Da@YtZ!$w+wd=JSGWW{Z)NVR z(2lb5(Qh4cf|QSb2S5j|AGUSO@8#Pq@jZlZ2}7xk724-xg+bpJYV8k%aV;m;!lKmx ze*}OGbD9~Q^W)XF#JS(bi;obegz^N>0fD#XMP}vBV6C7SzMsX;DsR^<{cV!gbn*WD zQt@u`w|)Dne*tZ9{M{uU)l*>x$B&`(=A2MAE93dNgOk9KVm^pFaUhL+mQSqvXYe7c z_RDv_Sf_Gh#E0=`(jBg-hco7e$@SSWUvFev_ z4ch)}%o|QfT@Yf%M{X#^e z7(areQ$OHdAS>O)jZ2nnq_et9G1`T? zgXa&4GxG6`r6T9#&SGRwrHhjl*e(qhc8+GO%Z03`TY}skxnnk%PE78~!0xS$%n$6| z+6XrnbZ?E$ZTHs7n_4i0NNmk5f2Il_w6d!bN|_qHNY%~!PLXKy^|Ua^ zV5W7Sx1v<03yL12!13e!)LpKX?D|%+;%-FtF6}Cgzb9!K9m^h1L;9AYs`&)57YOD0 zI?DGzDURP%2i%^meT^Wc*hAg~5^hlAfVfH!G-KoXU^O1g8tD_oYqe0{*4$ zu^<1t%Du14!oVMq-IvZRj{jmW--bJe_A8D*R`=~%9B)yJRr}^{PI0`q?pySdStySG zIms~kMb=0#n(p~(ooX23Wa%u|o}N@Q+9m^esrWrM2ITGC(;rdij$R@9G3~G7#+uT2 zNwjyQ##sej_lsmI(|x$q46_Q*P9cU^)6#e7wJ6(F&Zsf z9ZEUdyFShyF?siin);1a?8~;Z&^PueH90G{ln;MKKFzjt7|o$M1@0>J zv!peCO()ZufYNr`f+du$;uhDBGO~?dyEpCc)oOo2aC&VHfs}sC#Anx`)j$ibN6YD; zHgeZTUSxsZ_*WDoh@KRG8Lx{~I#PSaLpEU0~yZ~STYb0kd26ULvB zFA2K2A?UN&pwBe~eLfo`ZT6JJ7vx##laexg{B1!F%s@hW$EpEEq7*&Q)Y zl!EG=q%a|VxLgiErK?=mv8!AXM1Ln+;Yi2$-L$MKSK_5sA!Wc zSB4dBe9>&AG|hz9XQ51$YZY33p61aLb%C?Q;n!n-RmzbYXn$)c1#aHsxUr-a2)rx&9LDZpb$Yh}&b&9cTg%V8O!tdZn?~=*Sf5uyJb_ z9`G9Y91;Hq#A7y=hfGi^MC?$NFsbcro%iR44{~ym-h@5eN`nG%7@v$Z>{+pKZ(q$a zS*`{U{}Y<7?gUaD#{V*qDnuZC9mw%`W6s_P6ZzS*b9?X3;&imyL-y8*4V9fa-BrcJ zC&`fZu|f2G8-^}{X7xpWCcYpnH&#m6Ky%&8=s`_EVf<;@JtwuBK$d{chR%JEAd~fA zwp|F7sBdHLE_`i2gx;u0-1SBlUr;h~J~HP31&G3Tqs4MlWK>5%ZeM8pg1oq(xCO*G z;HNayQHVqN)NNVA{zxTQtJr2}D z6o2Dikl^qRLHrQk(`K~0xA*kg!4PLk1)dFKWzD_JuGZD@pFkNbmAC&3uL2C@2C#~u ziL%3#V>*Z0+lu8v{6}ztVp;k#DSDf!#b`kM8U?W7(j4PK?G6CqoWAtGohY04XizmM zSl{qi`leXs5tcc?y3=Fnn_`(qSmwATsNE&3S?+6>TFO|OPf}K3#6h18(ZBS_WKZx0 zB#oK^+RKbRQLh_w4eiRH_I00zzOhv7Ee&|hh#3V`Hm%E$21mMiBW11dd}yf9m5x&b zIo1NvOhHaSzfe3gP#DbuHeozWQCT`PqXNpJGIvXxe$Baz5q1Fmpa$>@gRnJvx%i$p ziUIYS>#5$(bnYi^tyQZ4f92W>k?by8!3IiXI8^xkK&ko~neFOJ&nSrJ44k{8xj}|U zf{kN^VDcV-HcsD-V^d*QlCBo%1%vAp68G7F+Q!N=8Bkr{?a3W}s_VO>)n&w4r|9-f zVa2}@@J$0y)#ji<=o?G67>8BpA#cPfn_ndc!Z7*`zC4#Dwjpbj-6Aax;yt0Qrh0Ee z%^U!}l>p2E;M)nn9A^f#?*UN1*VpV>&`tkKNYu84q2a7=81JV<$f<=wN>J+;<^b^h z1YiyT-%SAKU~@@{E-FWzY8^+=I-Ea@W~gacjuNEaCZyi!kouaC`ldsg*Mu~0I;8nc zNb{#dTF`{FU^=9QO-Ku;Lt4~?v?z2g%MO*BM)zKDb(N-kXxM^#A zKQ<-TKRb(_9`Z3B3VKH8s)$lBGu{SB(y=qZdXc)wsrk6ck1sX{9HqIRvjJ zRDq^N)zHyMm7V43QD;v@1vD+yfvKo~vZx38G62naPMwmJ%V1d^AdFgp6#$)~w(j;!X#$3o@GRIV2t#z&2M z5`Q#gAvAr555r`nm|8r_A4C`9i!ae8@WUAWb}u?>)$krlo)CKp(FnZ!76UToGPvR2*Jje2M#5e{44l2<@^Q5rouPKWwp(w z9EHU5m~xC}qag3*oo#dbo#p18^Mjgbm&auNAbKlAJYZ8^E4mw!VB`gt!7R>pD1>>q zq!B|H3u>br{;avwPskJUN&aok={~h9{~t&)TYeZ}a>Uevd(3RX|3>6Y!SAdWTp_OD ziq=qYSMDuy`<>>>O~HgCtuJ#>_;*_24Z6MA{FAeCM^O7CU&(X&rg-wOS7lrH6Y}`* zJz#`+%M%u#Y3_H5H_1yrRQ2#I4hRHDluAIi@GB6R{vL#!q8`SHYeHf= zpNcfU35n@^D$;@`B&PGJNDG^gn9iplF|(Syo3KFhstLPR@ty@tmyJjR(;+QyLRy|h zV&E10K!b_$vfHP;}F8>&FlqB0THg>i=pXj)WFzKt1hlW)D$NnUg7rlJDMQoT9o z-(+KpzUouKWGBDY&L!u6OZ_(Q+S6$D4t(o0B$^mKUt;u@2&ZK)Pd{uSv{7>)PwP9q zJbkne{FO#%9-`A1(-7=8{2G@nDN30o#r3K9-I0jjqCExg1g*i9=T^)LnVjAl+Z2JE z{vE*VP}vZ`1rD#e5nrsyhk^BRN}|^D9xPABjJf2q##xbE&B|uVL#O%#!u}DygJvof9fKLl-oabOC9gd zlB;jA7RG&-z=bRx5}-)~jQj>Py)1!CNGJj$xihtxU54l^rqDN$!Oni+|sCzSXq9Dk!if_$|^_9rac z6!giag37Og>f2aQK~z9#Ai4so-nM9}x9E5U+rfg*kl*soaN~8LzzvutTI{rju6CTp zZnQH%G>u(#DBn+K@@=_bK7B^H(L7@g0Dl*N?^FK!w7%kZKC|ESEI>_%`o^+-<@QJ< ze_?LQ8f!550)Zx5Jda~jVKIT#4il;r60-$Al$`gr=2VyZb2KF(h&B>}(H!$M*9sU+ z{)68P<$h7_G|CEz7m0Ggi3!qJxcu5_QlkBvKl!QI7_eFiF6OGCZdAT4g4AD%m3fj7#^9 zvfWC;A3T6?8vASd-~9IMSzmSUIzVZ7?8r{}!f3QFCyh$4-iP zt<2Jr47$NVLz=5eDn4|83=O+BWN1{}Ojl9=5m8m#tc-tWSge2v6%<>WJXMHWA{l;@ZLeH<8 zkJYKp-+p7~FGBLcCEgu3bS?~mc(z6~6f72oD6OAG>ZV~jGNTxOg{d@eb||qsvATpR z-?!cA!zIq3OZ;lOi<2a!W9DtT*v>5JYQ9uGZk(F_4%zghanj@llP3HyO?waZ_J*{- z=TAPmw{OXfK=-$zYhyFVM(7MHGnF7IO{W(l44OGJX|W5Vzf;^13@vP$%M}=%hgHuI z->CPlkXlt>oF^&G$y8_d%2v50S8)i!SDaRT29XcbSda3VF$+ObV}P^(d)otUrEhR7kH3iom*^l7 zYwV%6?$(WMXyKm;`meiMsU5fHvt2GaGRMAUE_X^0FNOuE+edE!N#_2=`zHy-H zqQ>F1`o!mM;_2SeBw}qIz5cjg6m5B}VPhsa^fS)sJ;P zYu{wr+K0GClZ@WRcXmrsH`RNoDYB~`ZtE$GHEBUR2!Bwg^nE108?26c4WW7I>Sri7 zy4uyxfkDh|PU_%XvK$XmOg3S&pmTs*J_|X9>D(WU&+jBD8+XoA?yLu0hKq5^4Ik5% z;O$_{ZZQ>{hMb3N!(2|7X((Z~Xu0!gDXrodOI(w+B6eV^Oz6Wii-WP2*b9z}wYH}2 zG^TWNYh!C1HXzMnLQzu=&!$babQarsqBl{V5!63XAabg|b6VXHj6Rsg6;#sO;`TZV zrSuchfw_=fv}ThZ;e>V4TC`| z>b~5IP(gp+)?LVykly0j+TOWs&v0#x)!8&N6jshm^riAqmGsR*P>Y}BR)rB- z+4N)=7F_~@B5a!hCJ~f*n5K0nS6J<@e@-%+NEcAfm6Tl)5Ai9gP*aH}#9DwHn9o0iqNXbJOq&-fDhakFm zNT-KzK;t1ZJVYx0mb?C$9&$_yDSOC_6q1yhi-bN_QfxTqA+A*GH1tjpM#=(;*R6KF z&&eQW3Ezf*_o^zKy?7^y1vSN>4_{4)+imc&N7Q27%52AXOX`q9K|Z>QU+XQ2!E}U_ zYk|3eUz&l@HFzx#K~DNt=zpX4ei%TkRE7Wo{$(g|7XOHu;hKAZ#qUupL}KL!n>q|s zYYs*1vU>(jpU5zr0iC+Nt=8P9AoCX+^K5Q00-9j33hpNuX>YnK0LcWSCvB4XB)P6=S0i16sGdPNxlHvstrD=MrA;g!;sm`lrx4QV@5B2LCmpUKAq*|KEAT#~ z!-T^%XA;6ic<%LN=w0T*?2>$I^|zX1x$5*?zVY|G=lk;fzk^57 zgcD6}?APEJ3A<$IuV-in^tc}YAY^^Jdg|s3eD3OVNDo76Pgjpeb@rgY0ikfsfyz3! zo{I6)^dc8gzDz;>O#qk&36q;pZSjj4OlLU2Cs@!vw_|%Zcl;YzCB}D`fSrtEIP5A_ zaGxk(M_0)?xRM^xi=bW6%Ny=622P z>actLW8a0Wvv<(VZLk@cQs9w5+C8&trd@A0DYbi6*DME~UGDB3TGTZ==$hHpYj@o} z^G!_cC6(T;ULSSr=UuZ%MWz?JySln;xM3&9s8zq$K?EQt@eC2l|MmRrhS~+W0kDO?2*WN^&zj+EY{gB^Zlfl5$j~v(id>5 zSm)>3a&B}VH`i+ZM~2QlY-7M3)V>qbu7jw=v`pfOL{?7}WlbV@c`UwJZj;8mj2W8P zWkMI`o1B?-u99h>PUHow8Qb={&#)7sbm)O0neP0?RDuv|d423+)B@!zKc&6-i%)IVQpbK(tRTcVg>Wy# zXl@gb>AEi2yw3x(l8vRV9arr0*cN-AzS=c1#|nu>UgOjNVCq_}VVHxhA;#7c5zI@t zF3noFIRNOEtO3jcKsRI!U=9Gf9cut{Y|s-PA0x9t|0xq9g7So-@=*jnhDJPHTD5rQ z0HEut1~3PJtrLJb01PGob1cy#AxcUtSds*pV}-8HTQ15I1^`3XZH>G+0O*RY0nD*7 z=wF;>JVDWYTthJjRC^uD+zA7~zuOt8;9mu)(YDrxa3p?eLI$KTtQ*P_QHeEni`nCN zly()!o)p@}oyZ8=;W7-|+v6U2WaCUWe9FIK+2?eO6B)Ufn>V1XPq$~aj~x8XYS~mq zdRY*^QjD)DGfP`44bb6^@lD#o+k#$lK3fll0ATaKey49!^+g4gfMmY`ilETY=Iw=|Q09c*2xWE@9lOY^gmmt>Zhy6Wd)y*HcS) zdv8+57b55mM&xn_mmVzLM+4e%rS^+_gHE@gT>ftMR5%5){Q6kh#~as~oiEy7=?pr_ z_?>H1Hq5JWZKtA;N9A>lFLo9=m=QFysb|+w9MlF)T?8w-(-|ix-V%(D?ytQ^CF}0$ zJWPVxU0uWN9KX97PFQNUPC?E`2e2rc9(#$p`VLgPa*I%xPi{#F{csXZiCdudJMX0& zk86Ch!6&pm$=NOGgG^lcDwwovrYa>bvx3O&%s*Rfxn*zV$E8$oa`Qu!Nf+sQD#dsW z0~e>8Vq(FhXYUEE?wlyCmm50^YmTA~Fj%(oIwA5)5&1wPwLQA%pI*ER77eq2_B0YZ zPHpZ<#qT5{ICT@`5O;G=sBXgONm6$ge1ll;WLg7?^%|XI+g+JXt|2jOFRx&@_S?bV zA*qr1?)5qUnw5bt9C{I06=xhLwg=|!(1kC_&pL~sSs-_7jWVJQM!kdONXF|-XtMSY z9|>4(8_tH&GRhzA%#UkV&fd1s@#DUW^SBkm;`n!PxQa*gr^H+d!IHDNw!URRo@6!F9Z&)|xU+`Qi#*$}3`(3(?^Np~YGbslyy4@lt=tR#qvQ|&x z?70lvtiHa&+)8qJf%X(l9%6IezM~p3^+*!?K!YrOQeg;N>8aZ?tg+RZ6dC(jVwZ0m znoKItl!l2BblEZI7%{?VF~!S-D?z*3X;CuLmy4JIq^bJWk|r^Bk4rzuy^-|w=ig8; z$v%x1#0S!Gupwop&fEeZ`nTFk5Fey2*A~PFdki*qSg`9i`j^8ngF3{eEqH5B(LWW^ ztKG|!RB`sJ;uuJ_u0m(=O4aMm$zMg@9DlUTFu^UfrG+^?D+U7t6-?lB!OoqQ#4{kJ zG4_LAWCmLiIE#Lqd03yk%($T(FO`1Za2VPNq%%Kkze+QR5Aem-YQ?QUq8F{$?$tqx zz0N}P8~wvEq`7Bz2Y$S=*ZVZy+1tt1ZT({i#t5lS?!e5#>EoCt7_IwHLwbCQzScj- zy~sVr3^X`?4)aZKxw;fjyrV(Z0qN__Lf!>rUISzUkogUen}956fP46>#2FOo=^tU&F{wPqX0raFm9SxvO0(CZkIu8IeqX9HupqUNj<#Nhd{pAMGN`V@A zaJWE?OgKrPg_($@3l4?ZY{;_rKC~nmvk#wcQig za>3*aYA;V<%$=nP`GVRW3C!Zk7u5D_fXNrsmM5^cE3SM&ZLb7&zF_hNwG|2M&4S4n z)b>tb90ryqwcrwS%tP&*)j zS-SECwF48F@kPF1a+zxMAam|2=PL~J-~@9w!Q=~Sha@oLmVA}-!`@wHgj^+Bitmck zPT#@q`pXmcuHH}&-YFX_j|C%!o4fw-Q19yShI*`>v$5n!Vwrn$v3AMEk|&8}?#;zo zmW?G(63g71i?wSumOM!;b2r60!8PE_t5f;-WoqOo4yi5kEWqyaPQ{B~4t$9M)V>=C z>`RS{fCc2^Jv@OXym%#OMnIjRfxwc%F3-(16fDV5N8kPc0xH@8?<9gcoBGoytr5nmTLR*W|HA=hhRl$H!pL z`ci#1Y6A0Ob;v#@-8pu8zrb^Mg9Jf19Ldzh=!Rljehn>0e#v!gMFauv(GW#=Vd zqO+Rsv*ZsufLEN>ySiiOfI_jby6-hdv9G>iMxIyZYmZ{wj#uVudRMwTA7Ua+g2Rqj z;RJnt;s-22;;3C@owGC)v}1y0hcEQ7f{i4jWH%lR(6sRoY1dQB-8Vs`;R1&MnF|~i z4&Hb(o&Xs<3x6)y)Lp9*AcfI2is2PTX9Uq6FeL$&Clna;Zt9*8wg+qL%_1dR9PdEz zVh==ntg`WF_gRw!n2nR|juyY$!3q5ncXwGQNzF7>Cva>ke2hF*526(eu2V=n zfS9ncH1#fPl-vCzcee&*)pNjtm~r+^vbGodS%re6$**7Jqdm5 z%5oklxo@mMPeM)~ny9#)3&_hIoTb{ItIPpiM>uX|_ry0K->9p=0X=|r+{l3Q^&U4; zcCPuyVbs*BcpitwEr=zOPqnUj&ic~%B<8mRBHoE`Ye=UGOfy$jhB?V#~|+u=lW5-=JE>Dql~;VZW3P1+slObF2(% zZw6rZhN5u@kX8D1tJ%QBiHv69G=F`Q=Fd*2kn2oRU@*Ck-wcyJAtt@Tn4}PC2n-{*m<=BRJ17eS}f{eDYhN}p6phgeDqi3gRExAoO(d-tv^Mw_ze zo0KK3XaR%C3mYkaN|aw|lob*$5#?a5aI0)=p}w_^c(NBTi}7p1=uxBkW@^;DS(Jp%a+jX&TN<6^S)`;0*6Pzs zio){^zMkZk%qqN(T)=25HN(ruy58ECfEcShXnq2M>mIZ?0dX*AAdV7eI~b1^Z~-&{ z4x~UzYru^`bPhAb@CeV3=*zC3q}B0pc5cjY=Lowp23eOt*jTiaDVY=t=n2d(bz3KQ z=#u1J3dv8X69hqYJU(O?J5`^8KU%$s;B}Jz?2^V%a!F%l;@CNHtVkSt%Yg)ZjYVP> zHV1(BBmi>&xHbWpV-H@(0T5OEbabinOU@8HsJ_7IMo%>4CLw`Lo@>dWiJ5y|a+mEQ zmI`NMvr2mVoQK)PGEN)ad>NtAZZjREH7|;^&5zXqnA#KF?e0wo`^RZ$G)7$%&w!_%Qa^(ttqcy1h zhG>>?YZTertq*bF<&4YBa92UH$X4jQ8Q7Z=@dTY4s`X8C-Su9;(_D9bt4_3F<@>}+ zzSkuzHOH+y1qNVbaj;fj7wnL$&sb|2ajiw6y0rKmQi(%pQ|;_LVVsvQ3DVo{^`KwM zmjvm__d;Yr-o&=9P_D_Mir%hz}!vy0pLpsz#IU+kN~`+FB(u!I3m&Xm{5_hZkQ0bHNiIr z1iqXA%mLsl3BVixZc6~>0C0N(Fb9CICIE8)_*w!m2Y|090CUhC5Zg;wrBp70XiSY` zYkq=(g9(_hgiikhU0OkO2X96$>fV&caImR(Z z27nb~?QVTbLG2#C(!kLbZv$HIQ>Xw6HGnw)D7pd60pQ*QU=C!y2LQ}-=1&Ng&+yFw z;719-9L(_#0?-_JTsp2DCY2Qs2Q5$6?!i643l`wBx2F!V9D zSrpOui7+*=m;=C16M#7Y{44>O1HkJKDVdU(IwsQp&NGQMaDEbD~D-8uj32o5`B>6^rMmpbrP~+3u?*Xl?qD_p91hv26 zL1suzgjUO(L`ORie?oX!b2^!r5OunZ<=p)3-M-QFn0h0^NMEp4Uq)D(W%V)34tn~^ zj^N7i4}?dd^bMj@thSaq6oF)Y=OMn@{LnY1mi^w%YG~@25izfSt9XW9LSc7C`%GLZ zus08b|b$n9m=F{woLK|laR=g{f5XMX=PGKw9J)BxYeVqOuM==8MR3a84;pV z=$qLQcE%@9aPYyAnY#2WlpwNw;M*}{3zAa$%f{=O+9ms{I zl0TUIJHMHd!O<-G{rf$u&yZMpmBUK1Me;BM79K!E|;r!!U3g z&7)&rIwHL{6LBs%=V6m*OGvx%&(wTalATY8CY{|pYCbwoxEeRMhA+BL)ex<QT@Oe#h4b-jp|JW=V057< z?9soe`d>H(gNc8U3%3W+YWI5oK^=t2TMqr(xrZFMk5t}Z`E$Cky`4jIxkk0YG(Bgu zOLMWk!`+|aBIKWnTHd`5`rMn>Vk`Cixxx2G`Bnwe-!bDYA*Ys?Gfq+ZO?T?jsK>diotQ?wE{$p~qAF`nZ#bAP>PczT52jJgMO5jZzC_fM6;&?>-A1)X zA69g%giSuz*bcu9y!v`;hYE@IRy$nmS;^+``^>09li-I@dcOZ2PHA{aPgl7`Sh%4WrN6Ap)7I7&OB3@fyTgK zci}Cf+Qq{h4LNL8pL8;AdoF&n%OmraMrO@h`qpk|9M^DKX4zPWsOMJ$j!IEKsqR2M zbMtabKG7%C7Btqf@tJ#3<+M>Fv^S)xnvU4@eb7bNf{#r{L>|Pg2k`D^z8)z?L$tr4 zBK{xZw`l~Nt-y&7c5$~+TuoVnvH)J1(2`@YH(sUCf#oncJ{%{S!rSs0Mg`s+(GQXE zOz6i*hXQ0-Lyif_?O{A3*c@PT6yn#>%qO(K2;=RN5IG9*DGJf*1nUL>=8Xg^3+$nuS>7qfKGspJP{}T>T3hb}@UO7(Un-*h?hw=~U>* zjKCh2GS6^VPkwM}-j2H5WbH~5uzNDc-@WUtUPetZ zzOvv`V0<~=-sm%AMWdQ`5nr;y>-g$Vw;%2%i|OqLP0ntL4x*2#To*wF9fF<-h49?L z_z#8t4xr~JV$^(0Y7@wlO|I=!?qJU2^TqT_4C{xo`H#x%O3bj}<|*g)$xH zTdPQX5b3iC$X^`;uZ~Cq((?$u^xtj0IJT_+>@hkO&>#M2h3_+RxKtYxlv3FuF}>8mBFi z`7R7C!(p^F$)uT6zI_s-)vpq3otBQ3#rgPe$}r!@{r3s~ebRrQ_20AXpoC}6J+Gz~ovElXKNJ5@USN;b_|nBPee#;H zN`?LxNArcgrKQ|Pwky9!&Uw_sjcGib)}1Sgts3(&`mYDjXo!l}QQS8qK%rOw$lbty zx%8W7`Ebk5k}psE8@y$A350De+*p?4H)feyns`xu3}Nw^ctP%7i`85D&F3>TEIhuB zELp;a>Cs4zTTSCcM(WF%QU@2~#X# zN$Qq?cas6l=VAb3evsQ8T&!Ps9`|orx+tir?&?*!w1a&;<8NuGST^~v!~#G9;)Hmt z?YroHwOZ(MXy~@0%mKjGINF;s$FaV>43O%4w^eR%Hu`Om6iy`Z4oL`^146G9;ClBR zFvmoU;*X;VC591IqqY?5UT5;m=ho0?ZCPykuDpJEKD;ZM>93co~^&p-M?>o0)vGF zmzX(745fYtFb9A$6M#8rqr%KIWApkdHX^hxeHUgFN1Wd)vos)Obh!*E(dBAD%IK*W z679W9U7`Ugqk&~ei3U~{3DZn7)hngsA$WhH1f_m`|pS1bp+6SgK4L33xWr3eTPG86m7Rdfr2&=?5}B z;=mNdfh=NL;O)iQ*;BKTz&9UBV@nfjEs_l|b=Hojl8!P=2T(ianFedU%o;k&9Y1y+ zhqB!6E@>W-0pbj#xv$Jh`^q^`vW{sE`o8X6@6A_#!P>J4j=n1cRXjy(9-ebxzbbmU zgcR1=+}-h(xPxd<4?8b~>8L-f4iRNSk)_RiE?-S!`evpvH%%tm%nI}>oN{KhnVGzl zrZ!;pB`dGiNa{QqPz(x|av>~zQ!Mic%N(}^HSQx>cJ$3W80BaRm_8WwoJWSF;3-L? zkOJ4r+xTvjVcS}1KgU+~S?hUDnP{i}KHFQluj#Q2W6D*zt=|{zwQb>Y<(Ca~*uPiN z%hA5@18GEYFy?6AUI(mdRJw<>ph2`Z_`@#`;$!&g{`AQ%ripZ4p?_PC z?Ow`EWCyWHvcqd3%_yMqn(WYe;lO!F39WSF-+V)S7o|sGi)x$GbK0X!R)KtW$JbvTbW?xS%#^0P5Tv$1;gK zZK|2cTLA{gFvM|0S97t!?Fhty#=)%)X&&5Wr-R!?Nm}M$-oH2jm}55wSd@7}OYlXg zIL^>i+<=sMLd%et)ayuf4GE=0)mT&#ye3J|9DAS!2q1mv^AhLR$&TQSk8}zm-Mwp@ zV#u!;`ZmT8B%`)uNs@>63#?vd4zhZ&nosQmfTR7WN8RDLJ_{9fg;vj@!h53q!CB() zP3emeQ~KiT?1q#R3m85P%Ku&hnV>fC$*7Mg1FU?n6SO|38MJIrV!ls-v|pX?9m!XJ zD769AU~Zv7bO9w8rs*n~#9R<+X!wG)LJ1~6$gj2E>v3!e=qbb z=$j5eP1%wfp@?h$-{?(!h(~BVdq>S!dXpc*pGoQMO6kp(l0staf(`jHXE#&rUC)4* zomQTl^p{JBxlY-&cRf|K_>IYi$C+|8H}t*IhR&u-p11zo!#cCW2iP+QlDTkY2($%u zTU=W(2Ww}uKaUE{PZ)`Yu{-0e)7#bb#FB1kX6N00NYXQxGDc&QgK0jCZfk#o zt3#QC7)C)c=LsT7BGNaW!#><}cXIwgV1`GJi$`mXM+%A2 zbjsYxIZ>U4KSxvjMzqP;&sEFmog4v!$$vIdenONdjIu)FSBNrieh9akL#*tH4gth~ zU^JV`@+4>~i@q5J14}o3TjE~?X3Fwpy(|jZY*~ypWzly^Sp*Cw|J_LW@1i_uWl>1{ zN>>)ct#V|*;C84hi_yHB2Q)xa{`Jj>gO>kU!P-Xw+f7OtOLh0&>b$nN0cxGRg{Ru8nYyxNt;Xf~DQ8Az%u`o;@4 zQXOro^*d_m4~b_z34J%aa8sZsA*Ux{yN;09oy>}h`fm36o&r4yIXwxx zzK6i3i7fjts`GnU%x1X+DI?VxQXERoJdA2c$R_$WJdElA*<7V)nTJsw8au1? z%&$nOv2)U?#-N=Oho_yBI$}aE`!K5Er4OUZ$79?scEiJ{4ljKe)eu)Y#DR58W%Wlj z6=Wd)sAdDI?QoTpNi7HsRiJ56wRUVm1vD+H){af6ws!1DYdFa(J3&)W0ZmJF`BYRu zS=0lQGUOWGP<7=JEX#iOqtXD9%)X)82!Dx4**8?Pk<|M_vf&jU8jdBKoh=n ze(T_q5;APOG$Fd%?!9()B|D1Pa_y3#o`4+_?mk7k_{4R#H6>iniA0AYKuPUs1>gEp z-FrKzGu8Mu*)h0VPy9)|)K@~IRF3ov5sNDE)t3E1X4!wB4xA%t2k?w*^e(=}gCMsf z`MlEfDh^llNT-Wh-9$QA)Xk{b9E0nOGFG_15GB>nvAXFQ^p&Xv)yHKI_y%yjGuq zIWxP5+QZQit^Qo#2=4?bx|X&2Hog-i2x~ok{F#@WS+X{Jk+-}sCB&PfzT{U{S-2W> zgWIVM`)4KZ1X<_+nQ3>mWoR7mT*UMZEsna~0nf!5zupN_z=Vov?*y6S{~_*8pyaBm zw&Ch~t8NWFq^pOj?oQHGgmiML>h2`n3?V=gLYTr7AYgYG5~e@`ruvup_sgIB&OudAptn>&58| zIgeH*+x_(;7jSP!l%pb@#N_2H-%OoaR+%XZYj>2Rm9}>^*eKkEhm-i$7Cs+C?5zXs z6x3CHyX0Z+i?u{>L})VW0Un^2BZ$H;?@(gd8~e}_t)An=6DR8t0v{}CE361s;8SGJ z_Flq5dj;nc%vyylZ#TxdZa5vmbKNkDZ>1R&Fn7_MrrB+U5l4nBr;K_Lb-U@(rc@JY zZiU&#IU~!>(b`TY<`dhLdHCWS5B0&688Y%E10uX81WSF~9m1fmuLEn2P4UD=v1eVl~wWWO-8$jUACu0e8BPWvF$k6~-i+sGAQw;eG^iMb6{)zQ~t z{ITt8gEQI_+g{)dEs}8cedm`TPhCSTqPq~Ol^YPfmqpu>J9e-M{WI-2a=;G~Av6ls zqa6}BF63ruRp_lUr9KT$V2=vZ?Eoje*PE9X7mVDBQf9e4rrNHzX0{eb#i?<9bb!~w zZ{JTPO;%(g(tI1rP+O|l*n$;&X0M9_;YBM~bjMQ&?>L1mH9<}u!=pXeT$^lOSMIm0 zg|@pGK^<=L<$n=Z68YSgn)y16V}hxV=ce=*;<-Y9DxN#0f6tlsk*Y?XEs=Kj7z8Yg`YD^-Q?qu$`!5O0?$o*SFDb5+~kX3vtPUJ>e{HQxxB=nb-NJ8AK z+;M_TDY91#L0$0SAF9q|@WThjCee$udtZQ`My3mAyZ~b4R%Y{)a@^w} zs$L7X59*5-I`QjK3jRGTC!jK93IEumi4?o75+8eLjuaPK^7I!>`{B(r3;|%;Q%!im z>LdW>L4s&;yxRG~&w~gDs)%toD0smNkqvB3G)HtGf@bStG*(O>_s*Iqi!xhFu!vVA zghdNaa>yeD*t4R#PwrTCLQg5X94EOkBO;PlvSjB9)C0ecYnc5ElViACf6(~V+j89U z@The-WS4Q|03~dGgQ#^hDsQcfqwGveY&sSvj%xr%K$r~)c}^waPJu;R=*Fb9(7jdy z4^KpklO>`gUh=Zr#7j>?o>_rU`tjfN;xj(KNXVFz{Hi`$YCWhnzR0C^%j4U4Rw)aY z>T5&}MseCFa~#+#@?)2x1**aFPQ-~7?{xSq*ky6}Ch`jXJ_2utsgIh6r7Th}Ya0IX zL>7w6PVk`@C?xqFuL-Cwal587%AqrAchDOJr}8s}WGd*Bej9c01lOA;YAxhY!YZd> zdvp5LmtgJyGluL@GzvVs#PzqRobRJf0gGFT<}qOhbNya$X!-)_J9##yh55xXZx6=2 z?1vy~={1se?pW<)?1X;JK$zY9z!r!QVZ1V1*)nd}{^&S$}*G8mtQemMzS-*}*N3ru7c*m1@qAr+E zV~MJGeAq_F;Gm}$geKB7UPR1Db`mtv__Z;vPf6SwI1~!^;-&~Bq%DpNp2Y4Qfxt)l zkSdoY)?Pwgzgb-5)V-EYA14H$8(LiM7)JxeBJoD@OJ2rqyJ{si#- zwH#FSS0QE9-){8B35ytz8$8>=F`x7k@>DVR1~`<)z76#eKy4ciNmD8q^A4D|1FqnN z6l*(NjSDLgp`BM&WtFZ}qeO&|v^#Z?4nMw71V(*72k+9Z9Wk0_aXE~d)1!+@b`2OHe|o0Dtpcy7J#=Lo4)cM zV3+dZ7m?3IxlLKFyq1+U??cNY2YmF=5%mZuYc+|nW%6@Xt|DF`S3X9gs|Dw&rLW2I zc0r>0>|9GBmqrsv5*I0S6GICG@(yuRR3(77!=o`Q z39wJHnqpcOCgJ?A@Pd7Is> zCJHPrvD(^nF~hDfBw5TDA6m@ty~-=Cm@A`M;#?VzBuBxiyBAxGxK&z12CUNM{K%PY z=2eF6SDB=vHzDnXcz*RdhI3u%KgTm|d+{XP+2H;oV)NtLb-u=hA}d`p>n-b1mT5cpQq)KEwJ3=q5XZZM z0$2rQ%t&-kUmLIe(m0|TuHDnZ0Sj;L02%}JztVbz(&5!H~czPa*q z3iA|wfgQ=COzE5<>aGRa)0dRHjTghL8a(yM500}IftG(->dL%JEGldJnoVufo1E~e zcKL(L-WVmHC(m2X50a zaJvB;T$ohwF%c+K;$W~n;mw83RvS)OT?(78-022fq#k&x4U3tVBJQT$|f?9OJOWd8|_nF}3(sVgvPIXS{M(ONFsB$?Dym(E0fmD9;vv~mVMypW_#ySEP0 z$O=xoaA}QVuHe86$vl!h9gvCBSxQFHSI$;5d!NdPdMVX<*_Ain&r!0OG@q+x3FRRtAMax7f!(`+-41vc(hHEYY*6YZpQ2Go@_(A27u8aUbu875wNzpqOSQF@FR_m0>s?YwKFW_+$F_3+O{!{{5bM|& z-J@%$#5$I0DXFSb73)~O&LdToFR_m0Yb~j&WkRfD^Knxxl~~78Jy9E@SjWcr45@m9 zCRnUv!+J9aOWJ#}jxG0pBbAg1p-OMR4mqFjB_UK|9UE2?sj5;H>sYCF*HVdfELDFk zl~_kpr7mLki;4D9j3=jPC%ncgUjmQ=)V27^bIeACJ8`Vr>y$r*g!S3ui**x_2#%+m z@}+>xP&N*(75roX#^SmBQggn-ikye=yE%T8@mp@{lB~X!#k7K_c1K>+pqhsJ5qKWd zbtG^??;XkbebA9XAH=g$Vq`tjO1Q5pF|s+ZG$uw)#uAy~jVoyzHQGFmhDDahLk1c< zM|LAm!lUF>)k&G_ z&Bn_tNm{BjBcq+T*NsCdC?0+xUI(+g2|tCugdfI|g5nw}2E{_v{fcCRa?@*d$lib@ z_sivdm*8cWnsR6Yt9nGDS>R<rL?9UZ( zVoh6>1!z@dT;hEj+{j{QaotS&>;|DU-wZA(f^Z%yj zXm~E?0!VJM$kg)Yk!4&fO4Sz+L4$f3OrDL2Dx@rBmV*G<6X@&Lm5Px!{k9W2hPu&b zWDGuG$ZtlW2xDmqfnAQk`ff)$@U}5tGBNKUJLZl`Q)KaJ{@I>r7KjJe+w;v%J*X4aT0XB{)%Mc>@0(JujO^ap)fHFu^#m4QoPM#d&+@ zQg3&B*nF{BBV-y&!YJ5#;UjI3mg_H$YQy$~Gs`u}P?otOAhE;D6#)qxX08a-v}Z>n ztvx0Wz6W_@mzm4k()DKt`z`MtfW1>pTe2dMZCl*$@>2=-7M30>>*xD5%=g=v?_W_d za+M)FNa=9xAurN_5Uzy##(a>20zySXVyr@Tj~dqG+ooEAqa8tYabM0Nf3Y8c<|6!&!Mi?bYg zHB^QavP~!(hL95vJLXyjGx6GhG>|CXG%dv4FMtL+_R_lPQ@AbA{)l?jn~O`q#^PLc z_)*UXt*$^4kH|L06Vgj03zw)2xuTSXzL07`gy>#ER_Q(|Wj7V+3-@a;!j-Zk6=cVy zshYe$9)4WP#Qhf7M2qWf#IlIXTxjJLTba44#da*H;R z+$b+}$wHjoqQ%z!JEqJIBCef+xU4cqpc=e;9V173f|HsX8?ZsW5#pH=EHl2#^f{uh zrU3uaaR_sz?}EA12p3SQ_WBV{fvWa~5l$+q_QnxTAFB4&=m^K!As~j<9Rc_5kCO|Q z_Z1kSFwFZZzIaTUA8hxhV{6uc|DM)_I$(1puBP}X;^Mv%%-2jXU)Nyx(O@bj7;%tb z#3aFlh$pOjoTIdiv$-c5-`vxY*xb{Z+}zWZj&AN5pN?(j{*V_8gb3P#&vpUc&O|?A-El9?D8O!C3EqEo` zi8!}ij)wqYX@}S^^@$u8q2@HSSV2#0aR_dEb!?P$^dELj>FA%W3lhS< zHtZ^M1H(5LK{b78lVZ*`{V^HyatJ*13lCqzAVYe_RIv|P7W9mWf-*4EnHCMlNIsfv z*g77>((^s7`CIMzGKGZc`x+v%_Ve>J8u=08oQ62H!QmosV-nK`%s*to9Ov1E7DtLA z#TE{P_?xXSHe~s06iHekLCa91DrwwlP2|4_-%Bz2k?a^l{5NDv;%eqg>Azw0zJNk# zc`3+yWDzpe@)}^&Q#~t@UGb~YhAC<3e@TBGx_WG-ejWQAY&W8EZWZFho&+)7a-j+B zqEKyz5l-mHhg0Tq_;#7`{)uAb6t)FB1Z&w``ui29`}-AZS-mC2W+!7s;KKH!@Bmnq zDFbd)!;Zu69P;9Xdxhg#ZfA1}Yc)9)b_&!-bS1udoFR-X32cz(hfCxf1Rc32lW`wn zQ7&L>d}&2MY;?DA``q=|ZpF>m+xV?@%MlbNiEM82&55qAn-k;nYZ3j;iEdDCxjB(b;@f=^ zO(~di&0?&lv4cizfIAp4syaMufa|z49y#_T-IHc|IuYPoNDp>vP=}sI8r&b_r=F*( zpQ2=OQ+Y+ki(^M>iWSY^p-k^L+&SVrf&JV-C>^CQA=N!2S3ok}W*BYn%LLrhkcj#) zFF3R3^OB$H@5MWjXAs^X>ty+L2n*hi$Eo;wr~D3V4Yqe2Y>mnCov`7e_}$=QRWz|8 zS^hQvr~Eto4zC_`A9^h+Ul&i4G^XkrLWK_Ze@a$rQ^_y;r;{( zwh}d9bU|WR@pN=W*2sa>mM9>ME=Wg*Rtzr}lC2GCJl2C&j@r>)#hIk9A{ykmruDSQ z5f8{F9O`OJ&Uo^?Vll5$jk#X~u?IEPsgxbXSw%`Y<_tI6vCMSnwWBTwzB3I~k|;Ot zp-ST9D%5d9flFsLE9wbRkbcIj8zpH!{*Fj;2Vd6F$XtZA3&Ij9rK&=z7a2J!B3#vu zYdTE=`9!8suZRHxQ>SU`j-;pgVaMdo#;!rw;Q*;bV|*Mho|f-Gc4cVzCJd5TIZ24e zQ3qa^a~npACK@Bd*2vUZe%XydYhxrb4l>L&Oa9{B2q%M!ZLBlSL}%g#tO@1jF5Pmo z)9rL`$jw>Xb-v33RTXj(pW9;KVH-p*nWutb~B z5;y$6LB?V5?(hxY^bOzg4d3<+clw6!_=dY^SOyi{tTP@7VP=IAGn6IUnlZL!%iSbL zl9dZT$w;3i?cke`y-DB8OrM`T<}#H1xxWIa=R*fR;G;BHR!E6<`Ba735B;%b&sefg zu^W9%PD!zV3yw3_^s;_=h2;f}HQrHy!5$J7z!19Mma$GLtszO_w67338z4CMUGQ|O z(8nT0Q+{kyd?X4D*uix?mZREu9KPK^K9p!f*peOE(0$_4=ZuFA!x&=xBVs&F`i|9BRkVhFtTBOT$nnpbkLFLzjsN#~}WUh-6IHj&!k)QV2`ZbXl3ppXjVy%JUK* zkkFLVL-BY%_Xn7_%{|M-oV8wV`A~&}`l@J#CLj0O|77Un4|yNEFqZpV-x@{Bkh=li&j zw;*Uq^_Vz0GWfV?E&Dn5e_0e5|E)FgcZK8c`u`jM$sf&IuKD8}JH$~1yd8nDA^ay9 z2hZfa0}V?xPrAdrcmF@)efv3*%YR&|-H&se{&9{o|FgXQ9g-LC;_%OwnznP&vbVVZ zLw7sRaly_xOC0R(lb5Q4Wy{Xm5<_O$xsH>i)&}m#&oGGvzqR(TP4lgKx6{rHpdZSf z=zb_nBk`qSx$F^^Ecmi!6o<%Y(gs zc}gpQ6D|{ulnEObj;pPO6K?Gtt@0mJceH(*hj{p>gmyR%Tg#pAVieVXWQk^YIxh%? zCv8PF&<1qQtPIM%@LrPy;~MU@G=%>cIs0?2EpjYnyZ4~ePiZ3yh4vh~Ll1QwM<=y( z-~AZ67~6fBSE!JCkP{dkI30`K1JI>Qe_Nl4XN=h6+V^wZL|t~f$sB-bjYK5ze z731;ud@Dl6MSSv$VyaU|Z%Q{ckcKzyu?3uE%}{dP!r$ z%~}TU9*l`&Ps1kOC9>t+(A|+%gxQ7|usGzDPDj4s`hnxN04dC~qcV#cit0Q`*HJnC znMHr)2N5RMICNdB{9AIXYc@6OT5T%ZUB~#_QI|6%@ZDPMgcuU#w-L_J&fy?lLJ(5c zSw3oc#+@Ils=&PTJlcXDKLOq^*fMa=xj+2vL7uCmGFnCh;{D?1;ZneA%rD$GL?&!m?gaArUGgSDp>PV*;J`bQW8&EJziu!}w;_f8WeS96lFKTC~BNWz)kR_?8v}r@|)4Qj?!|UUwH`bGFy(jJs^;t%o+GVlUDvQTzgS< zdMN<$Asq>!seo8kxGsc8o+5L}zmTkEq0^#;@d2ypnukyxN_BXhqw)Z(c%n+f5<*FA z)uZ%$xe3RtdsVZ1<}-+-CAzKsm$0{>GBDMZ7}j7#fqi55jZOy$wvaB3=2uuRJw*mmCa}CVkMp#}$YH=C^NOII;gIh>W5Sz&hD9jj|gajHa61W)?;cfjh5v-%o2`$M5wq>GxiPrAf&F&M_t~-gh?Q= z#k&J3>fO;PV|OQ-xaMBeqL6zT=hdQ#8!8+VO5M-R8h8Yk-g}(n7Vi=I%&O0%`qUK9FDlzlwwy6|HVN;=*VMwlD%E=AlTC~+HtSC;MQlFTl4N3pJ}G8aK}w?zgc z-Z;_(wr1KmM*Rc^SMzK0~9KohwD zG-}ZM_^lYIZeTL z0sgt~$i8L-|Ci&Rd$pVJe-Hkj#Q)3q{{a7WC_kcSK@!>h4|@+4<$Mm549#{o(-Fot9J_! zL%c(v;{kQijMZ7fL+HGBlJ5ll!rLr*Qy8{h4Km39^K?-{*jixgjt?b=&^1dKz{sJo z!uCFFU2*#S9q|q!^J513EYb1GAHo6hFpv(^H{nf?JJcru4l%0^pP@si07Cdl@!A!l zI2*_W6DtEh0roCG!LT0=dlKIR@%5R@wFPOx&KAU{c2MC!9Az6~KOOd$4gCEBxo+ju z4u32J@FzUJPP38V5WbQc(ENyAjCdw0YMC!wzYf1GB!0u+%o_$dSQO%kdoM1r@_o-2$lNvyre z1caPGIK?t2ZY+}YQasZL+{*2uso=y-3q9s-V(2E_zEV_+v*Y4xH=kT=JNaP*)ufoQ za0!%Iz-Zy!(R*|0SlW@cI-RKCJW4dMJC%*F;>=-y$V$NCp;Q_>6gZ6N zGw7ST6I&Xcr1nWoj`lw4b(7!yyr$=C*#Dx9!kR*<6N&8c#^YDo-PG1rwBgTi@Y{z~ zhq*5071RH0-0f{=UD`brJfh~iIq>q>50k~nsH9ydBG~r;nNiBWxweihU2~YlTrHm zCm2fvjY9u8-{p4BMvHaX%4_s%P(Ee9t*)|_kUJghLsPf>4)GU{5yL?b^E_916K3?e zdfo}AiZI4!{N-gl)L1QE6bFbqE=7n{EO$O$fr9~Z#tPW~KvTWbLG^c`VmPu4=_u73up>mm?h<&j%0y7GnQuH6I}%-t8{!Ry z{MSHD+Rg!Q{L=*3GJEcc^~Gg@qnM4!oFZ0cQ5VSF6~PZ_4TwrQL5&kyJQk5>K@);v zV@$@tFVp7$cac+JKsRb-0~!kZ^J~F}EW`FZdj{uEa^+aIhoO6vrL{Mne;+i( zSpE%sp3|~oMQ(s)0n3Uk6S-SiYfQOeWq8hgRS^o@H%p0KjuNZnnVJu@Zy-5B+F@dj z=JJRZ3!{;x&q1zIDEDKj#sl<$rE@R|A>@@t{TFV;d+EZueo=&(HN2e7FRW5bP|k4f z1*4aPn2sQ|TslIu^@uh|g%t8%qOAH!VE`g$Kjn;%4^pB@q*2^7I)gH1&6%2HOX15k zdn=H5EU>Gl?_CfO8nYRUP$a9xK#YnRQBzN~{?|qNBaz6#)xLt&a+IEdC@4^s@Th1f zb~SV(f^EAUnGckINE!=CK99=l&S55~#90|B@%&sAZsQ>JnGQ72VV*e1JoGYzbqILT zvxwN_`7LO;$urJLKyw7Og5eY#v=%1fqU3YnZ7fFrnmKGs;Z>pPQjTxtsKYmpDa3(9 zq>(d~Ny)LrBCT+A$Se&7=VpSFLC5Ps8ces{xkz+?FEjGc9I`dP=Yawzb+lq6u(`nk zfFZ|9spT9aMk8yGe(rH0Il}7R@MB9`lV=~gOE(;t9%<)2Htu0c97Gl}-Ha>dmDU*+ zP)?&YSU891@emLOxhZFbQmh>OMNKf8w^yRshc#q|K*O#+6U* z02OvexaIK}x@Xyh^E*P$#w zvdpbA%4$ZKk16nF4u{=?5e~Yl^~;sgR3%djEcZY-t7qYUqU2Rgyx0}0o2YA*3&>MT zUAL}I8e7gRLHgE|u21^bdR@HqtqrIq zwhy1XefWI9y?l&1GsHm<+cBPdl`*O$G%77NHeHb+_CdaEq`i)b%%sV&?SrUP7pDw) zV>CO|$vqpaty%6tl-r?91#IG~HpUf=^dPRokVoc>8un<%IdMx>9&Wi=mb2BK(QtUy@vrHqwkaST%F*kQSPtcQJi^sLjkZ85*rmnNT~3 z6{_Db(dv>jZL9C&&(t@dqdq@ao&sKOcG|ukr3|Ts%VXxqO zDU8eujDImiG9l&!cW^SU;T#CYo}qRR%~5OedAgPR;K(> zfazOAJk25r=;+pofke;IM?Y4Uty~_xRzC7Rjw@3AxyqzLzae^Iw;7|!=~%8EiVq8c zVGZ@EF0!|uZ|-iaL+LCsi`_fA6q4st;%8+#a`=~leU;6YEL^rO+tjI4p!7C2oZHt#Bi zJl=AT#n#TJduPI1+8L5dxfxu=Ju*}U z(zq?h8@a5(t@SPSFiK79#Uef0)e383I+d>XVj#c*nQ>l@Wi_0%$C6$=jqQ%sWExEs zS1?SS9Jo0R>Y;ik*BJLxEj{BNK!l;z1}E2)Zpf5A#N{DxIa8Y(H_F~zW5=mi^$MM+ z(}$oddE8L${Uwdb#Bgr>P-`@S)BdRPp~54Dt-d22lLmdLh~+)?gAK@B6XF53>9t>M zF@=IXrH~>!Oei&-Kus{=uAnv;b`G_{l=bC+|YPXID#OY*`Ed9EHq@A(ktz7oChLz(WZc&V^ zoYATZjCoO#mn|^Ip(0p}h@c%jKZ6Q2h6}Q?!c8;QZ5>$_j?do&)^()=@pEk?=Pn+S zYXwV@l_q|+4;Nv#%FZ=-@1Xg!J)RxcU+EL;F%LKa^ty|UL-pF(t*rg6egsj-`X6@w*o4c{z>p`WbNfptBjmMQ4&*b4vNtP>*UapH0ksji2NJC# zx1x!+3WvsUVFC`(*idZQ5|;%XgC-@9DhXsOzP~IUz$@2BDZ4rBBSLOiu^hk}MsGrw zRFL@!=v|8ihV&W+BWo@UgX6m?_%<>97zZ&Xr%F--Fz_Ls?h|&Dh?s_>@5X32eBsh@ z&thU^eFm4s2*v~g>2~oMJZ{w zGkUf!MWe*H$hwoI}k;^9_wdH;|%*GahWxua?`;{ zWa4su7HjPsv+{hPq4P~^sd zeAC@w&^K7+I(*$Svtt&|GFY`%JFw!WjwD|EL>`WS)qq z)%_$~@CGe@QFs{#*Yp=bwow0peF;j?*@#oExY&FzG;(4SLk+?J_QE)tBN0Z<&k2t_ z!)E+Lk$m8PobeyW9W@-~b85Z5sAX|a_&thoui&J@Rqvcn^mZgP`sRd(bARx?B91#^ zCoc6z|AvL1IfWOkGD}nWI&@ojrz&JC%gpLiOt3)%z@&XI#D6sFn($2?igI_nH?Psl zz>Fm_E?KOgoCoobDh>SHZv&1;SU9swomI*ZXK~&&h#fM_R#>W>?9wg1tITr)SC%U1 z2nk%JUkqGX1f4Fp`gzudxKy7g>yxa=;5y4L(AD38Jh9nN@%#ebTbSsc%&Os(BfOM| zNpP2o&Zy|&*d-?3JXL}L1G^$@R+Ucz$I^}9kP9?yv7>6`ZVKH^2VMLeLTlm7zxywiN?XsYqwiqYAuG?7qf5jdoF&bocrWP9 z93J^T!YVzE!FnYQk#J3g&5HJmY}a(&PdD6`^_~DBTL--H1jPFxtSG;T>;@JI0d2>7 z5-_X!xH=cRMk!?sy%;&c1MrM=jpberr_zrYbAmBvwLQ~1sPVHNX#AvL{7(h(6Y+j* z;xCK4<2@}A%bnv#;CG1mC2sCU^4BIY^>{xKZ?aLGax$4s@|Z=v_fxO%~);iooSirf6wwhYeHjM8H>J+k&rb}`(GDs2I2PiYhUd(Xp& zCO#i|H4+)le`q6QlKhW(PYUM!FF>wkkGa4?w;7?}-7C5~-ivVNl?HPygjZ`oVuM7|{BdQ;geO^| zR6l|lG`_;CSks9-s8YiJ-l7!Wc&LPx%@yZky|rkNBm5m zkjM^16Wue~61gVAxf!WMZfZYFeS=V}Bki7sJa9KgP3&)YYw@#Wo%LNRB*!rv_Z|a2 z?A{g(r!eFX1~V&WKo`=s_ET{PAzlcs2g`6nC>K{R3hQ0qs%Cl)NpLf@JRjfe3Y%TR zlFSM`I>3t{FF~jnTfB@9FUD7XsrFa+iB*0@7?&<8uPXeS!dv;l`GMEzyb;cCsPnJY z`Ay^emV9HC-{33S5`Ie{TKOG6vC8koIa+yJzIZxNzE0&`d`(}oALPM5MDYi@Ml0{} z6RZ4DXrq-s$v0N{vwWS(`|^!fK9Fys@)!9gD}Tkeut}9+N6TlxCWlKQ=JJ`aMCDhY zKz|^|A`f%SEaaGckgy&d0CzOK*Rkdq7js<9CluD$<(JVSMCEsIoL&B<*!YY3nkmdu zcg0UA+-sL#6$1VaPPEIfiH*PXyj5)c70*X2wNjm+&L<#KOHg%@s+@$JMOBdDu#Ei< z1MfNV9y|tBCJieY6naP{8$C{b9c=)Xd%cHHD4`vNYr4?esNNh8>O9zyaxC13u-}wE z+pdqB@p58AFRzBm^`qi@(lY5#7!P(_f;4c#!!w@ROWB-E^7N?vWe$XKX44-M6Z8{; z63c_BH6@n!Bp+a{0S`PIaT31Avc6!1z+!I3_bYSTRxCLa>g#qkZ(+qdj+HwH4Njvh zd14g<_YKfbi?8Gc^EEe~Z%KAwp=5=#BEE8H;Dto#e~@^jK#pfyNNq)+Nq)p6>_T&DzN@waA^Yb{ieR4K9 z<#a;rWJf=>{yD`Kr{g53V=!ljc^jgjYAS>$JHkbP<7@mjB;YsE*+02BL-{}ml?Tb9 zaMkU73Ou9#1six4s$D~Ne?qI#fMMi=sY|r{H0FXBS7VG#VV29V_F>tN7EIyz@h-&* zTZIlG8eS)O4MByn%Mo|`rpMs6bBczrzJ5VPF=3XLmMuyxEk$ly1pN zJB_dP)=WnV-Mb(}%yh)x)d#DG7_LNJjmf+3*$?O+2>a@T6#pm9hp3rH_^)0l zW)-2kg#yRU8?S@~76$7+7j`ig_f>%I^Xj6OXT>6A&=SPMDxd)bK+~BcE?3c07-9}Nnzd-a-28;VBe9l~~bg)5za$g1~Jh1aid}Wb#RNE4Z z%m9DVwurx6!!aow%9dMa4i=LB0Dq-z;27rje6#xsOq#w}gzwUcf74J)Y3@EL*MWc> zt7luBrCWmtTS8$(BcDSUm?UG4Kl3UWquz&zapIEF9*`y$;?yo#;q?RJR&XD_-ZK2e zgm_3@r;BTterH2JxLx{Pfnt;FS4fY^z-vhFMdBFCa8bsd<1u@|6z2d3;CnL5qPIK9 zM9)+fif^Z5(TSxtR1wa(2&KuJ2`WBdDKb$G2M8gnC}CWZmAfs{gJ>Mp{rpg0RX!4X zMeGxPEqn(3TzL_3uFcd!?psy5)#&!nd?<;#RWpw5?EXm0DN?UU!Zn%!B>WL%*13NK z?^r8>$|Cm-c<^By>bG!rGLCCyuLIVl8V~oiQv*NbxGyI9<#0$BZSZ_>=4R3Fw$GS= zh3%?cq)_T)k4zf7ye}!6uy)e7H;5sVpS>VhwFjfu#2s;>QRb3n@E- zO!_f4n7vJCyJMvZz$!iPDT`?8$HRrH)W8qya+V=thF0vOiV3m3DV2lecm>k3Leiq+ z=+f^{TcH)29b`kI6I-Jg!6rNVrxa)6$Q|eEP0=-1p`W{WJ@PP?=s0PS6^|{5y1zq^ z#V&sg8<&UdeoM?;oG`=jIP#T!#kGhRt0NfuuwPC=;#^EHm$JnS<)v&-7um4|9#{OD zOrs+abE=0ENCzkfB;@Vw86rEATFXR?J%OnzivcgWJ#zvQ1b7cF$xPmC=97j5_cb zD5ns3{MiC)T2rt;Ol4YF8eD$0ZU!U*m~y5%R6=u2)B*9WV-gfr zSzg011>3^Wc*cDf0m(RVD)_pH^M>#^gjI;u#E}7sc*&|4)HgeF75uD3TF}0&Y2q~o z>5dx`6PMIOO)rK zsMDM(OB~Xe#^#hc(0~F6HZpiRK$rN@Ht{-6R!(+Q)^d8D1eI57DBv6OH&_T{oa+c?w#@-GK zIGmlj%VEJH)rjSx=XP+e!Fw4eOnNb-U4@X_WD$z(SWNCq;9L*-BeGh?kO}vVKvTx1 z6gI$HA}w{^Zx9nMyx)OVGqa&{N$0k@9tgC0{>tTM|_u+AQfI*YQ9vw+cqWOY5G^0OnW;0NcjkjIoosuLRr zS5h9hqu0E23v42tSiBn+46&sW zP~!@_%Wg|oSR7q4X#pU8roNGZEkVPFOu%|{s_4%Yi{m*>#6(aQ2L7A*mvsLJA3Y^M z@aw`en4jK?AhUx_+^_ly<0PX6+HUi0wNC64_s5wwY&c?U$e^JISGunH`1nDN5IOH` zNc1(ud(je(gF=mU$kD9R6^i^~*N8=xx>|*`_zWlG?pKB9W;h()0>G=O&FemWk zNe1?QXW{=Dn17A`nGe8{IOpdWDI%q2JJ6O161Za8hPnV}hj1f0nrV#{J1q?E z#&;r}7~?ykzLQouS?jxNNckvOiE}XAu-tzj7GM1uuw#h*GlYf6v@l^wBSaR$aGTw7 z**UsWbez!I3bbk5#&s3t8fHYYB;C2ji+LDZ#KbvMz>jnciU)6)+Y#yl!&m_8@-vLo*%F70QmnJXUW{`O zM-~ShZ-hCFGRMV)!tu7A;F89d;|g1b73^HTgeDO0QEGPH4`S~Qw&i%tTOqs<5#7on|* z%6tmj@UovTg^J138e1<(!&?JbLu=zsE8VpnNm%GVw?UXtcu*`t6Y)l_$3TM;C>)G? zB>ky$yd~CRW91RE7L;3*X8a}wp4E_`ZU@wAPDf>7*QD!M@P;!CejCCy0M4K0Vde`h z=6tM`^L_c6n>{A3k-3Hw*;ar50rE$_}>2r6MU!;6+BqmT)rgM|?)U6;vdVFJ|);8{bPv!5plI3J}8zsR*9^bjWeoCl8iG19Hg{B@Y~x9HX~J z#3UJ^DV=k^E{byOI1jvySrhFl^5Q-FAKTlFTykP*x~#n-f~jl{mJ&5fdk#A!&)^ z;TA+RLKZpm#*;Us!~TGd_dnyYbG$`g9s z@+O4GV^1X~h8AFOl|- zKJA}KONg}cC9N1hyP33q_G#ZIEg{m%m$W|cWjYWL11N6w0WoZWqC*TU;LZdZZRaF4 zMiN;R_Vm&N5L;yj%*q(g?S3d?0PqbT5Cecad_W8UzUc#E0Prmz5Ced3`+yh#-01^i zs2+L|E8M?B_Z7Yh_6n_-6t1H{?xIt-?Vd|9O~SgxdA{L%-*AC%xX?GO@(pDgSVs;- z()owk1lP9krc?)dUPdJIo2d5^I!X7FB=<>L2U`tERQAc-OX&&@R`ZLnwij;We-5|l zqr$B)TqbdiZ@9=eto02S`-V$=gYZmW!rm+krFk~o+!IIuh4pZmGs?dADEr(|_Iac1 z`;4;hJIX$PlzqQZ_WeiM4;W=XaFl()DEmR9><5ps9}?IlPk0_l#&Lc1Ba3lWtc0l? z-t2(ww7_PSS+H!c5p8$MX&*F{O|W8gLpLYtjf2gMgAVw=6J~bEg!(6JKQ^IwF($7W z@eI_D%fO~yF3;^!)0WlmMv>Xf) z=g%adDoQI*3C+~o8}Thy$F;X2y(u%4WcyIBYXlr6`~MvM(ac*K{P*p|um};*v1jD} zB=b*q-&~yR;9!i5_c^-9yE|B^E;!xz@4|lv{xRWWX^7=|Z2oj5Gc%G-uGd5#Pi_=C+2g?@Km%_S`<>h*pE(K5`!96l zVA-I>MiYy{mCx&}k+rCxCJpv#W~M%CWT65pTsUu>F7b@Vl~5ecKdZC@E4S5FIvdF^ zY-N!>z00rjhBnvGpYe_Lwf=1NC)MVPpmhMT%wt>-Uq@6UF~qMhlCLe6xN!I&(rbp9oO{X@PiK9ul(xW6V*0y#g(B2@k z$Bpu;zC@xohcjD-1gY&3ONqK;3~@^}+ZsRG-@{}4wO0K#ZPyS)A!@J3dRKRtB&qxByea3WZ=a8F&OtAD{RZ<&0wr}?S&C;@7`F- zo(+T7#?voj(=T*7-7dd~mVDqXjtA+F>pbGGU1)IVsK)2;c6@@rECL39k5X8(u{zZevTGm1 zo{DRovPLC~_BhtG5vOh{>{)H6B0a9s9u3+xl(Q@na#2e?fV{8EnBlo0VLT_)vm@O% zR=t|y#vv{ah=YM64(Y@hhsC?_!cP#it=YIK!555Te*%Bd7JYZX# zVQX5%2sRq9{lbXFKQd`Ea?RGz@CosPb|$h`(n|r#1{MNEaX1q*EhJyhcCb|CaRz}W zJmh$XE&&fx6;LPhU-vllP{&J!UDq`67^U+ zODc?n&#(j(jLlO1mu#spPAgjV&$umIb`HqN1c0i4auZ77U{=m2XsWEUdCc@yJ!>k5 zPbINo7?tg-taL%yxtRHXF1>I8-oA~dlt$o)?69yXp*Zp@JEm*Y-L7%BtL|6TxVNZ( z-<{21mX)5vFY@6;&W21c0Uvps+Vhp&Ek^?&%I;G6U%`1DwE5tG zj=#&{_cY$LHQ+7&@l|dLy)DHjo|NP6s?1&xI6bKCp%s~#X0Ape`CsE_9VM`qCv|f< zHB*u-aIt(W7HKVg3w*Cl3szTG7s6Tuv#eOYE*5E1x>mt#JB+mn7LA6ncEMt?FqRR_ zal%+uuy{O-bqJP7gt1P+lF2aEC0Hs&tj?rkykPb9VQhk64Gm#zqF{}UVXRxQrY2ym zetL6)jTl19^#4y$`Sa)|An12)VDU(&Vmk}gGZ|Q{u3fQR1e?+$m?;~(3O03$m5)XJa=)8k?o?vqC#c_n>qzKf!j}HH_^q z*v#D`c{FGy9R~=u`%D{{FM|UGo3(owTOimTvk+dym%%}T?YT!7J6N#2_6%c(2sV4K zFm|Y5b7qIJ!vvc~O*6?H$IB5Nw}$VeCl3=I;~6@PIYS^S<+uwv?aV zqXgS;UzR`H)Ze28+kd|>_6flb*guR733lKCVQg5i1qX()#eyBQAdDR&*ue)0X6g}k z;K1J@2Z!mf6$k9lLj*H*3!87i4m(sZQ@54~w(u~)Oxv_nu)`M;iL9inZ4`U|^ zcH|LZ>?FY!9T~<>7VM}+#2gdeDS{n+6tRTCmI?NWqlqOAcB)`QpCE=c0O`w46Kr@W zj4c;z@o*ShA=ojC!`SJ99eYd|J43MJjtygH3U>T)VQi&fOO6j?o?uItgt4;(J7H-U zJ6o_5PY7cpf}M0?7%K^O@=0Or9KlXGnOL2X!MTDhJ0*;rC)laW1T$swe8EmTHH=*# z*z(iD*oA_vST2|;SE~d&eT87A43z~t<8;AH8CosanP-H*PDPA?IxG$P>{?303>Q=;FL!7df-+;apo za=A>f^Ue*Y<8r|+JP%ky%FumEuvO`JFm{7rS6mjxZWQdw%fsP)RHhn&f z-67Z)ZYI`b!uzIRU%Z9bID>slurF;Q)@-nE3%2`}p<|4tZtOt2U33S*B8_KUm2*b{=icn>kZ5B;HFFMT(R zJt^4B_lB__3HHnT!q`)Sy>fpT`>|lZ`d%1&TCi6i;F#JUJN`tl*B<0}vc;5_p9;41 zA&#?s>}P_#{(Xk$_Y2Pm_Qu1+eA)k;*tWz=LEAJ4P#pbvmXm% z&kGiPJdC{{SnP=~_6xzB9|DW|@xCZn{7GVd+w_uP$sYl0^4t5D1xr08nBni2g4O?+ znBU&NB3Q%Iz#4tOzY?tRCxRKjuL{=mQ)0f~*905)Gho5^bgN+LXP6)UIQDhHT7DkQ zN1OdTdPA_*XMqLz_G`h~o(p4d3f8`b_16#YEx|I+$MVqzKfK=vmVJS|#7&<6R6I%hIQJg z+=2dpX93+doNkM{JIL?8_;tImsE1Wm$DNO*Xvcd4>wfO{xcGC4PrM_@xbMC%2%_>@ zi4x3;#@v1!2eL~Kk$#y~{uAO8B?DIZ&%O~0N;u77mX_ZGiml5(%12J{SLg?!tLM_o zh^s=sg|5=`vIHe-Q0uYu^GR8|ln}}cKvd^J)k(p2=fW3OZLvg#vrJgctjE4xu45YP zxX|$f1d~7F$oWU|kz1q1q#@pw$UrO6GOTzfM0bf*X2|kZV0j+2I%ER(7CYg79h=cf z7Y{n%oDc3hxQ`&rEcG#Lz_ZEnWW8nkkIdWVY54*!ElWa07Hak`#VzE@?{RZM*Z6vn zu1mSbS1N&Ro=SQQA>;G7exA_J5AksdCt`!0qJa_!EWdd;5A0NUk#n@e`E=k-&e0B+ z(BUXLoTp*bgeR==>Lzq!xDO&mY9AJVZDTDfv(u44f%&EMu1?ks}8<)gs z#q+^6wnu5h;U&6xPtwBu3GRr0M12__t}pHu`dG2Onxak!hv9M8{8N;hRhr79Wj5;I zAcR^Em64?v83siCSFpfKFXBhn|6#pkg^I8wZ?r_#S8h?$z59L^@n_4BNOgcVMS6(Ey0@ao~W&t zBH$fXMIVJIl%ULalXxLS-alrW{uFq>s>(Yxv0^i?Drl-2qoOnspq~c5AES4~G*MOM z{(_p6;^=x*H0{-AR*3$INmL!so8hmj`>Ri6SEQq&>94_G(C1-^m!QXs>I``!WJ(-}As_KZY=7-4|+{lS~pMzv74)yg^-M!02TrB#Mf8Hgq zYaP<}%RkL}7wY#)I9!@aN$-MY>N(`bIWM4v!dqaaH<@kKgEs$#Fj3+D8y{4er|Afp zk4K$(9p9@(_H^`q1t;D#mI?#Kp;|L=KryH}#>|?NNC^k^@e&`)>d77A{Yt(I&3C@} z&XccICKn!Gqh9WbzIFjJE9Bwocvf3TY(kSPX_`siE6`@LB@$P^QY$*-J=&g(RTj2i z2HTC^UpNnx<9v?7y{NdA>3pk-Y9 zKX5Khr0MT4jcnnOfuEw5to>hFCmiEj|3T}r!1_;G?+mQ}qV*qv_1~~&N9G@EJiBir z_KuPDHTKStmuu`@Ba@B`(~loHqsBgA0WkdoN_ggY6lSEw#;D#v{eqK}Xzi z#&}yh6|y;nhpjafV&KDCLm?V#N5NV{AsTC^3C|6ON8bgj10mBRR4&0pKcP6-ceTRL zI+S%`o!3b6;8(_4y6-w3?(69;$$|S0bPs8cB)TECjp}6tj`!;&w zrGM@pM^JaQ0=mB1=LJb^7dD2HJGjLKaRXOOk|{=@*F z-3P<~AmamKm~B-R9GIgrRB^zgGW?b%A}dl;2X1 zRNZqmLy0gCXY$KD6hpW!?^4VDJQAW!le%tKXq8m%R!g>zAD$SXXw=;wc?s!=9TCp= z3B-Wr1_oY^M#h5s1M2A;H^nL)jj(!B z6#`Bn)m1prT5|x*%8=v+AulQq%wG5Mzq&gsxq!<8D=Z^ql zSmSpG8Vrfh`bjq??wku*qGR(~ro;3_+B_;T6zO2xL488dG-Dc0<5lLjl)(m(0d*Rw z4DMGM5a0}Z&A~8;01ER)+@)rmw3aB7a0tIF3}OIqs1JxCH69mg)*R*sVd#*z;yQ2S zydXf*Fu;Yre=(#cU>3OM@Q{Cj=Z!oOc%&mea&d)y(UBxRzgnPaXMyIoG(`&Z1zK2$ z(B~q4nFcWcILZga02#5LnT4<1ACvOTwxoLa8h#nQlosqnn6?k@h3vZ5P?9+f zVn%It&u6DHJGZTLAq+iMgbVpMg9uCdi~lCgXs9z2)M}zT@>HpoZeqgf|Ta zyT$f!O55qp;s|gym8>r|#gi^nKBju1|1Y|=GvQqeOW$)_aYq3&WLd$A#t(N2>8M%9 z%0>nk=p3s$cpCyAmb((2q37YJve@utML6c>Sj8%nCgtS*-4C_&gQ>{YxaF<}C$IW* zw=@o;M0kx?bdOQdZd=?~XJY&g&r=hP#c@t;Y(My(K5dqpD8RE`7P%tr}X>|g?5_-=4TYPhHN4p3X zI>t2Q4ioa$#Xg;(61o0N6OD0>gw&>-38zqAfrH58Svl8Kcr(ENoSks#G?SvpR#9Y_ z-S0gC$^yYV|C%5x{)_NnU+D`)*z1KlQ(=>N$;wXw$ee9Y(B2TpIJa#OFAOo~su?+0 zZ)H@zsbV}MrH-RS7P|^%ET^v5f+aR4?f_U7!v>Ur!W6FM4Jwp%uO?BoFJ4L>sAKNy z;NeE_V9O%8m&KAuFB%A2pSA7^E!_4t%EAT${Sl}1SmnnE$$gJ2-TlV0KM;_~x-Jxg zkt_oJ;fNXwjF;h)+B$p6RwQu0z-wz~t$R1ztuoo`O^>vk5IGA903f&0r{H^4n_Ll! z)Is*pARlR79P=`Bh6Q;nQ7_-^4X6}Q+GH`X-$(|r>ah!I#qS5b`k{+Wt`fqGquNY z`|M=vJ}{pvEJm57DkvTt&%zHoQYLiS`4bNpM|)C&y^bn(=XO2|isU2NQH{~<+jIRT zf8T%ckB?p6lM*kEyZ;RJDzz;Xrm_uM%n3Pqo01Sao>0%x@Rm&Z?u3Tl&y;`b+|u>F zh&cbPzKK4;U3&Mzx2Og0{}UWBr0bWW|InX5^QWzTF#T*eAN>VS?TQjc#X>G|m7+r& z_)zp{(V@=0ub9+f&OIdeByPt;&nC~esog@Xy>aoYC%lqXh}ql^FDLIdzxG{l=c5l1 zY#HnkF_RBhfUmvK6RzYtS}OPvYLQaM&eG0c@lGH5^o+<5ldJ#XnT1ms|6%JxxKGdc zzrd}zS9T2tV||L#flL44RC`|S7Pa%0A_qG#Z{|DP6SCt`qR)PfpddsQQmU__1e?M) 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Ò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%0A)8qejNJuch(6j+J%(& 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
q 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 rp{E0J-y^5J1@}Aa=>I!*w+Q?fD5dL> literal 0 HcmV?d00001 diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Ignore.dll.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Ignore.dll.meta new file mode 100644 index 00000000..20ac4ba1 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Plugins/Needle.PackageTools.AST.Ignore.dll.meta @@ -0,0 +1,89 @@ +fileFormatVersion: 2 +guid: 85aa172ecb046b64a8f2e13f6138e880 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 1 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs b/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs new file mode 100644 index 00000000..a22ceffa --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using UnityEditor; +using UnityEngine; +using PackageInfo = UnityEditor.PackageManager.PackageInfo; + +namespace Needle.HybridPackages +{ + public static class UnitypackageExporter + { + // This does the same as "Assets/Export Package" but doesn't require the EditorPatching package. + // [MenuItem("Assets/Export Package (with UPM support)")] + // static void ExportSelected() + // { + // var folders = Selection.objects.Where(x => x is DefaultAsset).Cast(); + // if (!folders.Any()) return; + // + // ExportUnitypackage(folders.Select(x => AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(x))), "Export.unitypackage"); + // } + +#if HAVE_AS_TOOLS_PACKAGE + [InitializeOnLoadMethod] + static void SetKeyword() + { + const string define = "UNITY_ASTOOLS_EXPERIMENTAL"; + var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.activeBuildTargetGroup).Split(';'); + if (!defines.Contains(define)) + { + var newDefines = new string[defines.Length + 1]; + Array.Copy(defines, newDefines, defines.Length); + newDefines[newDefines.Length - 1] = define; + PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.activeBuildTargetGroup, string.Join(";", newDefines)); + AssetDatabase.Refresh(); + } + } +#endif + + public static string ExportUnitypackage(IEnumerable packageInfo, string fileName) + { + var guids = packageInfo.Select(x => AssetDatabase.AssetPathToGUID("Packages/" + x.name)); + return ExportUnitypackage(guids, fileName); + } + + public static string ExportUnitypackage(IEnumerable rootGuids, string fileName) + { + if (!fileName.EndsWith(".unitypackage", StringComparison.OrdinalIgnoreCase)) + { + Debug.LogError("File name must end with .unitypackage"); + return null; + } + + var collection = new string[0]; + foreach(var guid in rootGuids) { + collection = AssetDatabase.CollectAllChildren(guid, collection); + } + + PackageUtility.ExportPackage(collection, fileName); + // TODO return absolute export path + return Application.dataPath + "/" + fileName; + } + + // [MenuItem("Test/Export package files")] + // private static void ExportTest() + // { + // var dir = @"C:\Users\wiessler\AppData\Local\Temp\test"; + // AddToUnityPackage(@"C:\git\npm\development\PackagePlayground-2020.3\Assets\PackageToolsTesting\AssetReference\TestMaterial.mat", dir); + // AddToUnityPackage(@"C:\git\npm\development\editorpatching\modules\unity-demystify\package\Documentation~\beforeafter.jpg", dir); + // var package = dir + "/package.unitypackage"; + // Zipper.TryCreateTgz(dir, package); + // EditorUtility.RevealInFinder(package); + // } + + // [MenuItem("Test/Scan Folder for preview.png")] + // private static void ScanFolder() + // { + // var path = EditorUtility.OpenFolderPanel("Select unpacked unitypackage root", "", ""); + // if (!string.IsNullOrEmpty(path)) + // { + // var di = new DirectoryInfo(path); + // + // var distinctExtensionsWithPreview = di.GetDirectories("*", SearchOption.TopDirectoryOnly) + // .Where(x => x.GetFiles("preview.png").Any()) + // .Select(x => File.ReadAllText(x.GetFiles("pathname").First().FullName)) + // .Select(Path.GetExtension) + // .Distinct(); + // + // var distinctExtensionsWithoutPreview = di.GetDirectories("*", SearchOption.TopDirectoryOnly) + // .Where(x => !x.GetFiles("preview.png").Any()) + // .Select(x => File.ReadAllText(x.GetFiles("pathname").First().FullName)) + // .Select(Path.GetExtension) + // .Distinct(); + // + // Debug.Log("Extensions with preview.png files:\n" + string.Join("\n", distinctExtensionsWithPreview)); + // Debug.Log("Extensions without preview.png files:\n" + string.Join("\n", distinctExtensionsWithoutPreview)); + // } + // } + + private static bool IncludePreviewImages = true; + + // TODO figure out a better way / find someone who knows which assets actually get preview.png generated + // derived experimentally for now by exporting a giant .unitypackage from an entire project and checking what happens. + // reason for a block list and not an allow list: ScriptedImporters can be for anything. + private static string[] extensionsWithoutThumbnails = new string[] + { + ".shader", + ".cs", + ".anim", + ".unity", + ".asset", + ".playable", + ".lighting", + ".usdc", + ".usda", + ".usd", + ".usdz", + ".asmdef", + ".asmref", + ".bundle", + ".controller", + ".dll", + ".md", + ".xml", + ".json", + ".txt", + ".manifest", + ".jslib", + ".java", + ".ttf", + ".exp", + ".usdz", + ".mtl", + ".fbx", + ".fbm", + ".pdb", + ".usd", + ".prefab", + ".assbin", + ".mm", + ".iobj", + ".lib", + ".overrideController", + ".so", + ".plist", + ".zip", + ".7z", + ".unitypackage", + ".ipdb", + ".url", + ".shadergraph" + }; + + public static void AddToUnityPackage(string pathToFileOrDirectory, string targetDir, ref Dictionary guidToFile) + { + if (!File.Exists(pathToFileOrDirectory) && !Directory.Exists(pathToFileOrDirectory)) + { + Debug.LogError("File " + pathToFileOrDirectory + " does not exist"); + return; + } + if (Directory.Exists(targetDir)) + { + Directory.CreateDirectory(targetDir); + } + + if (guidToFile.ContainsValue(pathToFileOrDirectory)) + { + throw new ArgumentException($"Duplicate Path exported! {pathToFileOrDirectory}"); + } + + var isFile = File.Exists(pathToFileOrDirectory); + if (pathToFileOrDirectory.EndsWith(".meta", StringComparison.Ordinal)) return; + var metaPath = pathToFileOrDirectory + ".meta"; + var guid = default(string); + var hasMetaFile = File.Exists(metaPath); + if (hasMetaFile) + { + using (var reader = new StreamReader(metaPath)) + { + var line = reader.ReadLine(); + while(line != null) + { + if (line.StartsWith("guid:", StringComparison.Ordinal)) + { + guid = line.Substring("guid:".Length).Trim(); + if (guidToFile.ContainsKey(guid)) + throw new ArgumentException($"Duplicate GUID in AssetDatabase ({guid})?! Existing: {guidToFile[guid]}, new: {pathToFileOrDirectory}"); + guidToFile.Add(guid, pathToFileOrDirectory); + break; + } + line = reader.ReadLine(); + } + } + } + else + { + if (File.Exists(pathToFileOrDirectory)) + { + var bytes = File.ReadAllBytes(pathToFileOrDirectory); + using (var md5 = MD5.Create()) { + md5.TransformFinalBlock(bytes, 0, bytes.Length); + var hash = md5.Hash; + // guid = BitConverter.ToString(hash).Replace("-","");//(md5.Hash); + + guid = new Guid(hash).ToString("N"); + int maxTries = 200; + while (guidToFile.ContainsKey(guid)) + { + Debug.LogWarning($"GUID collision ({guid}), Existing: {guidToFile[guid]}, new: {pathToFileOrDirectory}"); + hash[0]++; + guid = new Guid(hash).ToString("N"); + maxTries--; + if (maxTries < 0) + { + throw new ArgumentException($"GUID collision on file: {pathToFileOrDirectory} with GUID {guid} even after 200 attempts of finding a new one. Aborting."); + } + } + guidToFile.Add(guid, pathToFileOrDirectory); + } + } + } + + if (guid == null) Debug.LogError("No guid for " + pathToFileOrDirectory); + pathToFileOrDirectory = pathToFileOrDirectory.Replace("\\", "/"); + var projectPath = Path.GetFullPath(Application.dataPath + "/../").Replace("\\", "/"); + var relPath = pathToFileOrDirectory; + if (relPath.StartsWith(projectPath, StringComparison.Ordinal)) relPath = relPath.Substring(projectPath.Length); + + var outDir = targetDir + "/" + guid; + if (!Directory.Exists(outDir)) Directory.CreateDirectory(outDir); + var pathNameFilePath = outDir + "/pathname"; + if(File.Exists(pathNameFilePath)) File.Delete(pathNameFilePath); + File.WriteAllText(pathNameFilePath, relPath); + if(isFile) File.Copy(pathToFileOrDirectory, outDir + "/asset", true); + if (hasMetaFile) File.Copy(metaPath, outDir + "/asset.meta", true); + + if(IncludePreviewImages && isFile && !extensionsWithoutThumbnails.Contains(Path.GetExtension(pathToFileOrDirectory).ToLowerInvariant())) + { +#if UNITY_2020_1_OR_NEWER + var preview = AssetPreview.GetAssetPreviewFromGUID(guid); +#else + var assetPath = AssetDatabase.GUIDToAssetPath(guid); + var asset = string.IsNullOrEmpty(assetPath) ? null : AssetDatabase.LoadAssetAtPath(assetPath); + var preview = asset ? AssetPreview.GetAssetPreview(asset) : default; +#endif + if (preview) + { + var thumbnailWidth = Mathf.Min(preview.width, 128); + var thumbnailHeight = Mathf.Min(preview.height, 128); + var rt = RenderTexture.GetTemporary(thumbnailWidth, thumbnailHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.sRGB); + + var copy = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);//, preview.graphicsFormat, preview.mipmapCount, TextureCreationFlags.None); + + RenderTexture.active = rt; + GL.Clear(true, true, new Color(0, 0, 0, 0)); + Graphics.Blit(preview, rt); + copy.ReadPixels(new Rect(0, 0, copy.width, copy.height), 0, 0, false); + copy.Apply(); + RenderTexture.active = null; + + var bytes = copy.EncodeToPNG(); + if (bytes != null && bytes.Length > 0) + { + File.WriteAllBytes(outDir + "/preview.png", bytes); + } + + RenderTexture.ReleaseTemporary(rt); + } + } + } + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs.meta b/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs.meta new file mode 100644 index 00000000..8e412b5f --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/UnitypackageExport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75df106947e68c74dad4cc3b8c28b51e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs b/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs new file mode 100644 index 00000000..d8cd3552 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs @@ -0,0 +1,123 @@ +ο»Ώusing System.Diagnostics; +using System.IO; +using UnityEditor; +using Debug = UnityEngine.Debug; + +namespace Needle.HybridPackages +{ + public static class Zipper + { + public enum CompressionStrength + { + Fastest = 1, + Fast = 3, + Normal = 5, + Maximum = 7, + Ultra = 9 + } + + public static bool TryCreateUnityPackageForPackage(string packageDirectory, string packageName, string targetPath) + { + var temp = Path.GetTempPath() + "/" + packageName; + if (Directory.Exists(temp)) Directory.Delete(temp, true); + Debug.Log(temp); + CopyFilesRecursively(packageDirectory, temp); + var res = TryCreateTgz(temp, targetPath); + if (res) Directory.Delete(temp, true); + return res; + } + + private static void CopyFilesRecursively(string sourcePath, string targetPath) + { + foreach (var dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)) + { + Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath)); + } + + foreach (var newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories)) + { + File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true); + } + } + + public static bool TryCreateTgz(string contentDirectory, string outputFilePath, CompressionStrength strength = CompressionStrength.Normal) + { + if (Zip(contentDirectory, outputFilePath, strength)) + return true; + return false; + } + + public static bool DebugLog = false; + + private static bool Zip(string directoryPath, string outputFilePath, CompressionStrength strength) + { + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Packing " + outputFilePath, 0f); + + var zipper = Get7zPath(); + outputFilePath = Path.GetFullPath(outputFilePath); + + if (File.Exists(outputFilePath)) + File.Delete(outputFilePath); + + int RunWith(string args) + { + if (DebugLog) + Debug.Log(zipper + " " + args); + var processStartInfo = new ProcessStartInfo(zipper, args); + // processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; + if (directoryPath != null) + processStartInfo.WorkingDirectory = directoryPath; + processStartInfo.UseShellExecute = DebugLog; + processStartInfo.CreateNoWindow = !DebugLog; + var process = Process.Start(processStartInfo); + process?.WaitForExit(); + var res = process?.ExitCode; + if (res.HasValue && res == 0) return res.Value; + if (DebugLog) + Debug.LogError("Result: " + res + " for " + processStartInfo); + return res ?? -1; + } + + // Command line syntax: + // https://sevenzip.osdn.jp/chm/cmdline/syntax.htm + + // Compression switches: + // https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm + + var files = directoryPath + "/*"; // string.Join(" ", filenames.Select(f => "\"" + f.Replace("\\", "/") + "\"").ToArray()); + var tarPath = Path.GetDirectoryName(outputFilePath) + "/archtemp.tar"; + if (File.Exists(tarPath)) File.Delete(tarPath); + var args_tar = $"a -ttar \"{tarPath}\" \"{files}\""; + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Packing .tar file for " + outputFilePath, 0.1f); + var code = RunWith(args_tar); + if (code == 0) + { + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Packing .tar.gz file for " + outputFilePath + ", compression: " + strength, 0.4f); + var args_tgz = $"a -tgzip \"{outputFilePath}\" \"{tarPath}\" -mx" + (int) strength; + if (File.Exists(outputFilePath)) File.Delete(outputFilePath); + code = RunWith(args_tgz); + if (DebugLog) + Debug.Log(code); + var success = code == 0; + if (success) File.Delete(tarPath); + } + + EditorUtility.DisplayProgressBar("Creating .unitypackage", "Done", 1f); + EditorUtility.ClearProgressBar(); + return code == 0; + } + + private static string Get7zPath() + { +#if (UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX) + string execFilename = "7za"; +#else + string execFilename = "7z.exe"; +#endif + string zipper = EditorApplication.applicationContentsPath + "/Tools/" + execFilename; + if (!File.Exists(zipper)) + throw new FileNotFoundException("Could not find " + zipper); + return zipper; + } + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs.meta b/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs.meta new file mode 100644 index 00000000..2f52403f --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Editor/Zipper.cs.meta @@ -0,0 +1,3 @@ +ο»ΏfileFormatVersion: 2 +guid: 97d7acb6c08f42adb166739a4a2307ea +timeCreated: 1620044445 \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/LICENSE.md b/Packages/com.needle.upm-in-unitypackage/LICENSE.md new file mode 100644 index 00000000..2f7a9d28 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Needle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Packages/com.needle.upm-in-unitypackage/LICENSE.md.meta b/Packages/com.needle.upm-in-unitypackage/LICENSE.md.meta new file mode 100644 index 00000000..a3195ede --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d67a253fac9f9d4581f1063f3b7e6fa +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Readme.md b/Packages/com.needle.upm-in-unitypackage/Readme.md new file mode 100644 index 00000000..fc25810a --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Readme.md @@ -0,0 +1,367 @@ +# Hybrid Packages + +![Unity Version Compatibility](https://img.shields.io/badge/Unity-2018.4%20%E2%80%94%202022.1-brightgreen) + +Unity has two separate package formats: +- `.unitypackage`, a zip-based file format that is used on the Asset Store +- `UPM package`, to prepare modules for Unity's package manager. + +The latter is newer, enforces better code and directory structure (AsmDefs required), and generally much easier to work with / add / remove / update. + +So far, it has been impossible to ship UPM packages on the Asset Store or via `.unitypackage` files. +This package fixes that by introducing **Hybrid Packages**, regular .unitypackage files that contain the correct directory structures for UPM. +After installing this package, you can select assets and folders from the Packages folder to be exported, which +- allows packages to be uploaded to the Asset Store through the regular Asset Store Tools +- enables Assets/Export Package to export stuff from package folders directly + +The resulting .unitypackage files _do not require any additional setup for users_. This package here is only required for creating those `.unitypackage` files, not for importing them. + +**If you switch to Hybrid Packages today, the transition to "registry-based" packages will be much more painless, as all your code and content will be ready on day 1.** + +## Update (October 2022): Unity has listened and added Hybrid Packages support to their Asset Store Tools! + +It's experimental and needs to be explcitily enabled. There's two ways: + +- either add the Hybrid Packages package (this one)! +- or add the scripting define `UNITY_ASTOOLS_EXPERIMENTAL` in Project Settings. + +> **Note**: We still recommend installing the Hybrid Packages package as it fixes some current issues in Unity's tool, like selecting packages with `file:..` references. + +This will unlock a new option in the Asset Store Uploader window: + +![20221030-024915_Unity](https://user-images.githubusercontent.com/2693840/198858071-9e3fc114-3636-4049-a2cf-d451f51297e9.png) + +**Fun fact:** the Asset Store Tools ship as Hybrid Package themselves! + +![image](https://user-images.githubusercontent.com/2693840/198858153-57f5f9ba-c1c7-406e-9fb6-06594876a522.png) + + +## Installation πŸ’Ύ +1. +
+ Add the OpenUPM registry with the com.needle scope to your project + + - open Edit/Project Settings/Package Manager + - add a new Scoped Registry: + ``` + Name: OpenUPM + URL: https://package.openupm.com/ + Scope(s): com.needle + ``` + - click Save +
+2. Add this package: + - open Window/Package Manager + - click + + - click Add package from git URL or Add package by name + - paste `com.needle.upm-in-unitypackage` + - click Add + +
+Alternative: git package (no PackMan updates, not recommended) + + - open Window/Package Manager + - click + + - click Add package from git URL or Add package by name + - Add `https://github.com/needle-tools/upm-in-unitypackage.git` in Package Manager + +
+ +## How to use πŸ’‘ + +### Export a .unitypackage that contains files in Packages or entire packages +1. select what you want to export +2. hit Assets/Export Package (also available via right click on Assets/Folders). + +### Upload Packages to Asset Store directly + +1. Install the Asset Store Tools as usual: https://assetstore.unity.com/packages/tools/utilities/asset-store-tools-115 +2. Open Asset Store Tools/Asset Store Uploader +3. Find your draft package in the list (must have already created on Unity Publisher Portal) +4. Choose the "Local UPM Package" upload type +5. Use the "Browse" button to select your package directory +6. Select additional packages as needed in the "Extra Packages" section +7. Press Upload + +#### Using an Upload Config to create and upload .unitypackage files + +Using a configuration file makes it easier to specify settings for export, and allows for "Package Bundles" (multiple packages in one `.unitypackage`). + +Here's how it works: + +1. Create a folder for your "package collection" in Assets, e.g. "My Package Collection". +2. In that folder, right click and create a `Needle/Asset Store Upload Config`. +3. Add entries to the `Selection`" array and drag the folders/files into the `Item` field. + For packages, drag in the `package.json` since package folders can't be drag-dropped. + This can be a single file, a folder, one or multiple packages, or a combination of these. +4. To test your Hybrid Package locally, select your config, and click Export for Local Testing. + This produces exactly the same .unitypackage as on Store upload, so you can test this one by importing it into a different/empty project. +5. Open Asset Store Tools/Asset Store Uploader +4. Choose the "Pre-exported unitypackage" upload type +5. Select the .unitypackage you already exported that contains package data +7. Press Upload + +## Known Issues / Limitations +- The optional Validate step isn't supported yet. Export your package via Right Click/Export Package or an Upload Config and test in a separate project for now. +- Dependencies into other packages shouldn't be exported, so you must turn off "Include Dependencies" when exporting a package. +- The `package.json` of your package can [define dependencies](https://docs.unity3d.com/Manual/upm-manifestPrj.html). However, only dependencies from the Unity Registry will be automatically resolved in empty projects - we'll need to think of a separate mechanism / guidance for people to add dependencies from scoped registries. For now, it's recommended that you guard against missing dependencies via [Version Defines](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html#define-symbols). +- .unitypackage preview images for hidden folders will not be exported unless you're on 2020.1+ and had that folder in the AssetDatabase in the current session (e.g. the folder was named "Samples" and then "Samples~" to hide it before export). +- There's experimental support for .gitignore and .npmignore, but the behaviour isn't exactly the same as with npm/git (e.g. when multiple of these are in different folders, the order they are applied isn't always correct). You can turn this on on the UploadConfig asset. +- The AssetStore Tools sometimes get stuck in an endless loop when trying to export nearly empty folders or empty multi-package sets. This seems to be an AssetStore Tools bug. + +---------- + +## FAQ / Why should I use this? + +Hybrid Packages are an in-between solution. Unity is still not ready for a proper, registry-based package workflow for the Asset Store. Hybrid Packages allow Asset Store developers to switch to a package-based workflow today, with some (but not all) of the benefits of that, with no (known) downsides compared to the current workflow. +If you switch to Hybrid Packages today, the transition to "registry-based" packages will be much more painless, as all your code and content will be ready on day 1. + +### How are these packaged up by your tool during submission? +Nothing changes, same process as the regular "Export > Unity Package" flow or "Asset Store Tools > Upload" (which are the same). Our tooling mostly just disables the check for "is this in assets?" and thus allows you to upload your embedded/local packages to the AssetStore. + +### When they are unpacked during installation, where do the assets wind up? +The files that before went into +`Assets/YourContent/` +now end up in +`Packages/com.your.content/ `. +This is what's called an embedded package. It is mutable, that is, users can change the files. It is not in the library, and files don't get duplicated into the `Library/PackageCache` folder. Also, this folder is not (and should not) be excluded from source control. From a file system perspective, it's really just a move from `Assets/` to `Packages/`, bringing some of the package benefits with it. + +Here's an example of how this looks for the Asset Store Tools themselves, which also ship as Hybrid Package: +![image](https://user-images.githubusercontent.com/2693840/198858135-1795f67d-9121-4835-95e4-214c237ecfb7.png) + +### How does Unity treat these assets when they are placed in the new (and non-standard) location? +For assets, nothing changes, no new/different rules. This is the same as if a user makes a `Packages/com.your.content/` folder and moves the files there (what a good number of users are already doing anyways). For scripts, Unity's rules for packages apply: code needs to be in AsmDefs to be compiled. This enforces better code structure, faster compilation, and is benefictial no matter if in "Assets" or "Packages". + +### Do these packages appear in the Package Manager at all? If so, can I use the "Install Sample" (or whatever it is) feature? How does that work? +Yes, this is one of the main points! Hybrid Packages +- show up in PackMan +- can use package.json dependencies +- can ship samples that can be installed via Package Manager. Samples are shipped with your .unitypackage in a folder called `Samples~` and set up via package.json. (see below for more on this) + +### How does this differ from the package lifecycle for packages installed via Package Manager? +Local Packages don't come from a registry, they're just "local". That is, they can't be updated via `PackageManager/In Project`. They still get updated by users from `Package Manager/My Assets` by downloading the new version and it gets "unpacked" over the old, as before. So, same rules still apply for updates: if you removed files, ask users to delete the folder before importing. + +_Before_ the existance of Hybrid Packages, installing Asset Store Content in user projects was mostly a fire-and-forget operation: +Users download a package, install it, and then neither the user nor Package Manager have any information that this content is actually in the project (of course the user can look for the folder, but the point is there's no real "entry point" for the content). + +_Now_, with Hybrid Packages, the content actually shows up in clear, structured places after installation: +- as a package in the project, under `Packages/Your Content` in the Project Window +- in the `In Project` section in Package Manager, with the ability to install Samples +- Updates are still done in the `My Assets` section as before. + +When the package is _not_ installed, it only shows up in "My Assets", as before. No change here. + +### How do I prepare my asset for the package workflow? +You create a local or embedded package: you define your own package.json file and add the relevant details such as your package name/version/description/author, set up "Runtime" and "Editor" folders. + +You move your code and assets over: make sure that all scripts are part of AsmDef files, that are properly marked for "Runtime" or "Editor". Mostly, that's it! + +_Recommended:_ Add a documentationUrl in your package.json, pointing at your docs either locally or on the web. This will be opened when people click on "Documentation" for your package in Package Manager. + +Also see
Guide to Packages. + +### Now that dependencies can be specified via package.json, what happens to the "Include Dependencies" functionality in the Asset Store Tools? +The "Include Dependencies" is now redundant. It never worked great (sometimes including way too many dependencies), and you have much more fine-grained control by adding exactly the dependencies you need to your package.json. +This has the additional benefit that dependencies aren't forcefully added to user project manifests (as with the Asset Store solution) - they are only resolved as long as your package is actually in the project. + +### How do I add samples that can be installed via Package Manager? +In your package.json, you can declare an array of samples for your package: + +```"samples": [ { "displayName" : "..", "description":"...", "path":"Samples~/..." } ]``` + +Samples are stored in folders. These all live in a folder called `Samples~` (note the tilde), which is hidden in Unity. +While you work on your samples, you simply rename the folder to `Samples`, and before submitting, you rename it back to `Samples~`. + +The advantage of shipping samples this way is that while samples are already downloaded and ready to be used, they don't clutter the asset database of user projects – only once people import the sample is it copied over to their Assets folders, ready to be adjusted as needed. + +### What differences, if any, are there regarding Unity's Special Folders? Is the functionality the same? Do Gizmos and other folders still work as expected? + +### Future: How do I prepare my asset for the future "registry-based" package workflow? + +_Note: some of the below depends on how Unity implements this for Asset Store publishers._ + +The main change with "registry-based" packages is that they are immutable, which means that users can't change the files in the package (they can still "embed" the package and make it locally editable, like you can for all Unity packages). + +But the goal is that your package is a single thing, nobody changes the content of it. Users then compose their project out of these assets as usual, e.g. they use animation files, models, materials, make new prefab variants, use components, ... + +One thing that you can't do anymore at this point is write your own files (e.g. settings) into your package once it's in users hands. Thus, your settings should live in a proper place depending on whether they need to be accessible in the Editor only (ProjectSettings/UserSettings) or at runtime (Assets/Resources). +If your code reads/writes from a settings file, this is a good point in time to modernize this, if you haven't already. Make sure settings are accessible via a SettingsProvider](https://docs.unity3d.com/ScriptReference/SettingsProvider.html?), and are either stored in "ProjectSettings", "UserSettings" or "Assets/Resources" (for settings that need to be available at runtime). + +## Technical Details + +This is tested with Unity 2018.4, 2019.4, 2020.3 and Asset Store Tools 5.0.4. + +All the functionality to use packages in .unitypackages is already provided by Unity. Just the tooling to create them has too many incorrect/outdated safety checks - so all we're doing here is bypassing those. It's still the same Unity APIs creating / exporting / importing packages. + +## Ideas for Future Development +- Immutable Packages could be shipped in `.unitypackage` as well as `Packages/com.my.package.tgz`, but this needs a bit more work to create an additional archive and include that in the exported package. +- ~~More safeguards around accidental inclusion of dependencies from other packages~~ +- Ability to show hints/warnigs for people to ask them to manually install dependencies from scoped registries. The Unity Terms of Service currently prohibit doing this automatically. + +## If you're Unity + +We're happy to provide guidance on what we needed to change here. This took only a few hours to create, and ideally wouldn't be necessary - `AssetStoreTools.dll` and `.unitypackage` utilities in Unity could just work. + +## Guide to Packages + + +**Option 1: Single-Project Workflow** +A single project where you work on your asset. + +``` +Your Test Project +β”œβ”€β”€ Assets +└── Packages + β”œβ”€β”€ manifest.json + β”œβ”€β”€ manifest-lock.json + └── com.your.package "Your package root folder" + β”œβ”€β”€ package.json "Specify package name, version, author, dependencies, samples, documentationUrl here" + β”œβ”€β”€ Changelog.md "This should follow SemVer conventions. See sample" + β”œβ”€β”€ Readme.md "Some basic info to get started" + β”œβ”€β”€ Runtime + β”‚ β”œβ”€β”€ Your.Package.asmdef + β”‚ └── "your runtime code and assets" + β”œβ”€β”€ Editor + β”‚ │── Your.Package.Editor.asmdef "This AsmDef must be set to Editor-only" + β”‚ └── "your editor code and assets" + └── Samples~ "This folder is hidden, samples get specified in package.json" + β”œβ”€β”€ Simple Sample + β”‚ └── "your sample code and files" + └── Complex Sample + └── "your sample code and files" +``` + +**Option 2: Multi-Project Workflow (recommended)** +Many packages need to support multiple Unity versions. This has traditionally been pretty cumbersome to maintain, with multiple submodules in different projects, copy-pasting code over, or just hoping everything works. +One of the biggest advantages of a package-based workflow is that cross-version development becomes incredibly easy, as the same package on disk can be referenced by multiple projects. Testing code is as simple as focussing the right Unity Editor instance. + +``` +Your Content Development Folder "often the git repository root" +β”œβ”€β”€ Your Test Project on Unity 2019.4 +β”‚ β”œβ”€β”€ Assets +β”‚ └── Packages +β”‚ β”œβ”€β”€ manifest.json "contains the line: " "com.your.package":"file:../../com.your.package" +β”‚ └── manifest-lock.json +β”‚ +β”œβ”€β”€ Your Test Project on Unity 2020.3 +β”‚ β”œβ”€β”€ Assets +β”‚ └── Packages +β”‚ β”œβ”€β”€ manifest.json "contains the line: " "com.your.package":"file:../../com.your.package" +β”‚ └── manifest-lock.json +β”‚ +β”œβ”€β”€ Your Test Project on Unity 2021.3 +β”‚ β”œβ”€β”€ Assets +β”‚ └── Packages +β”‚ β”œβ”€β”€ manifest.json "contains the line: " "com.your.package":"file:../../com.your.package" +β”‚ └── manifest-lock.json +β”‚ +└── com.your.package "Your package root folder" + β”œβ”€β”€ package.json "Specify package name, version, author, dependencies, samples, documentationUrl here" + β”œβ”€β”€ Changelog.md "This should follow SemVer conventions. See sample" + β”œβ”€β”€ Readme.md "Some basic info to get started" + β”œβ”€β”€ Runtime + β”‚ β”œβ”€β”€ Your.Package.asmdef + β”‚ └── "your runtime code and assets" + β”œβ”€β”€ Editor + β”‚ │── Your.Package.Editor.asmdef "This AsmDef must be set to Editor-only" + β”‚ └── "your editor code and assets" + └── Samples~ "This folder is hidden, samples get specified in package.json" + β”œβ”€β”€ Simple Sample + β”‚ └── "your sample code and files" + └── Complex Sample + └── "your sample code and files" + +``` + +**Complete Example: `package.json`** + +```json +{ + "name": "com.needle.my-package", + "version": "2.3.0", + "displayName": "My Package", + "description": "Shows how to set up a Package", + "author": + { + "name": "Needle", + "email": "hi@needle.tools", + "url": "https://needle.tools" + }, + "unity": "2019.4", + "type": "tool", + "documentationUrl": "https://github.com/needle-tools/upm-in-unitypackage#readme", + "samples": + [ + { + "displayName": "Simple Sample", + "description": "A very simple example, enough to get started.", + "path": "Samples~/Simple Sample" + }, + { + "displayName": "Complex Sample", + "description": "Shows everything this package can do.", + "path": "Samples~/Complex Sample" + } + ] +} +``` + +**Complete Example: `Changelog.md`** + +```md +# Changelog +All notable changes to this package will be documented in this file. +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [2.0.0] - 2021-02-12 +- added: new horse +- fixed: old horse sometimes lost teeth + +## [1.1.0] - 2021-01-08 +- added: horse controller and sample +- fixed: sample didn't actually explain how everything works + +## [1.0.0] - 2021-01-05 +- initial release with one horse +``` + +**Complete Example: Single-Project Folder Structure with settings** + +``` +Your Test Project +β”œβ”€β”€ Assets +β”‚ └── Resources +β”‚ └── YourPackageRuntimeSettings.asset "Your package should generate this if needed. Note, Users might move it somewhere else!" +β”œβ”€β”€ Packages +β”‚ β”œβ”€β”€ manifest.json +β”‚ β”œβ”€β”€ manifest-lock.json +β”‚ └── com.your.package "Your package root folder" +β”‚ β”œβ”€β”€ package.json "Specify package name, version, author, dependencies, samples, documentationUrl here" +β”‚ β”œβ”€β”€ Changelog.md "This should follow SemVer conventions. See sample" +β”‚ β”œβ”€β”€ Readme.md "Some basic info to get started" +β”‚ β”œβ”€β”€ Runtime +β”‚ β”‚ β”œβ”€β”€ Your.Package.asmdef +β”‚ β”‚ └── "your runtime code and assets" +β”‚ β”œβ”€β”€ Editor +β”‚ β”‚ │── Your.Package.Editor.asmdef "This AsmDef must be set to Editor-only" +β”‚ β”‚ └── "your editor code and assets" +β”‚ └── Samples~ "This folder is hidden, samples get specified in package.json" +β”‚ β”œβ”€β”€ Simple Sample +β”‚ β”‚ └── "your sample code and files" +β”‚ └── Complex Sample +β”‚ └── "your sample code and files" +β”œβ”€β”€ ProjectSettings +β”‚ └── YourPackageProjectSettings.asset "If your package has project-specific settings, put them here" +└── UserSettings + └── YourPackageUserSettings.asset "If your package has user-specific settings, put them here" +``` + +**Complete Example: Settings Provider** +```TODO // Move somewhere else``` + +## Contact βœ’οΈ +[🌡 needle β€” tools for unity](https://needle.tools) β€’ +[@NeedleTools](https://twitter.com/NeedleTools) β€’ +[@marcel_wiessler](https://twitter.com/marcel_wiessler) β€’ +[@hybridherbst](https://twitter.com/hybridherbst) β€’ +[Needle Discord](https://discord.gg/CFZDp4b) diff --git a/Packages/com.needle.upm-in-unitypackage/Readme.md.meta b/Packages/com.needle.upm-in-unitypackage/Readme.md.meta new file mode 100644 index 00000000..36783671 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Readme.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a0dd248cfa2c0045a4100b8e3f8c0f8 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config.meta new file mode 100644 index 00000000..8c5fc221 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0974992eb90174042a6ea1a8a00c7d26 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset new file mode 100644 index 00000000..6b6c6047 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72b48b51417c2fb4390f04d9a1d34a86, type: 3} + m_Name: Hybrid Packages Upload Config + m_EditorClassIdentifier: + items: + - {fileID: 2100000, guid: f9fa06aeedf24f042a4b5cec1c389bb9, type: 2} + - {fileID: 8385607101436470782, guid: e7d8125c437c58147941d1b4abeba86b, type: 3} diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset.meta new file mode 100644 index 00000000..340459d4 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Asset Store Upload Config/Hybrid Packages Upload Config.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c1e8454340c979d43b37eb1ae65e92f7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples.meta new file mode 100644 index 00000000..4c3706ce --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a46b2fe2794a20343b063cf14fb01d07 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md new file mode 100644 index 00000000..9023e7f1 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md @@ -0,0 +1,5 @@ +# Changelog +All notable changes to this package will be documented in this file. +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [0.1.0] - 2022-10-30 \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md.meta new file mode 100644 index 00000000..d82aeb6c --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Changelog.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7ae9e90a780483e45942e4e3ecac7caf +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor.meta new file mode 100644 index 00000000..1e7d23f8 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3ff447a850e31f41b14e2241e3af81f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs new file mode 100644 index 00000000..ce1610e2 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs @@ -0,0 +1,14 @@ +using UnityEditor; + +namespace Needle.MyPackage +{ + [CustomEditor(typeof(MySampleComponent))] + public class MySampleComponentEditor : Editor + { + public override void OnInspectorGUI() + { + EditorGUILayout.LabelField("My Sample Component", EditorStyles.boldLabel); + DrawDefaultInspector(); + } + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs.meta new file mode 100644 index 00000000..c6431285 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/MySampleComponentEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 819d0ed84c86a814c9bad15002131906 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef new file mode 100644 index 00000000..b6163941 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef @@ -0,0 +1,18 @@ +{ + "name": "Needle.MyPackage.Editor", + "rootNamespace": "", + "references": [ + "GUID:e58729a9bca53b54381c73ba388f7dcb" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef.meta new file mode 100644 index 00000000..f828df03 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Editor/Needle.MyPackage.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c770dedabc19b16419e49cca957dbd80 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt new file mode 100644 index 00000000..e69de29b diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt.meta new file mode 100644 index 00000000..8c8a7948 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Readme - Move me to the Packages folder.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ee144de55cff3dc48ba017c35c71ffbb +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime.meta new file mode 100644 index 00000000..d0184756 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55aff9eb31ebf4e47b5fb1c8d1d184d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs new file mode 100644 index 00000000..16d52fac --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace Needle.MyPackage +{ + public class MySampleComponent : MonoBehaviour + { + [Tooltip("A Sample Setting")] + public bool sampleSetting; + } +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs.meta new file mode 100644 index 00000000..4990ab52 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/MySampleComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8fcae18749b2ad043b84f303276ec49a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef new file mode 100644 index 00000000..f057f06d --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Needle.MyPackage", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef.meta new file mode 100644 index 00000000..05de21d7 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Runtime/Needle.MyPackage.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e58729a9bca53b54381c73ba388f7dcb +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample.meta new file mode 100644 index 00000000..7daf45c6 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b2720cccf509a54bbd3c3dfd32b39c1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt new file mode 100644 index 00000000..e69de29b diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt.meta new file mode 100644 index 00000000..127d6540 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 01.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 988785e6d499caa4fbb4be444c6940d5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt new file mode 100644 index 00000000..e69de29b diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt.meta new file mode 100644 index 00000000..b4cc0fec --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Complex Sample/Incredibly complex sample with TWO files - 02.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9b3f71dd47b9f8d40a29d16348c0d0f3 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample.meta new file mode 100644 index 00000000..fb21e274 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2022e6cf63b014e4fb3a23fe6cb22432 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt new file mode 100644 index 00000000..e69de29b diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt.meta new file mode 100644 index 00000000..1913899a --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/Samples~/Simple Sample/A very simple sample with just one file.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f7a1f116f78d5e149b2dca9beac78cad +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json new file mode 100644 index 00000000..85246ef9 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json @@ -0,0 +1,28 @@ +{ + "name": "com.needle.my-package", + "version": "2.3.0", + "displayName": "My Package", + "description": "Shows how to set up a package.json", + "author": + { + "name": "Needle", + "email": "hi@needle.tools", + "url": "https://needle.tools" + }, + "unity": "2019.4", + "type": "tool", + "documentationUrl": "https://github.com/needle-tools/upm-in-unitypackage#readme", + "samples": + [ + { + "displayName": "Simple Sample", + "description": "A very simple example, enough to get started.", + "path": "Samples~/Simple Sample" + }, + { + "displayName": "Complex Sample", + "description": "Shows everything this package can do.", + "path": "Samples~/Complex Sample" + } + ] + } \ No newline at end of file diff --git a/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json.meta b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json.meta new file mode 100644 index 00000000..04dd8a34 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/Samples~/Package with Samples/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 619849b78037ee544a837405cb1959df +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.needle.upm-in-unitypackage/package.json b/Packages/com.needle.upm-in-unitypackage/package.json new file mode 100644 index 00000000..697df388 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/package.json @@ -0,0 +1,30 @@ +{ + "displayName": "Hybrid Packages", + "name": "com.needle.upm-in-unitypackage", + "version": "0.6.3", + "unity": "2018.4", + "description": "Export UPM packages as .unitypackage files and upload them to the AssetStore", + "author": { + "name": "Needle", + "email": "contact@needle.tools", + "url": "https://needle.tools" + }, + "category": "Libraries", + "documentationUrl": "https://github.com/needle-tools/upm-in-unitypackage#readme", + "samples": [ + { + "displayName": "Asset Store Upload Config", + "description": "Example for uploading multiple assets/folders/packages to the Asset Store.", + "path": "Samples~/Asset Store Upload Config" + }, + { + "displayName": "Package with Samples", + "description": "Basic package example with samples.", + "path": "Samples~/Package with Samples" + } + ], + "type": "library", + "publishConfig": { + "registry": "https://package.openupm.com" + } +} diff --git a/Packages/com.needle.upm-in-unitypackage/package.json.meta b/Packages/com.needle.upm-in-unitypackage/package.json.meta new file mode 100644 index 00000000..0338e3d5 --- /dev/null +++ b/Packages/com.needle.upm-in-unitypackage/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e7d8125c437c58147941d1b4abeba86b +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 2b6b0c19..12e1de3e 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -6,6 +6,12 @@ "source": "embedded", "dependencies": {} }, + "com.needle.upm-in-unitypackage": { + "version": "file:com.needle.upm-in-unitypackage", + "depth": 0, + "source": "embedded", + "dependencies": {} + }, "com.unity.addressables": { "version": "1.19.19", "depth": 0, From c964f9dd45bdb04bc0e961dda909b8841d6f73e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Mon, 24 Mar 2025 16:38:37 -0300 Subject: [PATCH 53/53] update readme --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a90d645e..5f85b1cd 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ SceneManager.UnloadSceneAsync("my-previous-scene"); ## πŸ“¦ Installation -You can install the package via **[OpenUPM](https://openupm.com/packages/com.mygamedevtools.scene-loader)**, **Git** or **Tarball**. +You can install the package via **[OpenUPM](https://openupm.com/packages/com.mygamedevtools.scene-loader)**, **Git**, **Tarball** and the **[Unity Asset Store](https://assetstore.unity.com/packages/slug/313159)**. Check the full installation guide in the [documentation](https://scene-loader.mygamedevtools.com/docs/next/getting-started/installation). #### OpenUPM @@ -79,6 +79,18 @@ Check the full installation guide in the [documentation](https://scene-loader.my 4. Select `Install package from tarball...`. 5. Select the `com.mygamedevtools.scene-loader-.tgz` file you downloaded. +#### Unity Asset Store + +1. Obtain the package at the [Asset Store Page](https://assetstore.unity.com/packages/slug/313159). +2. With your Unity project open, click `Open in Unity`. +3. The `Package Manager` will open with the package selected. +4. Click `Download` or `Update`, depending on the local cache. +5. Click `Import`. +6. Make sure everything is selected and click `Import` again. + +> [!NOTE] +> When updating from the Asset Store, make sure to remove the previous version completely before adding the updated version. + ## πŸ“š Documentation The detailed documentation including usage guides, examples, update guides, and tutorials are available in the [official documentation](https://scene-loader.mygamedevtools.com/).