From 64e0b517672f1d7cbaac7a8c347d80a4c3c8d7bc Mon Sep 17 00:00:00 2001 From: bd_ Date: Mon, 3 Jun 2024 09:01:13 +0900 Subject: [PATCH] feat: preview framework (#244) * feat: preview framework Import the preview framework from NDMF-Core (https://github.com/bdunderscore/ndmf-core/commit/7af1614a91c1d8330f3ccbb0cc7041d0a45a49c0) * feat: NDMF build pipeline integration for preview system * chore: improve API docs * chore: remove some spammy debug logs * chore: adjustments to public API scope * chore: CHANGELOG updates * fix: invalidate all watchers when the scene changes * chore: suppress spurious warnings * chore: add 0Harmony.dll for standalone configurations * fix: scene header shows as "deleted object" in some cases --- CHANGELOG.md | 3 + Dependencies~/0Harmony.LICENSE.txt | 21 + Dependencies~/0Harmony.LICENSE.txt.meta | 7 + Dependencies~/0Harmony.dll | Bin 0 -> 799232 bytes Dependencies~/0Harmony.dll.meta | 33 + Editor/API/Fluent/Sequence/Sequence.cs | 14 + Editor/API/Model/SolverPass.cs | 2 + Editor/API/Solver/PluginResolver.cs | 10 +- Editor/ChangeStream.meta | 3 + Editor/ChangeStream/ChangeStreamMonitor.cs | 204 ++ .../ChangeStream/ChangeStreamMonitor.cs.meta | 3 + Editor/ChangeStream/ListenerSet.cs | 108 + Editor/ChangeStream/ListenerSet.cs.meta | 3 + Editor/ChangeStream/ObjectWatcher.cs | 304 +++ Editor/ChangeStream/ObjectWatcher.cs.meta | 3 + Editor/ChangeStream/ShadowGameObject.cs | 455 ++++ Editor/ChangeStream/ShadowGameObject.cs.meta | 3 + Editor/GlobalInit.cs | 7 + Editor/PreviewSystem.meta | 3 + Editor/PreviewSystem/Harmony.meta | 3 + .../Harmony/HandleUtilityPatches.cs | 89 + .../Harmony/HandleUtilityPatches.cs.meta | 3 + .../Harmony/HierarchyViewPatches.cs | 181 ++ .../Harmony/HierarchyViewPatches.cs.meta | 3 + Editor/PreviewSystem/Harmony/Patcher.cs | 41 + Editor/PreviewSystem/Harmony/Patcher.cs.meta | 3 + .../Harmony/PickingObjectPatch.cs | 82 + .../Harmony/PickingObjectPatch.cs.meta | 3 + Editor/PreviewSystem/IRenderFilter.cs | 156 ++ Editor/PreviewSystem/IRenderFilter.cs.meta | 3 + Editor/PreviewSystem/PreviewSession.cs | 145 ++ Editor/PreviewSystem/PreviewSession.cs.meta | 3 + Editor/PreviewSystem/ProxyManager.cs | 69 + Editor/PreviewSystem/ProxyManager.cs.meta | 3 + Editor/PreviewSystem/Rendering.meta | 3 + Editor/PreviewSystem/Rendering/NodeGraph.cs | 40 + .../PreviewSystem/Rendering/NodeGraph.cs.meta | 3 + Editor/PreviewSystem/Rendering/ProxyNode.cs | 171 ++ .../PreviewSystem/Rendering/ProxyNode.cs.meta | 3 + .../Rendering/ProxyObjectController.cs | 145 ++ .../Rendering/ProxyObjectController.cs.meta | 3 + .../PreviewSystem/Rendering/ProxyPipeline.cs | 196 ++ .../Rendering/ProxyPipeline.cs.meta | 3 + .../PreviewSystem/Rendering/ProxySession.cs | 154 ++ .../Rendering/ProxySession.cs.meta | 3 + Editor/PreviewSystem/SequencePoint.cs | 23 + Editor/PreviewSystem/SequencePoint.cs.meta | 3 + Editor/PreviewSystem/Sequencer.cs | 58 + Editor/PreviewSystem/Sequencer.cs.meta | 3 + Editor/RQ-Unity.meta | 3 + Editor/RQ-Unity/CommonQueries.cs | 77 + Editor/RQ-Unity/CommonQueries.cs.meta | 3 + Editor/RQ-Unity/ReactiveQueryExt.cs | 186 ++ Editor/RQ-Unity/ReactiveQueryExt.cs.meta | 3 + .../ThrottledSynchronizationContext.cs | 208 ++ .../ThrottledSynchronizationContext.cs.meta | 3 + Editor/assembly-info.cs | 1 + Editor/nadena.dev.ndmf.asmdef | 4 +- RQ-Core.meta | 3 + RQ-Core/ComputeContext.cs | 60 + RQ-Core/ComputeContext.cs.meta | 3 + RQ-Core/IInvalidationObserver.cs | 7 + RQ-Core/IInvalidationObserver.cs.meta | 3 + RQ-Core/JetBrainsAnnotations.meta | 8 + .../JetBrainsAnnotations.cs | 2189 +++++++++++++++++ .../JetBrainsAnnotations.cs.meta | 3 + RQ-Core/JetBrainsAnnotations/assembly-info.cs | 7 + .../assembly-info.cs.meta | 3 + ...eactive-query.jetbrains-annotations.asmdef | 14 + ...ve-query.jetbrains-annotations.asmdef.meta | 3 + RQ-Core/ObjectIdentityComparer.cs | 25 + RQ-Core/ObjectIdentityComparer.cs.meta | 3 + RQ-Core/ReactiveField.cs | 36 + RQ-Core/ReactiveField.cs.meta | 3 + RQ-Core/ReactiveQuery.cs | 134 + RQ-Core/ReactiveQuery.cs.meta | 3 + RQ-Core/ReactiveQueryScheduler.cs | 38 + RQ-Core/ReactiveQueryScheduler.cs.meta | 3 + RQ-Core/ReactiveValue.cs | 486 ++++ RQ-Core/ReactiveValue.cs.meta | 3 + RQ-Core/SyncContextScope.cs | 24 + RQ-Core/SyncContextScope.cs.meta | 3 + RQ-Core/SynchronousTaskScheduler.cs | 31 + RQ-Core/SynchronousTaskScheduler.cs.meta | 3 + RQ-Core/TaskExt.cs | 50 + RQ-Core/TaskExt.cs.meta | 3 + RQ-Core/TaskThrottle.cs | 49 + RQ-Core/TaskThrottle.cs.meta | 3 + RQ-Core/assembly-info.cs | 7 + RQ-Core/assembly-info.cs.meta | 3 + ...nadena.dev.ndmf.reactive-query.core.asmdef | 16 + ...a.dev.ndmf.reactive-query.core.asmdef.meta | 7 + Runtime/SelfDestructComponent.cs | 29 + Runtime/SelfDestructComponent.cs.meta | 3 + UnitTests~/RQ-EditorTests.meta | 3 + .../RQ-EditorTests/RQUnityIntegrationTest.cs | 67 + .../RQUnityIntegrationTest.cs.meta | 3 + .../RQ-EditorTests/ShadowHierarchyTest.cs | 461 ++++ .../ShadowHierarchyTest.cs.meta | 3 + ...ev.ndmf.reactive-query.tests.editor.asmdef | 20 + ...mf.reactive-query.tests.editor.asmdef.meta | 3 + UnitTests~/RQ-StandaloneTests.meta | 3 + .../RQ-StandaloneTests/BasicQueryTest.cs | 144 ++ .../RQ-StandaloneTests/BasicQueryTest.cs.meta | 3 + .../ObservableInterfaceTest.cs | 216 ++ .../ObservableInterfaceTest.cs.meta | 3 + .../RQ-StandaloneTests/StandaloneTestBase.cs | 22 + .../StandaloneTestBase.cs.meta | 3 + UnitTests~/RQ-StandaloneTests/TestHelpers.cs | 32 + .../RQ-StandaloneTests/TestHelpers.cs.meta | 3 + UnitTests~/RQ-StandaloneTests/TestQuery.cs | 36 + .../RQ-StandaloneTests/TestQuery.cs.meta | 3 + ...dmf.reactive-query.tests.standalone.asmdef | 18 + ...eactive-query.tests.standalone.asmdef.meta | 3 + 114 files changed, 7587 insertions(+), 2 deletions(-) create mode 100644 Dependencies~/0Harmony.LICENSE.txt create mode 100644 Dependencies~/0Harmony.LICENSE.txt.meta create mode 100644 Dependencies~/0Harmony.dll create mode 100644 Dependencies~/0Harmony.dll.meta create mode 100644 Editor/ChangeStream.meta create mode 100644 Editor/ChangeStream/ChangeStreamMonitor.cs create mode 100644 Editor/ChangeStream/ChangeStreamMonitor.cs.meta create mode 100644 Editor/ChangeStream/ListenerSet.cs create mode 100644 Editor/ChangeStream/ListenerSet.cs.meta create mode 100644 Editor/ChangeStream/ObjectWatcher.cs create mode 100644 Editor/ChangeStream/ObjectWatcher.cs.meta create mode 100644 Editor/ChangeStream/ShadowGameObject.cs create mode 100644 Editor/ChangeStream/ShadowGameObject.cs.meta create mode 100644 Editor/PreviewSystem.meta create mode 100644 Editor/PreviewSystem/Harmony.meta create mode 100644 Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs create mode 100644 Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs.meta create mode 100644 Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs create mode 100644 Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs.meta create mode 100644 Editor/PreviewSystem/Harmony/Patcher.cs create mode 100644 Editor/PreviewSystem/Harmony/Patcher.cs.meta create mode 100644 Editor/PreviewSystem/Harmony/PickingObjectPatch.cs create mode 100644 Editor/PreviewSystem/Harmony/PickingObjectPatch.cs.meta create mode 100644 Editor/PreviewSystem/IRenderFilter.cs create mode 100644 Editor/PreviewSystem/IRenderFilter.cs.meta create mode 100644 Editor/PreviewSystem/PreviewSession.cs create mode 100644 Editor/PreviewSystem/PreviewSession.cs.meta create mode 100644 Editor/PreviewSystem/ProxyManager.cs create mode 100644 Editor/PreviewSystem/ProxyManager.cs.meta create mode 100644 Editor/PreviewSystem/Rendering.meta create mode 100644 Editor/PreviewSystem/Rendering/NodeGraph.cs create mode 100644 Editor/PreviewSystem/Rendering/NodeGraph.cs.meta create mode 100644 Editor/PreviewSystem/Rendering/ProxyNode.cs create mode 100644 Editor/PreviewSystem/Rendering/ProxyNode.cs.meta create mode 100644 Editor/PreviewSystem/Rendering/ProxyObjectController.cs create mode 100644 Editor/PreviewSystem/Rendering/ProxyObjectController.cs.meta create mode 100644 Editor/PreviewSystem/Rendering/ProxyPipeline.cs create mode 100644 Editor/PreviewSystem/Rendering/ProxyPipeline.cs.meta create mode 100644 Editor/PreviewSystem/Rendering/ProxySession.cs create mode 100644 Editor/PreviewSystem/Rendering/ProxySession.cs.meta create mode 100644 Editor/PreviewSystem/SequencePoint.cs create mode 100644 Editor/PreviewSystem/SequencePoint.cs.meta create mode 100644 Editor/PreviewSystem/Sequencer.cs create mode 100644 Editor/PreviewSystem/Sequencer.cs.meta create mode 100644 Editor/RQ-Unity.meta create mode 100644 Editor/RQ-Unity/CommonQueries.cs create mode 100644 Editor/RQ-Unity/CommonQueries.cs.meta create mode 100644 Editor/RQ-Unity/ReactiveQueryExt.cs create mode 100644 Editor/RQ-Unity/ReactiveQueryExt.cs.meta create mode 100644 Editor/RQ-Unity/ThrottledSynchronizationContext.cs create mode 100644 Editor/RQ-Unity/ThrottledSynchronizationContext.cs.meta create mode 100644 RQ-Core.meta create mode 100644 RQ-Core/ComputeContext.cs create mode 100644 RQ-Core/ComputeContext.cs.meta create mode 100644 RQ-Core/IInvalidationObserver.cs create mode 100644 RQ-Core/IInvalidationObserver.cs.meta create mode 100644 RQ-Core/JetBrainsAnnotations.meta create mode 100644 RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs create mode 100644 RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs.meta create mode 100644 RQ-Core/JetBrainsAnnotations/assembly-info.cs create mode 100644 RQ-Core/JetBrainsAnnotations/assembly-info.cs.meta create mode 100644 RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef create mode 100644 RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef.meta create mode 100644 RQ-Core/ObjectIdentityComparer.cs create mode 100644 RQ-Core/ObjectIdentityComparer.cs.meta create mode 100644 RQ-Core/ReactiveField.cs create mode 100644 RQ-Core/ReactiveField.cs.meta create mode 100644 RQ-Core/ReactiveQuery.cs create mode 100644 RQ-Core/ReactiveQuery.cs.meta create mode 100644 RQ-Core/ReactiveQueryScheduler.cs create mode 100644 RQ-Core/ReactiveQueryScheduler.cs.meta create mode 100644 RQ-Core/ReactiveValue.cs create mode 100644 RQ-Core/ReactiveValue.cs.meta create mode 100644 RQ-Core/SyncContextScope.cs create mode 100644 RQ-Core/SyncContextScope.cs.meta create mode 100644 RQ-Core/SynchronousTaskScheduler.cs create mode 100644 RQ-Core/SynchronousTaskScheduler.cs.meta create mode 100644 RQ-Core/TaskExt.cs create mode 100644 RQ-Core/TaskExt.cs.meta create mode 100644 RQ-Core/TaskThrottle.cs create mode 100644 RQ-Core/TaskThrottle.cs.meta create mode 100644 RQ-Core/assembly-info.cs create mode 100644 RQ-Core/assembly-info.cs.meta create mode 100644 RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef create mode 100644 RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef.meta create mode 100644 Runtime/SelfDestructComponent.cs create mode 100644 Runtime/SelfDestructComponent.cs.meta create mode 100644 UnitTests~/RQ-EditorTests.meta create mode 100644 UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs create mode 100644 UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs.meta create mode 100644 UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs create mode 100644 UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs.meta create mode 100644 UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef create mode 100644 UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef.meta create mode 100644 UnitTests~/RQ-StandaloneTests.meta create mode 100644 UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs create mode 100644 UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs.meta create mode 100644 UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs create mode 100644 UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs.meta create mode 100644 UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs create mode 100644 UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs.meta create mode 100644 UnitTests~/RQ-StandaloneTests/TestHelpers.cs create mode 100644 UnitTests~/RQ-StandaloneTests/TestHelpers.cs.meta create mode 100644 UnitTests~/RQ-StandaloneTests/TestQuery.cs create mode 100644 UnitTests~/RQ-StandaloneTests/TestQuery.cs.meta create mode 100644 UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef create mode 100644 UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 231a5c6e..31c6fcc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- [#244] - Added a framework that can be used to override the rendering of an object without modifying the object itself +- [#244] - Added a framework for observing scene object changes and reacting to them. +- [#244] - Added `SelfDestructComponent` (useful for hidden preview-only components) ### Fixed diff --git a/Dependencies~/0Harmony.LICENSE.txt b/Dependencies~/0Harmony.LICENSE.txt new file mode 100644 index 00000000..655c71c5 --- /dev/null +++ b/Dependencies~/0Harmony.LICENSE.txt @@ -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. diff --git a/Dependencies~/0Harmony.LICENSE.txt.meta b/Dependencies~/0Harmony.LICENSE.txt.meta new file mode 100644 index 00000000..4e5e7ff8 --- /dev/null +++ b/Dependencies~/0Harmony.LICENSE.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bbc8bb0ffc3ca7643ad5cc02c086ce59 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Dependencies~/0Harmony.dll b/Dependencies~/0Harmony.dll new file mode 100644 index 0000000000000000000000000000000000000000..6b7d29daaa2ca62c4bb99f45a92474a7d75c7056 GIT binary patch literal 799232 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%0AIkHtir*@l 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 /// Declares that the pass you just declared must run before a particular other plugin. /// diff --git a/Editor/API/Model/SolverPass.cs b/Editor/API/Model/SolverPass.cs index 3a5a1733..e8a2de2d 100644 --- a/Editor/API/Model/SolverPass.cs +++ b/Editor/API/Model/SolverPass.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using nadena.dev.ndmf.preview; #endregion @@ -22,6 +23,7 @@ internal class SolverPass internal IImmutableSet RequiredExtensions { get; set; } internal IImmutableSet CompatibleExtensions { get; set; } + internal IRenderFilter RenderFilter { get; set; } internal bool IsExtensionCompatible(Type ty) { diff --git a/Editor/API/Solver/PluginResolver.cs b/Editor/API/Solver/PluginResolver.cs index bce346bf..5f5eeb12 100644 --- a/Editor/API/Solver/PluginResolver.cs +++ b/Editor/API/Solver/PluginResolver.cs @@ -5,7 +5,7 @@ using System.Collections.Immutable; using System.Linq; using nadena.dev.ndmf.model; -using UnityEngine; +using nadena.dev.ndmf.preview; #endregion @@ -49,6 +49,7 @@ internal ConcretePass(IPluginInternal plugin, IPass pass, ImmutableList de internal class PluginResolver { + internal PreviewSession PreviewSession { get; private set; } internal ImmutableList<(BuildPhase, IList)> Passes { get; } public PluginResolver() : this( @@ -70,6 +71,8 @@ public PluginResolver(IEnumerable plugins) : this( public PluginResolver(IEnumerable pluginTemplates) { + PreviewSession = new PreviewSession(); + var solverContext = new SolverContext(); foreach (var plugin in pluginTemplates) @@ -195,6 +198,11 @@ ImmutableList ToConcretePasses(BuildPhase phase, IEnumerable 0) diff --git a/Editor/ChangeStream.meta b/Editor/ChangeStream.meta new file mode 100644 index 00000000..f6b1c2fd --- /dev/null +++ b/Editor/ChangeStream.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 12dce40ae2134d4a97d8046f50093dbd +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/ChangeStream/ChangeStreamMonitor.cs b/Editor/ChangeStream/ChangeStreamMonitor.cs new file mode 100644 index 00000000..71f3ab09 --- /dev/null +++ b/Editor/ChangeStream/ChangeStreamMonitor.cs @@ -0,0 +1,204 @@ +#region + +using System; +using System.Diagnostics; +using UnityEditor; +using UnityEngine.Profiling; +using Debug = UnityEngine.Debug; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + internal class ChangeStreamMonitor + { + [InitializeOnLoadMethod] + static void Init() + { + ObjectChangeEvents.changesPublished += OnChange; + } + + private static void OnChange(ref ObjectChangeEventStream stream) + { + Profiler.BeginSample("ChangeStreamMonitor.OnChange"); + + int length = stream.length; + for (int i = 0; i < length; i++) + { + try + { + HandleEvent(stream, i); + } + catch (Exception e) + { + Debug.LogError($"Error handling event {i}: {e}"); + } + } + + Profiler.EndSample(); + } + + private static void HandleEvent(ObjectChangeEventStream stream, int i) + { + switch (stream.GetEventType(i)) + { + case ObjectChangeKind.None: break; + + case ObjectChangeKind.ChangeScene: + { + ObjectWatcher.Instance.Hierarchy.InvalidateAll(); + + break; + } + + case ObjectChangeKind.CreateGameObjectHierarchy: + { + stream.GetCreateGameObjectHierarchyEvent(i, out var data); + + ObjectWatcher.Instance.Hierarchy.FireGameObjectCreate(data.instanceId); + break; + } + + case ObjectChangeKind.ChangeGameObjectStructureHierarchy: + { + stream.GetChangeGameObjectStructureHierarchyEvent(i, out var data); + + OnChangeGameObjectStructureHierarchy(data); + + break; + } + + case ObjectChangeKind.ChangeGameObjectStructure: // add/remove components + { + stream.GetChangeGameObjectStructureEvent(i, out var data); + OnChangeGameObjectStructure(data); + + break; + } + + case ObjectChangeKind.ChangeGameObjectParent: + { + stream.GetChangeGameObjectParentEvent(i, out var data); + OnChangeGameObjectParent(data); + + break; + } + + case ObjectChangeKind.ChangeGameObjectOrComponentProperties: + { + stream.GetChangeGameObjectOrComponentPropertiesEvent(i, out var data); + OnChangeGameObjectOrComponentProperties(data); + + break; + } + + case ObjectChangeKind.DestroyGameObjectHierarchy: + { + stream.GetDestroyGameObjectHierarchyEvent(i, out var data); + OnDestroyGameObjectHierarchy(data); + + break; + } + + case ObjectChangeKind.CreateAssetObject: break; + case ObjectChangeKind.DestroyAssetObject: + { + stream.GetDestroyAssetObjectEvent(i, out var data); + OnDestroyAssetObject(data); + + break; + } + + case ObjectChangeKind.ChangeAssetObjectProperties: + { + stream.GetChangeAssetObjectPropertiesEvent(i, out var data); + OnChangeAssetObjectProperties(data); + + break; + } + + case ObjectChangeKind.UpdatePrefabInstances: + { + stream.GetUpdatePrefabInstancesEvent(i, out var data); + OnUpdatePrefabInstances(data); + + break; + } + + case ObjectChangeKind.ChangeChildrenOrder: + { + stream.GetChangeChildrenOrderEvent(i, out var data); + OnChangeChildrenOrder(data); + + break; + } + } + } + + private static void OnChangeChildrenOrder(ChangeChildrenOrderEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.FireReorderNotification(instanceId); + } + + private static void OnUpdatePrefabInstances(UpdatePrefabInstancesEventArgs data) + { + foreach (var iid in data.instanceIds) + { + ObjectWatcher.Instance.Hierarchy.InvalidateTree(iid); + } + } + + private static void OnChangeAssetObjectProperties(ChangeAssetObjectPropertiesEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.FireObjectChangeNotification(instanceId); + } + + private static void OnDestroyAssetObject(DestroyAssetObjectEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.InvalidateTree(instanceId); + } + + private static void OnDestroyGameObjectHierarchy(DestroyGameObjectHierarchyEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.InvalidateTree(instanceId); + } + + private static void OnChangeGameObjectOrComponentProperties(ChangeGameObjectOrComponentPropertiesEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.FireObjectChangeNotification(instanceId); + } + + private static void OnChangeGameObjectParent(ChangeGameObjectParentEventArgs data) + { + var instanceId = data.instanceId; + var priorParentId = data.previousParentInstanceId; + var newParentId = data.newParentInstanceId; + + ObjectWatcher.Instance.Hierarchy.FireReparentNotification(instanceId); + } + + private static void OnChangeGameObjectStructure(ChangeGameObjectStructureEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.FireStructureChangeEvent(instanceId); + } + + private static void OnChangeGameObjectStructureHierarchy(ChangeGameObjectStructureHierarchyEventArgs data) + { + var instanceId = data.instanceId; + + ObjectWatcher.Instance.Hierarchy.InvalidateTree(instanceId); + } + } +} \ No newline at end of file diff --git a/Editor/ChangeStream/ChangeStreamMonitor.cs.meta b/Editor/ChangeStream/ChangeStreamMonitor.cs.meta new file mode 100644 index 00000000..2e59064c --- /dev/null +++ b/Editor/ChangeStream/ChangeStreamMonitor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71e71a70dcc445e9a424f50ae1908b29 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/ChangeStream/ListenerSet.cs b/Editor/ChangeStream/ListenerSet.cs new file mode 100644 index 00000000..0ee71cb7 --- /dev/null +++ b/Editor/ChangeStream/ListenerSet.cs @@ -0,0 +1,108 @@ +#region + +using System; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + internal class Listener : IDisposable + { + private ListenerSet _owner; + internal Listener _next, _prev; + + private readonly ListenerSet.Invokee _callback; + private readonly WeakReference _param; + + internal Listener( + ListenerSet owner, + ListenerSet.Invokee callback, + object param + ) + { + _owner = owner; + _next = _prev = this; + _callback = callback; + _param = new WeakReference(param); + } + + public void Dispose() + { + if (_next != null) + { + _next._prev = _prev; + _prev._next = _next; + } + + _next = _prev = null; + _param.SetTarget(null); + } + + internal void MaybePrune() + { + if (!_param.TryGetTarget(out _)) + { + Dispose(); + } + } + + // Invoked under lock(_owner) + internal void MaybeFire(T info) + { + if (!_param.TryGetTarget(out var target) || _callback(target, info)) + { + Dispose(); + } + } + } + + internal class ListenerSet + { + public delegate bool Invokee(object target, T info); + + private Listener _head; + + public ListenerSet() + { + _head = new Listener(this, (object _, T _) => false, null); + _head._next = _head._prev = _head; + } + + public bool HasListeners() + { + return _head._next != _head; + } + + public IDisposable Register(Invokee callback, object param) + { + var listener = new Listener(this, callback, param); + + listener._next = _head._next; + listener._prev = _head; + _head._next._prev = listener; + _head._next = listener; + + return listener; + } + + public void Fire(T info) + { + for (var listener = _head._next; listener != _head;) + { + var next = listener._next; + listener.MaybeFire(info); + listener = next; + } + } + + public void Prune() + { + for (var listener = _head._next; listener != _head;) + { + var next = listener._next; + listener.MaybePrune(); + listener = next; + } + } + } +} \ No newline at end of file diff --git a/Editor/ChangeStream/ListenerSet.cs.meta b/Editor/ChangeStream/ListenerSet.cs.meta new file mode 100644 index 00000000..022cc028 --- /dev/null +++ b/Editor/ChangeStream/ListenerSet.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3eaf3d7227b4441b805f1fc4b49f10b3 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/ChangeStream/ObjectWatcher.cs b/Editor/ChangeStream/ObjectWatcher.cs new file mode 100644 index 00000000..2f586fb0 --- /dev/null +++ b/Editor/ChangeStream/ObjectWatcher.cs @@ -0,0 +1,304 @@ +#region + +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using UnityEditor; +using UnityEngine; +using UnityEngine.SceneManagement; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + #region + + using UnityObject = Object; + + #endregion + + /// + /// ObjectWatcher provides a high level API for monitoring for various changes to assets and scene objects in the + /// editor. + /// + internal sealed class ObjectWatcher + { + // Supported watch categories: + // - Single-object watch: Monitor asset, component properties, etc + // -> simple mapping + // - Parent watch: Monitor whether the parent of an object changes + // -> record parent path + // - Component search: Monitor the set of components matching a type filter under a given object + // -> + + // Event types: + // - ChangeScene: Fires everything + // - CreateGameObjectHierarchy: Check parents, possibly fire component search notifications + // -> May result in creation of new components under existing nodes + // - ChangeGameObjectStructureHierarchy: Check old and new parents, possibly fire component search notifications + // -> May result in creation of new components under existing nodes, or reparenting of components + // - ChangeGameObjectStructure: Check parents, possibly fire component search notifications + // -> Creates/deletes components + // - ChangeGameObjectOrComponentProperties: + // -> If component, fire single notification. If GameObject, this might be a component reordering, so fire + // the component search notifications as needed + // - CreateAssetObject: Ignored + // - DestroyAssetObject: Fire single object notifications + // - ChangeAssetObjectProperties: Fire single object notifications + // - UpdatePrefabInstances: Treated as ChangeGameObjectStructureHierarchy + // - ChangeChildrenOrder: Fire component search notifications + + // High level structure: + // We maintain a "shadow hierarchy" of GameObjects with their last known parent/child relationships. + // Since OCES doesn't give us the prior state, we need this to determine which parent objects need to be + // notified when objects move. Each shadow GameObject also tracks the last known set of components on the object. + // + // Listeners come in two flavors: object listeners (asset/component watches as well as parent watches), and + // component search listeners, which can be local or recursive. + + public static ObjectWatcher Instance { get; private set; } = new ObjectWatcher(); + internal ShadowHierarchy Hierarchy = new ShadowHierarchy(); + private readonly SynchronizationContext _syncContext = SynchronizationContext.Current; + private readonly int threadId = Thread.CurrentThread.ManagedThreadId; + + internal ObjectWatcher() + { + } + + [InitializeOnLoadMethod] + private static void Init() + { + SceneManager.sceneLoaded += (_, _) => Instance.Hierarchy.InvalidateAll(); + SceneManager.sceneUnloaded += _ => Instance.Hierarchy.InvalidateAll(); + SceneManager.activeSceneChanged += (_, _) => Instance.Hierarchy.InvalidateAll(); + } + + public ImmutableList MonitorSceneRoots(out IDisposable cancel, Action callback, T target) + where T : class + { + ImmutableList rootSet = GetRootSet(); + + // TODO scene load callbacks + + cancel = Hierarchy.RegisterRootSetListener((t, e) => + { + ImmutableList newRootSet = GetRootSet(); + if (!newRootSet.SequenceEqual(rootSet)) + { + InvokeCallback(callback, t); + + return true; + } + else + { + return false; + } + }, target); + + cancel = CancelWrapper(cancel); + + return rootSet; + } + + private ImmutableList GetRootSet() + { + ImmutableList.Builder roots = ImmutableList.CreateBuilder(); + + var sceneCount = SceneManager.sceneCount; + for (int i = 0; i < sceneCount; i++) + { + var scene = SceneManager.GetSceneAt(i); + if (!scene.IsValid() || !scene.isLoaded) continue; + + foreach (var go in scene.GetRootGameObjects()) + { + roots.Add(go); + } + } + + return roots.ToImmutable(); + } + + public void MonitorObjectPath(out IDisposable cancel, Transform t, Action callback, T target) + where T : class + { + cancel = Hierarchy.RegisterGameObjectListener(t.gameObject, (t, e) => + { + switch (e) + { + case HierarchyEvent.PathChange: + case HierarchyEvent.ForceInvalidate: + InvokeCallback(callback, t); + return true; + default: + return false; + } + }, target); + Hierarchy.EnablePathMonitoring(t.gameObject); + + cancel = CancelWrapper(cancel); + } + + public void MonitorObjectProps(out IDisposable cancel, UnityObject obj, Action callback, T target) + where T : class + { + cancel = default; + + if (obj is GameObject go) + { + cancel = Hierarchy.RegisterGameObjectListener(go, (t, e) => + { + switch (e) + { + case HierarchyEvent.ObjectDirty: + case HierarchyEvent.ForceInvalidate: + InvokeCallback(callback, t); + return true; + default: + return false; + } + }, target); + } + else + { + cancel = Hierarchy.RegisterObjectListener(obj, (t, e) => + { + switch (e) + { + case HierarchyEvent.ObjectDirty: + case HierarchyEvent.ForceInvalidate: + InvokeCallback(callback, t); + return true; + default: + return false; + } + }, target); + } + + cancel = CancelWrapper(cancel); + } + + private static void InvokeCallback(Action callback, object t) where T : class + { + try + { + callback((T)t); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + public C[] MonitorGetComponents(out IDisposable cancel, GameObject obj, Action callback, T target, + Func get, bool includeChildren) where T : class + { + cancel = default; + + C[] components = get(); + + Hierarchy.RegisterGameObjectListener(obj, (t, e) => + { + if (e == HierarchyEvent.ChildComponentsChanged && !includeChildren) return false; + + switch (e) + { + case HierarchyEvent.ChildComponentsChanged: + case HierarchyEvent.SelfComponentsChanged: + case HierarchyEvent.ForceInvalidate: + if (obj != null && components.SequenceEqual(get())) + { + return false; + } + else + { + InvokeCallback(callback, t); + return true; + } + default: + return false; + } + }, target); + + if (includeChildren) Hierarchy.EnableComponentMonitoring(obj); + + cancel = CancelWrapper(cancel); + + return components; + } + + public C MonitorGetComponent(out IDisposable cancel, GameObject obj, Action callback, T target, + Func get) where T : class + { + cancel = default; + + C component = get(); + + Hierarchy.RegisterGameObjectListener(obj, (t, e) => + { + switch (e) + { + case HierarchyEvent.SelfComponentsChanged: + case HierarchyEvent.ChildComponentsChanged: + case HierarchyEvent.ForceInvalidate: + if (obj != null && ReferenceEquals(component, get())) + { + return false; + } + else + { + InvokeCallback(callback, t); + return true; + } + default: + return false; + } + }, target); + + cancel = CancelWrapper(cancel); + + return component; + } + + class WrappedDisposable : IDisposable + { + private readonly int _targetThread; + private readonly SynchronizationContext _syncContext; + private IDisposable _orig; + + public WrappedDisposable(IDisposable orig, SynchronizationContext syncContext) + { + _orig = orig; + _targetThread = Thread.CurrentThread.ManagedThreadId; + _syncContext = syncContext; + } + + public void Dispose() + { + lock (this) + { + if (_orig == null) return; + + if (Thread.CurrentThread.ManagedThreadId == _targetThread) + { + _orig.Dispose(); + } + else + { + var orig = _orig; + _syncContext.Post(_ => orig.Dispose(), null); + } + + _orig = null; + } + } + } + + private IDisposable CancelWrapper(IDisposable orig) + { + return new WrappedDisposable(orig, _syncContext); + } + } +} \ No newline at end of file diff --git a/Editor/ChangeStream/ObjectWatcher.cs.meta b/Editor/ChangeStream/ObjectWatcher.cs.meta new file mode 100644 index 00000000..ea15eb7c --- /dev/null +++ b/Editor/ChangeStream/ObjectWatcher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 156bbc8e03114b12aea9ebb5753450f4 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/ChangeStream/ShadowGameObject.cs b/Editor/ChangeStream/ShadowGameObject.cs new file mode 100644 index 00000000..88fb6aee --- /dev/null +++ b/Editor/ChangeStream/ShadowGameObject.cs @@ -0,0 +1,455 @@ +#region + +using System; +using System.Collections.Generic; +using System.Threading; +using UnityEditor; +using UnityEngine; +using UnityEngine.SceneManagement; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + #region + + using UnityObject = Object; + + #endregion + + internal enum HierarchyEvent + { + /// + /// Fired when an unspecified changed may have happened to this object. + /// + ObjectDirty, + + /// + /// Fired when the parentage of this object has changed. + /// + PathChange, + + /// + /// Fired when the set or order of components on this object may have changed + /// + SelfComponentsChanged, + + /// + /// Fired when the set or order of components on this object or any children may have changed + /// + ChildComponentsChanged, + + /// + /// Fired when an object is destroyed or otherwise we're not quite sure what's going on. + /// + ForceInvalidate, + } + + internal class ShadowHierarchy + { + internal SynchronizationContext _syncContext; + internal Dictionary _gameObjects = new(); + internal Dictionary _otherObjects = new(); + internal ListenerSet _rootSetListener = new(); + + int lastPruned = Int32.MinValue; + + internal IDisposable RegisterRootSetListener(ListenerSet.Invokee invokee, object target) + { + return _rootSetListener.Register(invokee, target); + } + + internal IDisposable RegisterGameObjectListener(GameObject targetObject, + ListenerSet.Invokee invokee, + object target) + { + if (targetObject == null) return new NullDisposable(); + + ShadowGameObject shadowObject = ActivateShadowObject(targetObject); + + return shadowObject._listeners.Register(invokee, target); + } + + internal IDisposable RegisterObjectListener(UnityObject targetComponent, + ListenerSet.Invokee invokee, + object target) + { + if (targetComponent == null) return new NullDisposable(); + + if (!_otherObjects.TryGetValue(targetComponent.GetInstanceID(), out var shadowComponent)) + { + shadowComponent = new ShadowObject(targetComponent); + _otherObjects[targetComponent.GetInstanceID()] = shadowComponent; + } + + return shadowComponent._listeners.Register(invokee, target); + } + + internal class NullDisposable : IDisposable + { + public void Dispose() + { + // no-op + } + } + + /// + /// Activates monitoring for all children of the specified GameObject. This is needed to ensure child component + /// change notifications are propagated correctly. + /// + /// + internal void EnableComponentMonitoring(GameObject root) + { + var obj = ActivateShadowObject(root); + + EnableComponentMonitoring(obj); + } + + private void EnableComponentMonitoring(ShadowGameObject obj) + { + if (obj.ComponentMonitoring) return; + + foreach (Transform child in obj.GameObject.transform) + { + EnableComponentMonitoring(child.gameObject); + } + + // Enable the parent last to avoid nuisance notifications + obj.ComponentMonitoring = true; + } + + internal void EnablePathMonitoring(GameObject root) + { + var obj = ActivateShadowObject(root); + + while (obj != null) + { + obj.PathMonitoring = true; + obj = obj.Parent; + } + } + + private ShadowGameObject ActivateShadowObject(GameObject targetObject) + { + // An object is activated when it, or a parent, has a listener attached. + // An object is deactivated ("inert") when we traverse it and find no listeners in any of its children. + // Inert objects are skipped for path update notifications; however, we can't just delete them, because + // we may need to know about them for future structure change notifications at their parents. + int instanceId = targetObject.GetInstanceID(); + if (!_gameObjects.TryGetValue(instanceId, out var shadow)) + { + shadow = new ShadowGameObject(targetObject); + _gameObjects[instanceId] = shadow; + + shadow.Scene = targetObject.scene; + var parent = targetObject.transform.parent?.gameObject; + if (parent == null) + { + shadow.SetParent(null, false); + _rootSetListener.Fire(HierarchyEvent.ForceInvalidate); + } + else + { + // Don't fire notifications on initial creation + shadow.SetParent(ActivateShadowObject(parent), false); + } + } + + if (shadow.Parent?.ComponentMonitoring == true && !shadow.ComponentMonitoring) + { + EnableComponentMonitoring(shadow); + FireParentComponentChangeNotifications(shadow.Parent); + } + + return shadow; + } + + /// + /// Fires a notification that properties on a specific object (GameObject or otherwise) has changed. + /// + /// + internal void FireObjectChangeNotification(int instanceId) + { + if (_gameObjects.TryGetValue(instanceId, out var shadow)) + { + shadow._listeners.Fire(HierarchyEvent.ObjectDirty); + if (shadow.IsActive != shadow.GameObject.activeSelf) + { + shadow.IsActive = shadow.GameObject.activeSelf; + FirePathChangeNotifications(shadow); + } + } + + var component = EditorUtility.InstanceIDToObject(instanceId) as Component; + if (component != null) + { + // This event may have been a component reordering, so trigger a synthetic structure change event. + // TODO: Cache component positions? + var parentId = component.gameObject.GetInstanceID(); + FireStructureChangeEvent(parentId); + } + + if (_otherObjects.TryGetValue(instanceId, out var shadowComponent)) + { + shadowComponent._listeners.Fire(HierarchyEvent.ObjectDirty); + } + } + + /// + /// Fires a notification that the specified GameObject has a new parent. + /// + /// + internal void FireReparentNotification(int instanceId) + { + // Always activate on reparent. This is because we might be reparenting _into_ an active hierarchy. + var obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject; + ShadowGameObject shadow; + if (obj != null) + { + shadow = ActivateShadowObject(obj); + } + else + { + if (_gameObjects.TryGetValue(instanceId, out var _)) + { + FireDestroyNotification(instanceId); + } + + return; + } + + FireParentComponentChangeNotifications(shadow.Parent); + if (shadow.PathMonitoring) FirePathChangeNotifications(shadow); + + // Ensure the new parent is marked as dirty, in case this is a new object and we suppressed the dirty + // notifications. + if (shadow.Parent != null) shadow.Parent._listeners.Fire(HierarchyEvent.ObjectDirty); + + // Update parentage and refire + + var newParent = shadow.GameObject.transform.parent?.gameObject; + if (newParent == null) + { + shadow.Parent = null; + _rootSetListener.Fire(HierarchyEvent.ForceInvalidate); + } + else if (newParent != shadow.Parent?.GameObject) + { + if (shadow.Parent == null) _rootSetListener.Fire(HierarchyEvent.ForceInvalidate); + + shadow.Parent = ActivateShadowObject(newParent); + FireParentComponentChangeNotifications(shadow.Parent); + + var ptr = shadow.Parent; + while (ptr != null && !ptr.PathMonitoring) + { + ptr.PathMonitoring = true; + ptr = ptr.Parent; + } + } + + // This needs to run even if the parent did not change, just in case we did a just-in-time creation of this + // shadow object. + if (shadow.Parent?.ComponentMonitoring == true) EnableComponentMonitoring(shadow); + } + + private void FirePathChangeNotifications(ShadowGameObject shadow) + { + if (!shadow.PathMonitoring) return; + shadow._listeners.Fire(HierarchyEvent.PathChange); + foreach (var child in shadow.Children) + { + FirePathChangeNotifications(child); + } + } + + private void FireParentComponentChangeNotifications(ShadowGameObject obj) + { + while (obj != null) + { + obj._listeners.Fire(HierarchyEvent.ChildComponentsChanged); + obj = obj.Parent; + } + } + + internal void FireDestroyNotification(int instanceId) + { + if (_gameObjects.TryGetValue(instanceId, out var shadow)) + { + FireParentComponentChangeNotifications(shadow.Parent); + ForceInvalidateHierarchy(shadow); + } + } + + void ForceInvalidateHierarchy(ShadowGameObject obj) + { + obj._listeners.Fire(HierarchyEvent.ForceInvalidate); + _gameObjects.Remove(obj.InstanceID); + + foreach (var child in obj.Children) + { + ForceInvalidateHierarchy(child); + } + } + + internal void FireReorderNotification(int parentInstanceId) + { + if (!_gameObjects.TryGetValue(parentInstanceId, out var shadow)) + { + return; + } + + FireParentComponentChangeNotifications(shadow); + } + + internal void FireStructureChangeEvent(int instanceId) + { + if (!_gameObjects.TryGetValue(instanceId, out var shadow)) + { + return; + } + + shadow._listeners.Fire(HierarchyEvent.SelfComponentsChanged); + FireParentComponentChangeNotifications(shadow.Parent); + } + + internal void InvalidateAll() + { + var oldDict = _gameObjects; + _gameObjects = new Dictionary(); + + foreach (var shadow in oldDict.Values) + { + shadow._listeners.Fire(HierarchyEvent.ForceInvalidate); + } + + var oldComponents = _otherObjects; + _otherObjects = new Dictionary(); + + foreach (var shadow in oldComponents.Values) + { + shadow._listeners.Fire(HierarchyEvent.ForceInvalidate); + } + + _rootSetListener.Fire(HierarchyEvent.ForceInvalidate); + } + + /// + /// Assume that everything has changed for the specified object and its children. Fire off all relevant + /// notifications and rebuild state. + /// + /// + /// + public void InvalidateTree(int instanceId) + { + if (_gameObjects.TryGetValue(instanceId, out var shadow)) + { + shadow._listeners.Fire(HierarchyEvent.ForceInvalidate); + FireParentComponentChangeNotifications(shadow.Parent); + _gameObjects.Remove(instanceId); + + var parentGameObject = shadow.Parent?.GameObject; + + if (parentGameObject != null) + { + // Repair parent's child mappings + foreach (Transform child in parentGameObject.transform) + { + ActivateShadowObject(child.gameObject); + } + } + + // Finally recreate the target object, just in case it took up some objects from somewhere else + var gameObject = EditorUtility.InstanceIDToObject(instanceId) as GameObject; + if (gameObject != null) + { + ActivateShadowObject(gameObject); + } + } + } + + public void FireGameObjectCreate(int instanceId) + { + var obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject; + if (obj == null) return; + + var shadow = ActivateShadowObject(obj); + + // Ensure the new parent is marked as dirty + if (shadow.Parent != null) shadow.Parent._listeners.Fire(HierarchyEvent.ObjectDirty); + } + } + + internal class ShadowObject + { + internal int InstanceID { get; private set; } + internal UnityObject Object { get; private set; } + + internal ListenerSet _listeners = new ListenerSet(); + + internal ShadowObject(UnityObject component) + { + InstanceID = component.GetInstanceID(); + Object = component; + } + } + + /// + /// Represents a single GameObject in a loaded scene. This shadow copy will be retained, once an interest is + /// registered, until the GameObject is destroyed or scene unloaded. + /// + internal class ShadowGameObject + { + internal int InstanceID { get; private set; } + internal GameObject GameObject { get; private set; } + internal Scene Scene { get; set; } + private readonly Dictionary _children = new Dictionary(); + + public IEnumerable Children => _children.Values; + + + private ShadowGameObject _parent; + internal bool PathMonitoring { get; set; } = false; + internal bool ComponentMonitoring { get; set; } = false; + internal bool IsActive { get; set; } + + internal ShadowGameObject Parent + { + get => _parent; + set { SetParent(value, true); } + } + + + public void SetParent(ShadowGameObject parent, bool fireNotifications = true) + { + if (parent == _parent) return; + + if (_parent != null) + { + _parent._children.Remove(InstanceID); + // Fire off a property change notification for the parent itself + // TODO: tests + if (fireNotifications) _parent._listeners.Fire(HierarchyEvent.ObjectDirty); + } + + _parent = parent; + + if (_parent != null) + { + _parent._children[InstanceID] = this; + if (fireNotifications) _parent._listeners.Fire(HierarchyEvent.ObjectDirty); + } + } + + internal ListenerSet _listeners = new ListenerSet(); + + internal ShadowGameObject(GameObject gameObject) + { + InstanceID = gameObject.GetInstanceID(); + GameObject = gameObject; + Scene = gameObject.scene; + IsActive = gameObject.activeSelf; + } + } +} \ No newline at end of file diff --git a/Editor/ChangeStream/ShadowGameObject.cs.meta b/Editor/ChangeStream/ShadowGameObject.cs.meta new file mode 100644 index 00000000..0088a98a --- /dev/null +++ b/Editor/ChangeStream/ShadowGameObject.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 08dfb4befa154fd585bd4a3be94b3200 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/GlobalInit.cs b/Editor/GlobalInit.cs index 4061db98..f90c94e7 100644 --- a/Editor/GlobalInit.cs +++ b/Editor/GlobalInit.cs @@ -1,5 +1,6 @@ #region +using nadena.dev.ndmf.preview; using nadena.dev.ndmf.runtime; using UnityEditor; @@ -13,6 +14,12 @@ internal static class GlobalInit static GlobalInit() { RuntimeUtil.DelayCall = call => { EditorApplication.delayCall += () => call(); }; + + EditorApplication.delayCall += () => + { + var resolver = new PluginResolver(); + PreviewSession.Current = resolver.PreviewSession; + }; } } } \ No newline at end of file diff --git a/Editor/PreviewSystem.meta b/Editor/PreviewSystem.meta new file mode 100644 index 00000000..8f4ee21f --- /dev/null +++ b/Editor/PreviewSystem.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 76de2fe061d942b5b53fa9dee427dc20 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony.meta b/Editor/PreviewSystem/Harmony.meta new file mode 100644 index 00000000..8ecbdcf9 --- /dev/null +++ b/Editor/PreviewSystem/Harmony.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9f996c23d7ef47e69921d72865c76b60 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs b/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs new file mode 100644 index 00000000..c1d8bd37 --- /dev/null +++ b/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs @@ -0,0 +1,89 @@ +#region + +using System.Collections.Generic; +using System.Linq; +using HarmonyLib; +using JetBrains.Annotations; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal static class HandleUtilityPatches + { + internal static void Patch_FilterInstanceIDs(Harmony h) + { + var t_HandleUtility = AccessTools.TypeByName("UnityEditor.HandleUtility"); + var m_orig = AccessTools.Method(t_HandleUtility, "FilterInstanceIDs"); + + var m_prefix = AccessTools.Method(typeof(HandleUtilityPatches), "Prefix_FilterInstanceIDs"); + var m_postfix = AccessTools.Method(typeof(HandleUtilityPatches), "Postfix_FilterInstanceIDs"); + + h.Patch(original: m_orig, prefix: new HarmonyMethod(m_prefix), postfix: new HarmonyMethod(m_postfix)); + } + + [UsedImplicitly] + private static bool Prefix_FilterInstanceIDs( + ref IEnumerable gameObjects, + out int[] parentInstanceIDs, + out int[] childInstanceIDs + ) + { + gameObjects = RemapObjects(gameObjects); + parentInstanceIDs = childInstanceIDs = null; + return true; + } + + [UsedImplicitly] + private static void Postfix_FilterInstanceIDs( + ref IEnumerable gameObjects, + ref int[] parentInstanceIDs, + ref int[] childInstanceIDs + ) + { + var sess = PreviewSession.Current; + if (sess == null) return; + + HashSet newChildInstanceIDs = null; + + foreach (var parent in gameObjects) + { + foreach (var renderer in parent.GetComponentsInChildren()) + { + if (sess.OriginalToProxyRenderer.TryGetValue(renderer, out var proxy) && proxy != null) + { + if (newChildInstanceIDs == null) newChildInstanceIDs = new HashSet(childInstanceIDs); + newChildInstanceIDs.Add(proxy.GetInstanceID()); + } + } + } + + if (newChildInstanceIDs != null) + { + childInstanceIDs = newChildInstanceIDs.ToArray(); + } + } + + private static IEnumerable RemapObjects(IEnumerable objs) + { + var sess = PreviewSession.Current; + if (sess == null) return objs; + + return objs.Select( + obj => + { + if (obj == null) return obj; + if (sess.OriginalToProxyObject.TryGetValue(obj, out var proxy) && proxy != null) + { + return proxy.gameObject; + } + else + { + return obj; + } + } + ).ToArray(); + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs.meta b/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs.meta new file mode 100644 index 00000000..e86b9c36 --- /dev/null +++ b/Editor/PreviewSystem/Harmony/HandleUtilityPatches.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eae12856a2de4a82b02fd3109970791f +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs b/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs new file mode 100644 index 00000000..0053d792 --- /dev/null +++ b/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs @@ -0,0 +1,181 @@ +#region + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using HarmonyLib; +using JetBrains.Annotations; +using UnityEditor.IMGUI.Controls; +using UnityEngine; +using UnityEngine.SceneManagement; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal static class HierarchyViewPatches + { + private static readonly Type t_HierarchyProperty = AccessTools.TypeByName("UnityEditor.HierarchyProperty"); + private static readonly PropertyInfo p_pptrValue = AccessTools.Property(t_HierarchyProperty, "pptrValue"); + + private static FieldInfo f_m_Rows; // List + private static FieldInfo f_m_RowCount; // int + private static PropertyInfo p_objectPPTR; + + internal static void Patch(Harmony h) + { +#if MODULAR_AVATAR_DEBUG_HIDDEN + return; +#endif + var t_GameObjectTreeViewDataSource = AccessTools.TypeByName("UnityEditor.GameObjectTreeViewDataSource"); + var t_GameObjectTreeViewItem = AccessTools.TypeByName("UnityEditor.GameObjectTreeViewItem"); + + f_m_Rows = t_GameObjectTreeViewDataSource.GetField("m_Rows", + BindingFlags.NonPublic | BindingFlags.Instance); + f_m_RowCount = + t_GameObjectTreeViewDataSource.GetField("m_RowCount", BindingFlags.NonPublic | BindingFlags.Instance); + p_objectPPTR = t_GameObjectTreeViewItem.GetProperty("objectPPTR"); + + var m_orig = AccessTools.Method(t_GameObjectTreeViewDataSource, "InitTreeViewItem", + new[] + { + t_GameObjectTreeViewItem, + typeof(int), + typeof(Scene), + typeof(bool), + typeof(int), + typeof(Object), + typeof(bool), + typeof(int) + }); + var m_patch = AccessTools.Method(typeof(HierarchyViewPatches), nameof(Prefix_InitTreeViewItem)); + + h.Patch(original: m_orig, prefix: new HarmonyMethod(m_patch)); + + var m_InitRows = AccessTools.Method(t_GameObjectTreeViewDataSource, "InitializeRows"); + var m_transpiler = AccessTools.Method(typeof(HierarchyViewPatches), "Transpile_InitializeRows"); + + h.Patch(original: m_InitRows, + transpiler: new HarmonyMethod(m_transpiler), + postfix: new HarmonyMethod(AccessTools.Method(typeof(HierarchyViewPatches), "Postfix_InitializeRows")), + prefix: new HarmonyMethod(AccessTools.Method(typeof(HierarchyViewPatches), "Prefix_InitializeRows")) + ); + } + + private static int skipped = 0; + + private static void Prefix_InitializeRows() + { + skipped = 0; + } + + [UsedImplicitly] + private static void Postfix_InitializeRows(object __instance) + { + var rows = (IList)f_m_Rows.GetValue(__instance); + + var rowCount = (int)f_m_RowCount.GetValue(__instance); + + f_m_RowCount.SetValue(__instance, rowCount - skipped); + + for (int i = 0; i < skipped; i++) + { + rows.RemoveAt(rows.Count - 1); + } + } + + [UsedImplicitly] + private static IEnumerable Transpile_InitializeRows(IEnumerable instructions, + ILGenerator generator) + { + foreach (var c in Transpile_InitializeRows0(instructions, generator)) + { + //Debug.Log(c); + yield return c; + } + } + + [UsedImplicitly] + private static IEnumerable Transpile_InitializeRows0(IEnumerable instructions, + ILGenerator generator) + { + var m_shouldLoop = AccessTools.Method(typeof(HierarchyViewPatches), "ShouldLoop"); + + var m_Next = AccessTools.Method(t_HierarchyProperty, "Next", new[] { typeof(int[]) }); + + foreach (var c in instructions) + { + if (c.Is(OpCodes.Callvirt, m_Next)) + { + var loopLabel = generator.DefineLabel(); + var stash_arg = generator.DeclareLocal(typeof(int[])); + var stash_obj = generator.DeclareLocal(t_HierarchyProperty); + + yield return new CodeInstruction(OpCodes.Stloc, stash_arg); + yield return new CodeInstruction(OpCodes.Stloc, stash_obj); + + var tmp = new CodeInstruction(OpCodes.Ldloc, stash_obj); + tmp.labels.Add(loopLabel); + yield return tmp; + + yield return new CodeInstruction(OpCodes.Ldloc, stash_arg); + yield return new CodeInstruction(OpCodes.Call, m_Next); + + // Check if this item should be ignored. + yield return new CodeInstruction(OpCodes.Ldloc, stash_obj); + yield return new CodeInstruction(OpCodes.Call, m_shouldLoop); + yield return new CodeInstruction(OpCodes.Brtrue_S, loopLabel); + } + else + { + yield return c; + } + } + } + + [UsedImplicitly] + private static bool ShouldLoop(object hierarchyProperty) + { + var sess = PreviewSession.Current; + if (sess == null) return false; + + if (hierarchyProperty == null) return false; + + var pptrValue = p_pptrValue.GetValue(hierarchyProperty); + if (pptrValue == null) return false; + + var skip = sess.ProxyToOriginalObject.ContainsKey((GameObject)pptrValue); + if (skip) skipped++; + + return skip; + } + + private static bool Prefix_InitTreeViewItem( + object __instance, + ref object item, + int itemID, + Scene scene, + bool isSceneHeader, + int colorCode, + Object pptrObject, + ref bool hasChildren, + int depth + ) + { + var sess = PreviewSession.Current; + if (sess == null) return true; + + if (pptrObject == null || isSceneHeader) return true; + + if (hasChildren && sess.ProxyToOriginalObject.ContainsKey((GameObject)pptrObject)) + { + // See if there are any other children... + hasChildren = ((GameObject)pptrObject).transform.childCount > 1; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs.meta b/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs.meta new file mode 100644 index 00000000..c87d2e6e --- /dev/null +++ b/Editor/PreviewSystem/Harmony/HierarchyViewPatches.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4b540a556667468dbfae0893180dbdb2 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/Patcher.cs b/Editor/PreviewSystem/Harmony/Patcher.cs new file mode 100644 index 00000000..a6e9cc33 --- /dev/null +++ b/Editor/PreviewSystem/Harmony/Patcher.cs @@ -0,0 +1,41 @@ +#region + +using System; +using HarmonyLib; +using UnityEditor; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal sealed class PatchLoader + { + private static readonly Action[] patches = + { + HandleUtilityPatches.Patch_FilterInstanceIDs, + PickingObjectPatch.Patch, + HierarchyViewPatches.Patch + }; + + [InitializeOnLoadMethod] + static void ApplyPatches() + { + var harmony = new Harmony("nadena.dev.ndmf.core.preview"); + + foreach (var patch in patches) + { + try + { + patch(harmony); + } + catch (Exception e) + { + Debug.LogException(e); + } + } + + AssemblyReloadEvents.beforeAssemblyReload += () => { harmony.UnpatchAll(); }; + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/Patcher.cs.meta b/Editor/PreviewSystem/Harmony/Patcher.cs.meta new file mode 100644 index 00000000..2367155c --- /dev/null +++ b/Editor/PreviewSystem/Harmony/Patcher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7ad14393462d40afa5025de0dedf8f3c +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs b/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs new file mode 100644 index 00000000..0262ab9c --- /dev/null +++ b/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs @@ -0,0 +1,82 @@ +#region + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using HarmonyLib; +using UnityEngine; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal static class PickingObjectPatch + { + private static Type t_PickingObject = AccessTools.TypeByName("UnityEditor.PickingObject"); + + private static Type l_PickingObject = + typeof(List<>).MakeGenericType(new[] { t_PickingObject }); + + private static ConstructorInfo ctor_l = AccessTools.Constructor(l_PickingObject); + + private static ConstructorInfo ctor_PickingObject = + AccessTools.Constructor(t_PickingObject, new[] { typeof(Object), typeof(int) }); + + private static PropertyInfo p_materialIndex = AccessTools.Property(t_PickingObject, "materialIndex"); + + private static MethodInfo m_TryGetGameObject = AccessTools.Method(t_PickingObject, "TryGetGameObject"); + + internal static void Patch(Harmony h) + { + var t_PickingObject = AccessTools.TypeByName("UnityEditor.PickingObject"); + var ctor_PickingObject = AccessTools.Constructor(t_PickingObject, new[] { typeof(Object), typeof(int) }); + + var t_SceneViewPicking = AccessTools.TypeByName("UnityEditor.SceneViewPicking"); + var m_GetAllOverlapping = AccessTools.Method(t_SceneViewPicking, "GetAllOverlapping"); + + var m_postfix = AccessTools.Method(typeof(PickingObjectPatch), nameof(Postfix_GetAllOverlapping)); + + h.Patch(original: m_GetAllOverlapping, postfix: new HarmonyMethod(m_postfix)); + } + + private static void Postfix_GetAllOverlapping(ref object __result) + { + var erased = (IEnumerable)__result; + + var sess = PreviewSession.Current; + if (sess == null) return; + + var list = (IList)ctor_l.Invoke(new object[0]); + + foreach (var obj in erased) + { + if (obj == null) + { + list.Add(obj); + continue; + } + + var args = new object[] { null }; + if ((bool)m_TryGetGameObject.Invoke(obj, args)) + { + var go = args[0] as GameObject; + if (go != null && sess.ProxyToOriginalObject.TryGetValue(go, out var original)) + { + list.Add(ctor_PickingObject.Invoke(new[] + { + original, + p_materialIndex.GetValue(obj) + })); + continue; + } + } + + list.Add(obj); + } + + __result = list; + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs.meta b/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs.meta new file mode 100644 index 00000000..5bb69c97 --- /dev/null +++ b/Editor/PreviewSystem/Harmony/PickingObjectPatch.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1fcf08c6e9b946ff8d9162f35edfc2c2 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/IRenderFilter.cs b/Editor/PreviewSystem/IRenderFilter.cs new file mode 100644 index 00000000..742f9de4 --- /dev/null +++ b/Editor/PreviewSystem/IRenderFilter.cs @@ -0,0 +1,156 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using nadena.dev.ndmf.rq; +using UnityEngine; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + /// + /// Represents the current state of a mesh. IRenderFilters mutate this state in order to perform heavyweight portions + /// of a preview rendering operation. + /// + /// TODO: This API is likely to change radically in future alpha releases. + /// + public sealed class MeshState + { + internal long NodeId { get; } + + /// + /// The original renderer that this MeshState was born from + /// + public Renderer Original { get; } + + private bool _meshIsOwned; + private Mesh _mesh; + + /// + /// The current mesh associated with this renderer. Important: When setting this value, you must set to a _new_ + /// mesh. This new mesh will be destroyed when the preview state is recomputed. + /// + public Mesh Mesh + { + get => _mesh; + set + { + _meshIsOwned = true; + _mesh = value; + if (_mesh != null) _mesh.name = "Mesh #" + NodeId; + } + } + + private bool _materialsAreOwned; + private ImmutableList _materials; + + /// + /// The materials associated with this mesh. Important: When setting this value, you must set to a list of entirely + /// _new_ materials. These new materials will be destroyed when the preview state is recomputed. + /// + public ImmutableList Materials + { + get => _materials; + set + { + _materials = value; + _materialsAreOwned = true; + } + } + + /// + /// An event which will be invoked when the mesh state is discarded. This can be used to destroy any resources + /// you've created other than Meshes and Materials - e.g. textures. + /// + public event Action OnDispose; + + private bool _disposed = false; + + internal MeshState(Renderer renderer) + { + Original = renderer; + + if (renderer is SkinnedMeshRenderer smr) + { + Mesh = Object.Instantiate(smr.sharedMesh); + } + else if (renderer is MeshRenderer mr) + { + Mesh = Object.Instantiate(mr.GetComponent().sharedMesh); + } + + Materials = renderer.sharedMaterials.Select(m => new Material(m)).ToImmutableList(); + } + + private MeshState(MeshState state, long nodeId) + { + Original = state.Original; + _mesh = state._mesh; + _materials = state._materials; + NodeId = nodeId; + } + + // Not IDisposable as we don't want to expose that as a public API + internal void Dispose() + { + if (_disposed) return; + + if (_meshIsOwned) Object.DestroyImmediate(Mesh); + if (_materialsAreOwned) + { + foreach (var material in Materials) + { + Object.DestroyImmediate(material); + } + } + + OnDispose?.Invoke(); + } + + internal MeshState Clone(long nodeId) + { + return new MeshState(this, nodeId); + } + } + + /// + /// An interface implemented by components which need to modify the appearance of a renderer for preview purposes. + /// + public interface IRenderFilter + { + /// + /// A list of lists of renderers this filter operates on. The outer list is a list of renderer groups; each + /// group of renderers will be passed to this filter as one unit, allowing for cross-renderer operation such + /// as texture atlasing. + /// + public ReactiveValue>> TargetGroups { get; } + + /// + /// Performs any heavyweight operations required to prepare the renderers for preview. This method is called + /// once when the preview pipeline is set up. You can use the attached ComputeContext to arrange for the + /// preview pipeline to be recomputed when something changes with the initial state of the renderer. + /// + /// + /// + /// + public Task MutateMeshData(IList state, ComputeContext context) + { + return Task.CompletedTask; + } + + /// + /// Called on each frame to perform lighter-weight operations on the renderers, such as manipulating blend shapes + /// or the bones array. + /// + /// + /// + public void OnFrame(Renderer original, Renderer proxy) + { + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/IRenderFilter.cs.meta b/Editor/PreviewSystem/IRenderFilter.cs.meta new file mode 100644 index 00000000..25826298 --- /dev/null +++ b/Editor/PreviewSystem/IRenderFilter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7402f7b9799943388df99b19bc982f7b +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/PreviewSession.cs b/Editor/PreviewSystem/PreviewSession.cs new file mode 100644 index 00000000..a31009ee --- /dev/null +++ b/Editor/PreviewSystem/PreviewSession.cs @@ -0,0 +1,145 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using nadena.dev.ndmf.rq; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + /// + /// TODO: Document + /// + /// (For now, this isn't very useful; use `DeclaringPass.PreviewingWith` instead) + /// + public class PreviewSession : IDisposable + { + #region Static State + + /// + /// The PreviewSession used for any cameras not overriden using `OverrideCamera`. + /// + public static PreviewSession Current { get; set; } = null; + + + /// + /// Applies this PreviewSession to the `target` camera. + /// + /// + public void OverrideCamera(Camera target) + { + throw new NotImplementedException(); + } + + /// + /// Removes all camera overrides from the `target` camera. + /// + /// + public static void ClearCameraOverride(Camera target) + { + throw new NotImplementedException(); + } + + #endregion + + internal IEnumerable<(Renderer, Renderer)> GetReplacements() + { + return _session?.OnPreCull() ?? Enumerable.Empty<(Renderer, Renderer)>(); + } + + internal ImmutableDictionary OriginalToProxyRenderer => + _session?.OriginalToProxyRenderer ?? ImmutableDictionary.Empty; + + internal ImmutableDictionary OriginalToProxyObject => + _session?.OriginalToProxyObject ?? ImmutableDictionary.Empty; + + internal ImmutableDictionary ProxyToOriginalObject => + _session?.ProxyToOriginalObject ?? ImmutableDictionary.Empty; + + private readonly Sequencer _sequence = new Sequencer(); + + private Dictionary _filters = new(); + + private ProxySession _session; + + private ReactiveField> _resolved; + + public PreviewSession() + { + _resolved = new ReactiveField>( + ImmutableList.Empty + ); + + _session = new ProxySession(_resolved.AsReactiveValue()); + } + + /// + /// Sets the order in which mesh mutations are executed. Any sequence points not listed in this sequence will + /// be executed after these registered points, in `AddMutator` invocation order. + /// + /// + public void SetSequence(IEnumerable sequencePoints) + { + _sequence.SetSequence(sequencePoints); + + RebuildSequence(); + } + + public IDisposable AddMutator(SequencePoint sequencePoint, IRenderFilter filter) + { + _sequence.AddPoint(sequencePoint); + + _filters.Add(sequencePoint, filter); + + RebuildSequence(); + + return new RemovalDisposable(this, sequencePoint); + } + + private class RemovalDisposable : IDisposable + { + private PreviewSession _session; + private SequencePoint _point; + + public RemovalDisposable(PreviewSession session, SequencePoint point) + { + _session = session; + _point = point; + } + + public void Dispose() + { + _session._filters.Remove(_point); + _session.RebuildSequence(); + } + } + + void RebuildSequence() + { + var sequence = _sequence.Sequence; + var filters = sequence.Select(p => _filters.GetValueOrDefault(p)).Where(f => f != null).ToImmutableList(); + + _resolved.Value = filters; + } + + /// + /// Returns a new PreviewSession which inherits all mutators from the parent session. Any mutators added to this + /// new session run after the parent session's mutators. + /// + /// + /// + public PreviewSession Fork() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/PreviewSession.cs.meta b/Editor/PreviewSystem/PreviewSession.cs.meta new file mode 100644 index 00000000..d56cea44 --- /dev/null +++ b/Editor/PreviewSystem/PreviewSession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 49d69a234a9b41188b774b2804934e0c +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/ProxyManager.cs b/Editor/PreviewSystem/ProxyManager.cs new file mode 100644 index 00000000..a5056272 --- /dev/null +++ b/Editor/PreviewSystem/ProxyManager.cs @@ -0,0 +1,69 @@ +#region + +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + /// + /// Tracks the proxy meshes created by the preview system. + /// + internal static class ProxyManager + { + [InitializeOnLoadMethod] + private static void Initialize() + { + Camera.onPreCull += OnPreCull; + Camera.onPostRender += OnPostRender; + EditorSceneManager.sceneSaving += (_, _) => ResetStates(); + AssemblyReloadEvents.beforeAssemblyReload += ResetStates; + } + + private static List<(Renderer, bool)> _resetActions = new(); + + private static void OnPostRender(Camera cam) + { + ResetStates(); + } + + private static void OnPreCull(Camera cam) + { + ResetStates(); + + if (EditorApplication.isPlayingOrWillChangePlaymode) return; + + var sess = PreviewSession.Current; + if (sess == null) return; + + foreach (var (original, replacement) in sess.GetReplacements()) + { + if (original == null || replacement == null || !original.enabled || + !original.gameObject.activeInHierarchy) + { + if (replacement != null) replacement.forceRenderingOff = true; + continue; + } + + _resetActions.Add((original, false)); + _resetActions.Add((replacement, true)); + + replacement.forceRenderingOff = false; + original.forceRenderingOff = true; + } + } + + private static void ResetStates() + { + foreach (var (renderer, state) in _resetActions) + { + if (renderer != null) renderer.forceRenderingOff = state; + } + + _resetActions.Clear(); + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/ProxyManager.cs.meta b/Editor/PreviewSystem/ProxyManager.cs.meta new file mode 100644 index 00000000..a8d707d6 --- /dev/null +++ b/Editor/PreviewSystem/ProxyManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b068eb5455ea44c5ad2c8f647d9026dc +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering.meta b/Editor/PreviewSystem/Rendering.meta new file mode 100644 index 00000000..2e279f38 --- /dev/null +++ b/Editor/PreviewSystem/Rendering.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6a659c6fb8074b9db08a2d4da342f2cc +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/NodeGraph.cs b/Editor/PreviewSystem/Rendering/NodeGraph.cs new file mode 100644 index 00000000..186a95eb --- /dev/null +++ b/Editor/PreviewSystem/Rendering/NodeGraph.cs @@ -0,0 +1,40 @@ +#region + +using System; +using System.Collections.Generic; +using System.Linq; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal class NodeGraph + { + private Dictionary _nodes = new(); + + public ProxyNode GetOrCreate(ProxyNodeKey key, Func OnMissing) + { + if (!_nodes.TryGetValue(key, out var node) || node.Invalidated || node.PrepareTask.IsFaulted) + { + node = OnMissing(); + _nodes[key] = node; + } + + return node; + } + + public void Retain(ISet nodesToRetain) + { + foreach (var key in _nodes.Keys.ToList()) + { + if (!nodesToRetain.Contains(key)) + { + var node = _nodes[key]; + _nodes.Remove(key); + + node.Dispose(); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/NodeGraph.cs.meta b/Editor/PreviewSystem/Rendering/NodeGraph.cs.meta new file mode 100644 index 00000000..84160cc2 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/NodeGraph.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 61b7a0313a584f89a2c94453d596f264 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyNode.cs b/Editor/PreviewSystem/Rendering/ProxyNode.cs new file mode 100644 index 00000000..7694dc8e --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyNode.cs @@ -0,0 +1,171 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using nadena.dev.ndmf.rq; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal struct ProxyNodeKey + { + public IRenderFilter Filter; + public ImmutableList Sources; // Sorted + + public ProxyNodeKey(Renderer r) + { + Filter = null; + Sources = ImmutableList.Empty.Add(r.GetInstanceID()); + } + + public ProxyNodeKey(IRenderFilter filter, IEnumerable sources) + { + Filter = filter; + Sources = sources.OrderBy(t => t).ToImmutableList(); + } + + public bool Equals(ProxyNodeKey other) + { + return ReferenceEquals(Filter, other.Filter) && Sources.SequenceEqual(other.Sources); + } + + public override bool Equals(object obj) + { + return obj is ProxyNodeKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Filter != null ? Filter.GetHashCode() : 0); + + foreach (var source in Sources) + { + hashCode = hashCode * 397 ^ source.GetHashCode(); + } + + return hashCode; + } + } + } + + internal class ProxyNode : IDisposable + { + private static long IdSequence = Int32.MaxValue; + + public long Id { get; } + public ProxyNodeKey Key { get; private set; } + public IRenderFilter Filter => Key.Filter; + + public ImmutableDictionary SourceNodes { get; } + public Task> PrepareTask { get; } + + private readonly TaskCompletionSource _invalidater = new(); + public Task InvalidatedTask => _invalidater.Task; + + public bool Invalidated => InvalidatedTask.IsCompleted; + public bool Disposed { get; private set; } + + public ProxyNode(Renderer renderer) + { + Id = renderer.GetInstanceID(); + SourceNodes = ImmutableDictionary.Empty; + Key = new ProxyNodeKey(null, new long[] { renderer.GetInstanceID() }); + PrepareTask = Task.FromResult(ImmutableDictionary.Empty.Add( + renderer, + new MeshState(renderer) + )); + } + + public ProxyNode( + IRenderFilter filter, + IImmutableList renderGroup, + ImmutableDictionary sourceNodes + ) + { + Id = (IdSequence++); + SourceNodes = renderGroup.ToImmutableDictionary(r => r, r => sourceNodes[r]); + + Key = new ProxyNodeKey(filter, renderGroup.Select(r => sourceNodes[r].Id)); + + foreach (var node in SourceNodes.Values) + { + node.InvalidatedTask.ContinueWith(_ => + { + Invalidate(); + }); + } + + using (new SyncContextScope(ReactiveQueryScheduler.SynchronizationContext)) + { + ComputeContext context = new ComputeContext(() => "ProxyNode"); + context.OnInvalidate = InvalidatedTask; + context.Invalidate = () => + { + Invalidate(); + }; + + PrepareTask = Task.Factory.StartNew( + async () => + { + // Wait for all tasks to complete, or for invalidation + var inputTasks = SourceNodes.Values.Select(n => n.PrepareTask).ToList(); + var allInputReady = Task.WhenAll(inputTasks).PreventRecursion(); + await Task.WhenAny(allInputReady, InvalidatedTask); + + if (Invalidated) return null; + + var inputMeshes = SourceNodes.Select(kvp => + { + var node = kvp.Value; + var state = kvp.Value.PrepareTask.Result[kvp.Key]; + + return state.Clone(Id); + }).ToList(); + + await filter.MutateMeshData(inputMeshes, context); + + return inputMeshes.ToImmutableDictionary(m => m.Original); + }, + context.CancellationToken, + TaskCreationOptions.None, + TaskScheduler.FromCurrentSynchronizationContext() + ).Unwrap(); + } + } + + public void Invalidate() + { + _invalidater.TrySetResult(null); + } + + public void Dispose() + { + Invalidate(); + Disposed = true; + + PrepareTask.ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + { + var value = t.Result; + if (value != null) + { + foreach (var meshState in value.Values) + { + meshState.Dispose(); + } + } + } + }); + + // clear private state? + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyNode.cs.meta b/Editor/PreviewSystem/Rendering/ProxyNode.cs.meta new file mode 100644 index 00000000..aad98b9b --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 650c1fad766d4e43b7fc1b16e6639854 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyObjectController.cs b/Editor/PreviewSystem/Rendering/ProxyObjectController.cs new file mode 100644 index 00000000..298309c2 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyObjectController.cs @@ -0,0 +1,145 @@ +#region + +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal class ProxyObjectController : IDisposable + { + private readonly Renderer _originalRenderer; + private Renderer _replacementRenderer; + + internal ProxyPipeline Pipeline { get; set; } + internal Renderer Renderer => _replacementRenderer; + public bool IsValid => _originalRenderer != null && _replacementRenderer != null; + + public ProxyObjectController(Renderer originalRenderer) + { + _originalRenderer = originalRenderer; + + CreateReplacementObject(); + } + + private void UpdateRenderer() + { + MeshState state = Pipeline?.GetState(_originalRenderer); + SkinnedMeshRenderer smr = null; + + if (_replacementRenderer == null || _originalRenderer == null) + { + Pipeline?.Invalidate(); + return; + } + + if (_originalRenderer is SkinnedMeshRenderer smr_) + { + smr = smr_; + + var replacementSMR = (SkinnedMeshRenderer)_replacementRenderer; + replacementSMR.sharedMesh = state?.Mesh ?? smr_.sharedMesh; + replacementSMR.bones = smr_.bones; + } + else + { + var filter = _replacementRenderer.GetComponent(); + filter.sharedMesh = state?.Mesh ?? _originalRenderer.GetComponent().sharedMesh; + } + + _replacementRenderer.sharedMaterials = state?.Materials?.ToArray() ?? _originalRenderer.sharedMaterials; + + var target = _replacementRenderer; + var original = _originalRenderer; + + if (target.gameObject.scene != original.gameObject.scene && + original.gameObject.scene.IsValid()) + { + SceneManager.MoveGameObjectToScene(target.gameObject, original.gameObject.scene); + } + + target.transform.position = original.transform.position; + target.transform.rotation = original.transform.rotation; + + target.localBounds = original.localBounds; + if (target is SkinnedMeshRenderer targetSMR && original is SkinnedMeshRenderer originalSMR) + { + targetSMR.rootBone = originalSMR.rootBone; + targetSMR.quality = originalSMR.quality; + + if (targetSMR.sharedMesh != null) + { + var blendShapeCount = targetSMR.sharedMesh.blendShapeCount; + for (var i = 0; i < blendShapeCount; i++) + { + targetSMR.SetBlendShapeWeight(i, originalSMR.GetBlendShapeWeight(i)); + } + } + } + + target.shadowCastingMode = original.shadowCastingMode; + target.receiveShadows = original.receiveShadows; + target.lightProbeUsage = original.lightProbeUsage; + target.reflectionProbeUsage = original.reflectionProbeUsage; + target.probeAnchor = original.probeAnchor; + target.motionVectorGenerationMode = original.motionVectorGenerationMode; + target.allowOcclusionWhenDynamic = original.allowOcclusionWhenDynamic; + + Pipeline?.RunOnFrame(_originalRenderer, _replacementRenderer); + } + + private bool CreateReplacementObject() + { + var replacementGameObject = new GameObject("Proxy renderer for " + _originalRenderer.gameObject.name); + replacementGameObject.hideFlags = HideFlags.DontSave; + +#if MODULAR_AVATAR_DEBUG_HIDDEN + replacementGameObject.hideFlags = HideFlags.DontSave; +#endif + + replacementGameObject.AddComponent().KeepAlive = this; + + if (_originalRenderer is SkinnedMeshRenderer smr) + { + _replacementRenderer = replacementGameObject.AddComponent(); + } + else if (_originalRenderer is MeshRenderer mr) + { + _replacementRenderer = replacementGameObject.AddComponent(); + replacementGameObject.AddComponent(); + } + else + { + Debug.Log("Unsupported renderer type: " + _replacementRenderer.GetType()); + Object.DestroyImmediate(replacementGameObject); + return true; + } + + return false; + } + + /// + /// + /// + /// (original, replacement renderer) + public (Renderer, Renderer) OnPreCull() + { + UpdateRenderer(); + + return (_originalRenderer, _replacementRenderer); + } + + public void Dispose() + { + if (_replacementRenderer != null) + { + Object.DestroyImmediate(_replacementRenderer.gameObject); + _replacementRenderer = null; + } + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyObjectController.cs.meta b/Editor/PreviewSystem/Rendering/ProxyObjectController.cs.meta new file mode 100644 index 00000000..89ec2418 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyObjectController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 57a5c633bf74444797067c679ce197ac +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyPipeline.cs b/Editor/PreviewSystem/Rendering/ProxyPipeline.cs new file mode 100644 index 00000000..5f093ec4 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyPipeline.cs @@ -0,0 +1,196 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using nadena.dev.ndmf.rq; +using UnityEditor; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal enum PipelineStatus + { + NotReady, + Ready, + Invalidated, + Disposed + } + + /// + /// Represents a single, instantiated pipeline for building and maintaining all proxy objects. + /// + internal class ProxyPipeline + { + private List<(IRenderFilter, ImmutableList)> _filterGroups; + private Dictionary> _rendererToFilters; + private ImmutableDictionary _meshLeaves; + + private TaskCompletionSource _invalidater = new(); + public Task InvalidatedTask => _invalidater.Task; + public bool Invalidated => InvalidatedTask.IsCompleted; + + private Task BuildPipelineTask; + + private bool _disposeCalled; + private Task _disposeTask; + + public bool BuildCompleted => BuildPipelineTask.IsCompleted; + public bool Aborted => BuildPipelineTask.IsCompleted && _meshLeaves == null; + + public IImmutableSet Renderers => _meshLeaves.Keys.ToImmutableHashSet(); + + private IImmutableList Nodes = ImmutableList.Empty; + + public ProxyPipeline(NodeGraph graph, IEnumerable filters) + { + using (new SyncContextScope(ReactiveQueryScheduler.SynchronizationContext)) + { + BuildPipelineTask = Build(graph, filters).ContinueWith(t => + { + if (t.IsFaulted) + { + Debug.LogException(t.Exception); + } + + EditorApplication.delayCall += SceneView.RepaintAll; + }); + } + } + + public void Invalidate() + { + _invalidater.TrySetResult(null); + } + + private async Task Build(NodeGraph graph, IEnumerable filters) + { + var ctx = new ComputeContext(() => "Preview pipeline: Construct pipeline"); + + ctx.Invalidate = () => _invalidater.TrySetResult(null); + ctx.OnInvalidate = InvalidatedTask; + + filters = filters.ToList(); + + _filterGroups = await CollectInterestingRenderers(filters); + + _rendererToFilters = new Dictionary>(); + foreach (var group in _filterGroups) + { + foreach (var renderer in group.Item2) + { + if (!_rendererToFilters.TryGetValue(renderer, out var list)) + { + list = new List(); + _rendererToFilters.Add(renderer, list); + } + + list.Add(group.Item1); + } + } + + var allRenderers = _filterGroups.SelectMany(p => p.Item2).ToHashSet(); + var nodes = ImmutableList.Empty.ToBuilder(); + + var leaves = ImmutableDictionary.Empty; + foreach (var renderer in allRenderers) + { + var node = graph.GetOrCreate(new ProxyNodeKey(renderer), () => new ProxyNode(renderer)); + leaves = leaves.Add(renderer, node); + nodes.Add(node.Key); + _ = node.InvalidatedTask.ContinueWith(_ => Invalidate()); + } + + if (Invalidated) + { + // Abort ASAP + return; + } + + foreach (var pair in _filterGroups) + { + var (filter, sourceRenderers) = pair; + var sources = sourceRenderers.Select(r => leaves[r].Id); + var key = new ProxyNodeKey(filter, sources); + + var node = graph.GetOrCreate(key, () => new ProxyNode(filter, sourceRenderers, leaves)); + nodes.Add(node.Key); + _ = node.InvalidatedTask.ContinueWith(_ => Invalidate()); + + foreach (var source in sourceRenderers) + { + leaves = leaves.SetItem(source, node); + } + } + + _meshLeaves = leaves; + Nodes = nodes.ToImmutable(); + } + + private async Task)>> CollectInterestingRenderers( + IEnumerable filters) + { + var ctx = new ComputeContext(() => "Preview pipeline: Collect interesting renderers"); + + ctx.Invalidate = () => _invalidater.TrySetResult(null); + ctx.OnInvalidate = InvalidatedTask; + + var result = new List<(IRenderFilter, ImmutableList)>(); + foreach (var filter in filters) + { + var groups = await ctx.Observe(filter.TargetGroups); + if (groups.Count == 0) continue; + + // TODO: Validate groups are non-overlapping + + foreach (var group in groups) + { + if (group.Count == 0) continue; + result.Add((filter, group.ToImmutableList())); + } + } + + return result; + } + + + public MeshState GetState(Renderer originalRenderer) + { + if (_disposeCalled) throw new ObjectDisposedException("ProxyPipeline"); + if (!BuildCompleted) throw new InvalidOperationException("Pipeline not ready"); + + if (_meshLeaves.TryGetValue(originalRenderer, out var node)) + { + if (node.PrepareTask.IsCompleted && + node.PrepareTask.Result?.TryGetValue(originalRenderer, out var state) == true) + { + return state; + } + } + + return null; + } + + public void RunOnFrame(Renderer original, Renderer replacement) + { + var filters = _rendererToFilters[original]; + + foreach (var filter in filters) + { + filter.OnFrame(original, replacement); + } + } + + public void CollectNodes(HashSet toRetain) + { + foreach (var node in Nodes) + { + toRetain.Add(node); + } + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxyPipeline.cs.meta b/Editor/PreviewSystem/Rendering/ProxyPipeline.cs.meta new file mode 100644 index 00000000..2807ce81 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxyPipeline.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cb563be3da564c819f5a651fe11ace1d +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxySession.cs b/Editor/PreviewSystem/Rendering/ProxySession.cs new file mode 100644 index 00000000..ece7a2e4 --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxySession.cs @@ -0,0 +1,154 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using nadena.dev.ndmf.rq; +using UnityEditor; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal class ProxySession : IObserver>, IDisposable + { + private ReactiveValue> _filters; + private NodeGraph _graph = new(); + private ProxyPipeline _active, _next; + + private IDisposable _unsubscribe; + + private Dictionary _proxyControllers = new(); + private List<(Renderer, Renderer)> activeRenderers = new(); + + internal ImmutableDictionary OriginalToProxyRenderer = + ImmutableDictionary.Empty; + + internal ImmutableDictionary OriginalToProxyObject = + ImmutableDictionary.Empty; + + internal ImmutableDictionary ProxyToOriginalObject = + ImmutableDictionary.Empty; + + public ProxySession(ReactiveValue> filters) + { + _filters = filters; + + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + _unsubscribe = filters.Subscribe(this); + } + + private void OnPlayModeStateChanged(PlayModeStateChange obj) + { + _active = _next = null; + _graph.Retain(ImmutableHashSet.Empty); + } + + public void Dispose() + { + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; + _unsubscribe?.Dispose(); + } + + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + Debug.LogException(error); + } + + public void OnNext(ImmutableList filters) + { + _active?.Invalidate(); + _next?.Invalidate(); + } + + public IEnumerable<(Renderer, Renderer)> OnPreCull() + { + if (_active == null || _active.Invalidated) + { + if (_next != null) + { + if (_next.Aborted) _next = null; + else if (_next.BuildCompleted) + { + _active = _next; + _next = null; + CollectNodes(); + RebuildRenderers(); + } + } + } + + if (_active == null || _active.Invalidated) + { + if (_next == null && _filters.TryGetValue(out var list)) + { + _next = new ProxyPipeline(_graph, list); + } + } + + if (_active is not { BuildCompleted: true }) + { + return Array.Empty<(Renderer, Renderer)>(); + } + + foreach (var poc in _proxyControllers.Values) + { + poc.OnPreCull(); + } + + return activeRenderers; + } + + private void RebuildRenderers() + { + Dictionary retain = new(); + + activeRenderers.Clear(); + + var originalToProxyObject = ImmutableDictionary.Empty.ToBuilder(); + var proxyToOriginalObject = ImmutableDictionary.Empty.ToBuilder(); + var originalToProxyRenderer = ImmutableDictionary.Empty.ToBuilder(); + + foreach (var srcRenderer in _active.Renderers) + { + if (_proxyControllers.TryGetValue(srcRenderer, out var poc) && poc.IsValid) + { + retain.Add(srcRenderer, poc); + } + else + { + poc = new ProxyObjectController(srcRenderer); + retain.Add(srcRenderer, poc); + } + + poc.Pipeline = _active; + activeRenderers.Add((srcRenderer, poc.Renderer)); + + originalToProxyObject[srcRenderer.gameObject] = poc.Renderer.gameObject; + proxyToOriginalObject[poc.Renderer.gameObject] = srcRenderer.gameObject; + originalToProxyRenderer[srcRenderer] = poc.Renderer; + } + + _proxyControllers = retain; + + OriginalToProxyObject = originalToProxyObject.ToImmutable(); + ProxyToOriginalObject = proxyToOriginalObject.ToImmutable(); + OriginalToProxyRenderer = originalToProxyRenderer.ToImmutable(); + } + + private void CollectNodes() + { + var toRetain = new HashSet(); + + _active?.CollectNodes(toRetain); + _next?.CollectNodes(toRetain); + + _graph.Retain(toRetain); + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Rendering/ProxySession.cs.meta b/Editor/PreviewSystem/Rendering/ProxySession.cs.meta new file mode 100644 index 00000000..22d0f85c --- /dev/null +++ b/Editor/PreviewSystem/Rendering/ProxySession.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eaaf12270b2d4f9b9c374576380a808f +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/SequencePoint.cs b/Editor/PreviewSystem/SequencePoint.cs new file mode 100644 index 00000000..a25814fc --- /dev/null +++ b/Editor/PreviewSystem/SequencePoint.cs @@ -0,0 +1,23 @@ +namespace nadena.dev.ndmf.preview +{ + /// + /// Describes the time at which a particular mesh operation should be performed. Sequence points are created + /// relative to each other; unrelated sequence points cannot be used in the same PreviewSession. + /// + public sealed class SequencePoint + { + private static int _creationOrder = 0; + + public string DebugString { get; set; } + + public SequencePoint() + { + DebugString = "#" + (_creationOrder++); + } + + public override string ToString() + { + return "[SequencePoint " + DebugString + "]"; + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/SequencePoint.cs.meta b/Editor/PreviewSystem/SequencePoint.cs.meta new file mode 100644 index 00000000..8f7127f5 --- /dev/null +++ b/Editor/PreviewSystem/SequencePoint.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 58a1339b057142b4827c4c24a9735713 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/PreviewSystem/Sequencer.cs b/Editor/PreviewSystem/Sequencer.cs new file mode 100644 index 00000000..3da13801 --- /dev/null +++ b/Editor/PreviewSystem/Sequencer.cs @@ -0,0 +1,58 @@ +#region + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +#endregion + +namespace nadena.dev.ndmf.preview +{ + internal sealed class Sequencer + { + private readonly HashSet _discovered = new(); + private readonly List _discoveryOrder = new(); + private readonly Dictionary _resolvedOrder = new(); + + public IEnumerable Sequence => _resolvedOrder + .OrderBy(kvp => kvp.Value) + .Select(kvp => kvp.Key) + .ToImmutableList(); + + public Sequencer() + { + } + + public void SetSequence(IEnumerable points) + { + _resolvedOrder.Clear(); + + foreach (var point in points) + { + if (_discovered.Add(point)) + { + _discoveryOrder.Add(point); + } + + _resolvedOrder[point] = _resolvedOrder.Count; + } + + foreach (var point in _discoveryOrder) + { + if (!_resolvedOrder.ContainsKey(point)) + { + _resolvedOrder[point] = _resolvedOrder.Count; + } + } + } + + public void AddPoint(SequencePoint point) + { + if (_discovered.Add(point)) + { + _discoveryOrder.Add(point); + _resolvedOrder[point] = _resolvedOrder.Count; + } + } + } +} \ No newline at end of file diff --git a/Editor/PreviewSystem/Sequencer.cs.meta b/Editor/PreviewSystem/Sequencer.cs.meta new file mode 100644 index 00000000..d5e6ba41 --- /dev/null +++ b/Editor/PreviewSystem/Sequencer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a8baaacd875940c7a84517642cdbb342 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/RQ-Unity.meta b/Editor/RQ-Unity.meta new file mode 100644 index 00000000..ca32b978 --- /dev/null +++ b/Editor/RQ-Unity.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b2611461f0a3404db655377ab50d678c +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/RQ-Unity/CommonQueries.cs b/Editor/RQ-Unity/CommonQueries.cs new file mode 100644 index 00000000..9221025e --- /dev/null +++ b/Editor/RQ-Unity/CommonQueries.cs @@ -0,0 +1,77 @@ +#region + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + public static class CommonQueries + { + /// + /// Reactive value evaluating to a list of all root game objects in all loaded scenes. + /// + public static ReactiveValue> SceneRoots { get; } + = ReactiveValue>.Create("SceneRoots", + ctx => + { + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var roots = ObjectWatcher.Instance.MonitorSceneRoots(out var dispose, _ => invalidate(), + onInvalidate); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return Task.FromResult(roots); + }); + + private static Dictionary */> _builderCache = new(); + + private static ReactiveQuery> _componentsByType + = new("ComponentsByType", + async (ctx, type) => + { + var roots = await ctx.Observe(SceneRoots); + + IEnumerable components = + roots.SelectMany(root => ctx.GetComponentsInChildren(root, type, true)); + + return components.ToImmutableList(); + }); + + /// + /// Returns a reactive value that evaluates to a list of all components of the given type in the scene. + /// + /// The type to search for + /// + public static ReactiveValue> GetComponentsByType() where T : Component + { + if (!_builderCache.TryGetValue(typeof(T), out var builder)) + { + _builderCache[typeof(T)] = builder = ReactiveValue>.Create( + "ComponentsByType: " + typeof(T), + async ctx => + { + var roots = await ctx.Observe(SceneRoots); + + IEnumerable components = + roots.SelectMany(root => ctx.GetComponentsInChildren(root, true)); + + return components.ToImmutableList(); + }); + } + + return (ReactiveValue>)builder; + } + + public static ReactiveValue> GetComponentsByType(Type type) + { + return _componentsByType.Get(type); + } + } +} \ No newline at end of file diff --git a/Editor/RQ-Unity/CommonQueries.cs.meta b/Editor/RQ-Unity/CommonQueries.cs.meta new file mode 100644 index 00000000..b7b9c5a8 --- /dev/null +++ b/Editor/RQ-Unity/CommonQueries.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4ffdaef8424347af8ab191de633600c7 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/RQ-Unity/ReactiveQueryExt.cs b/Editor/RQ-Unity/ReactiveQueryExt.cs new file mode 100644 index 00000000..79876925 --- /dev/null +++ b/Editor/RQ-Unity/ReactiveQueryExt.cs @@ -0,0 +1,186 @@ +#region + +using System; +using System.Collections.Generic; +using UnityEngine; +using Object = UnityEngine.Object; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + public static class ReactiveQueryExt + { + /// + /// Monitors a given Unity object for changes, and recomputes when changes are detected. + /// + /// This will recompute when properties of the object change, when the object is destroyed, or (in the case of + /// a GameObject), when the children of the GameObject changed. + /// + /// + /// + /// + /// + public static T Observe(this ComputeContext ctx, T obj) where T : Object + { + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + ObjectWatcher.Instance.MonitorObjectProps(out var dispose, obj, a => a(), invalidate); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return obj; + } + + /// + /// Observes the full path from the scene root to the given transform. The calling computation will be + /// re-executed if any of the objects in this path are reparented. + /// + /// + /// + /// An enumerable of transforms in the path, starting from the leaf. + public static IEnumerable ObservePath(this ComputeContext ctx, Transform obj) + { + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + ObjectWatcher.Instance.MonitorObjectPath(out var dispose, obj, i => i(), invalidate); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return FollowPath(obj); + + IEnumerable FollowPath(Transform obj) + { + while (obj != null) + { + yield return obj; + obj = obj.parent; + } + } + } + + /// + /// Observes the world space position of a given transform. + /// + /// + /// + public static Transform ObserveTransformPosition(this ComputeContext ctx, Transform t) + { + foreach (var node in ctx.ObservePath(t)) + { + ctx.Observe(node); + } + + return t; + } + + /// + /// Observes whether a given game object and all its parents are active. + /// + /// + /// + /// + public static bool ActiveInHierarchy(this ComputeContext ctx, GameObject obj) + { + ObservePath(ctx, obj.transform); + return obj.activeInHierarchy; + } + + /// + /// Observes whether a component is enabled, and its heirarchy path is active. + /// + /// + /// + /// + public static bool ActiveAndEnabled(this ComputeContext ctx, Behaviour c) + { + return ActiveInHierarchy(ctx, c.gameObject) && ctx.Observe(c).enabled; + } + + public static C GetComponent(this ComputeContext ctx, GameObject obj) where C : Component + { + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponent(out var dispose, obj, a => a(), invalidate, + () => obj != null ? obj.GetComponent() : null); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + + public static Component GetComponent(this ComputeContext ctx, GameObject obj, Type type) + { + if (obj == null) return null; + + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponent(out var dispose, obj, a => a(), invalidate, + () => obj != null ? obj.GetComponent(type) : (Component)null); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + + public static C[] GetComponents(this ComputeContext ctx, GameObject obj) where C : Component + { + if (obj == null) return Array.Empty(); + + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponents(out var dispose, obj, a => a(), invalidate, + () => obj != null ? obj.GetComponents() : Array.Empty(), false); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + + public static Component[] GetComponents(this ComputeContext ctx, GameObject obj, Type type) + { + if (obj == null) return Array.Empty(); + + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponents(out var dispose, obj, a => a(), invalidate, + () => obj != null ? obj.GetComponents(type) : Array.Empty(), false); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + + public static C[] GetComponentsInChildren(this ComputeContext ctx, GameObject obj, bool includeInactive) + where C : Component + { + if (obj == null) return Array.Empty(); + + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponents(out var dispose, obj, a => a(), invalidate, + () => { return obj != null ? obj.GetComponentsInChildren(includeInactive) : Array.Empty(); }, + true); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + + public static Component[] GetComponentsInChildren(this ComputeContext ctx, GameObject obj, Type type, + bool includeInactive) + { + if (obj == null) return Array.Empty(); + + var invalidate = ctx.Invalidate; + var onInvalidate = ctx.OnInvalidate; + + var c = ObjectWatcher.Instance.MonitorGetComponents(out var dispose, obj, a => a(), invalidate, + () => obj != null ? obj.GetComponentsInChildren(type, includeInactive) : Array.Empty(), + true); + onInvalidate.ContinueWith(_ => dispose.Dispose()); + + return c; + } + } +} \ No newline at end of file diff --git a/Editor/RQ-Unity/ReactiveQueryExt.cs.meta b/Editor/RQ-Unity/ReactiveQueryExt.cs.meta new file mode 100644 index 00000000..76446718 --- /dev/null +++ b/Editor/RQ-Unity/ReactiveQueryExt.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bf5ebaec60e5428797358bd2228ed31b +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/RQ-Unity/ThrottledSynchronizationContext.cs b/Editor/RQ-Unity/ThrottledSynchronizationContext.cs new file mode 100644 index 00000000..f6cebc62 --- /dev/null +++ b/Editor/RQ-Unity/ThrottledSynchronizationContext.cs @@ -0,0 +1,208 @@ +#region + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using UnityEditor; +using UnityEngine.Profiling; +using Debug = UnityEngine.Debug; + +#endregion + +namespace nadena.dev.ndmf.rq.unity.editor +{ + internal sealed class ThrottledSynchronizationContext : SynchronizationContext + { + [InitializeOnLoadMethod] + static void Init() + { + ReactiveQueryScheduler.SynchronizationContextOverride.Value + = new ThrottledSynchronizationContext(Current); + } + + private static CustomSampler _tscontext = CustomSampler.Create("ThrottledSynchronizationContext"); + private static CustomSampler _executingTask = CustomSampler.Create("TaskRunning"); + private readonly object _lock = new object(); + private readonly SynchronizationContext _parent; + private Queue _pendingWork = new Queue(); + private int _owningThreadId; + + public int OwningThreadId => _owningThreadId; + + // locked: + private List _remoteWork = new List(); + private bool _isQueued = false; + + private bool IsRunning { get; set; } = false; + + public bool InContext => _owningThreadId == Thread.CurrentThread.ManagedThreadId && IsRunning; + + private bool IsQueued + { + get => _isQueued; + set + { + if (value == _isQueued) + { + return; + } + + _isQueued = value; + if (_isQueued) + { + _parent.Post(RunWithTimeLimit, this); + } + } + } + + public ThrottledSynchronizationContext(SynchronizationContext parent) + { + _parent = parent; + parent.Send(InitThreadId, this); + } + + private static void InitThreadId(object state) + { + var self = (ThrottledSynchronizationContext)state; + self._owningThreadId = Thread.CurrentThread.ManagedThreadId; + } + + private static void RunWithTimeLimit(object state) + { + var self = (ThrottledSynchronizationContext)state; + + lock (self._lock) + { + self.IsQueued = false; + } + + Stopwatch sw = new Stopwatch(); + sw.Start(); + self.RunUntil(() => sw.ElapsedMilliseconds >= 100); + } + + public void RunUntil(Func terminationCondition) + { + if (_owningThreadId != Thread.CurrentThread.ManagedThreadId) + { + throw new InvalidOperationException("Can only be called from the owning thread"); + } + + _tscontext.Begin(); + lock (_lock) + { + IsRunning = true; + _remoteWork.ForEach(_pendingWork.Enqueue); + _remoteWork.Clear(); + } + + using (TaskThrottle.WithThrottleCondition(terminationCondition)) + { + int n = 0; + do + { + _executingTask.Begin(); + _pendingWork.Dequeue().Run(); + _executingTask.End(); + n++; + } while (_pendingWork.Count > 0 && !terminationCondition()); + + /* + if (_pendingWork.Count > 0) + { + Debug.Log("Throttling SynchronizationContext: " + n + " tasks processed, " + _pendingWork.Count + + " remaining"); + } + */ + } + + lock (_lock) + { + IsRunning = false; + if (_pendingWork.Count > 0) + { + IsQueued = true; + } + } + + _tscontext.End(); + } + + public override void Post(SendOrPostCallback d, object state) + { + if (_owningThreadId == Thread.CurrentThread.ManagedThreadId && IsRunning) + { + _pendingWork.Enqueue(new PendingWork(d, state, null)); + } + else + { + lock (_lock) + { + CheckInvocation(); + _remoteWork.Add(new PendingWork(d, state, null)); + IsQueued = true; + } + } + } + + public override void Send(SendOrPostCallback d, object state) + { + if (_owningThreadId == Thread.CurrentThread.ManagedThreadId && IsRunning) + { + d(state); + } + else + { + CheckInvocation(); + var waitHandle = new ManualResetEvent(false); + lock (_lock) + { + _remoteWork.Add(new PendingWork(d, state, waitHandle)); + IsQueued = true; + } + + waitHandle.WaitOne(); + } + } + + private void CheckInvocation() + { + if (Thread.CurrentThread.ManagedThreadId != _owningThreadId) return; + if (Current == this) return; + + Debug.LogWarning( + "Work was enqueued into ThrottledSynchronizationContext from a foreign task. This can result in deadlocks!"); + } + + private class PendingWork + { + public SendOrPostCallback Callback; + public object State; + public ManualResetEvent WaitHandle; + + public PendingWork(SendOrPostCallback callback, object state, ManualResetEvent waitHandle) + { + Callback = callback; + State = state; + WaitHandle = waitHandle; + } + + public void Run() + { + try + { + Callback(State); + } + catch (Exception e) + { + Debug.LogException(e); + } + finally + { + WaitHandle?.Set(); + } + } + } + } +} \ No newline at end of file diff --git a/Editor/RQ-Unity/ThrottledSynchronizationContext.cs.meta b/Editor/RQ-Unity/ThrottledSynchronizationContext.cs.meta new file mode 100644 index 00000000..53195b41 --- /dev/null +++ b/Editor/RQ-Unity/ThrottledSynchronizationContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b9ecac1cad4742efb2ce25ec02b2cfb2 +timeCreated: 1717367851 \ No newline at end of file diff --git a/Editor/assembly-info.cs b/Editor/assembly-info.cs index 0143eac5..92ab177a 100644 --- a/Editor/assembly-info.cs +++ b/Editor/assembly-info.cs @@ -5,4 +5,5 @@ #endregion [assembly: InternalsVisibleTo("nadena.dev.ndmf.UnitTests")] +[assembly: InternalsVisibleTo("nadena.dev.ndmf.reactive-query.tests.editor")] [assembly: InternalsVisibleTo("nadena.dev.ndmf.vrchat")] \ No newline at end of file diff --git a/Editor/nadena.dev.ndmf.asmdef b/Editor/nadena.dev.ndmf.asmdef index d91b103f..bf93ca12 100644 --- a/Editor/nadena.dev.ndmf.asmdef +++ b/Editor/nadena.dev.ndmf.asmdef @@ -1,10 +1,12 @@ { "name": "nadena.dev.ndmf", + "rootNamespace": "", "references": [ "VRC.SDKBase", "VRC.SDK3A", "VRC.SDK3A.Editor", - "nadena.dev.ndmf.runtime" + "nadena.dev.ndmf.runtime", + "nadena.dev.ndmf.reactive-query.core" ], "includePlatforms": [ "Editor" diff --git a/RQ-Core.meta b/RQ-Core.meta new file mode 100644 index 00000000..0d6e5996 --- /dev/null +++ b/RQ-Core.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 179694d3a7fe47758ea3178da6fd91b8 +timeCreated: 1717367862 \ No newline at end of file diff --git a/RQ-Core/ComputeContext.cs b/RQ-Core/ComputeContext.cs new file mode 100644 index 00000000..29284ab2 --- /dev/null +++ b/RQ-Core/ComputeContext.cs @@ -0,0 +1,60 @@ +#region + +using System; +using System.Threading; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public sealed class BlockingNode + { + private Lazy _description; + private string Description => _description.Value; + + public BlockingNode(Lazy description) + { + _description = description; + } + + void SetBlockingOn(BlockingNode waitingOn, bool isWaiting = true) + { + // TODO + } + } + + public sealed class ComputeContext + { + public BlockingNode BlockingOn { get; } + public Action Invalidate { get; internal set; } = () => { }; + public Task OnInvalidate { get; internal set; } + public CancellationToken CancellationToken { get; internal set; } = CancellationToken.None; + + internal ComputeContext(Func description) + { + BlockingOn = new BlockingNode(new Lazy(description)); + } + + public async Task Observe(ReactiveValue q) + { + // capture the current invalidate function immediately, to avoid infinite invalidate loops + var invalidate = Invalidate; + var ct = CancellationToken; + // Propagate the invalidation to any listeners synchronously on Invalidate. + _ = q.Invalidated.ContinueWith( + _ => invalidate(), ct, + TaskContinuationOptions.ExecuteSynchronously, + TaskScheduler.Default + ); + + var compute = q.RequestCompute(); + + await TaskThrottle.MaybeThrottle(); + await Task.WhenAny(compute, q.Invalidated.ContinueWith(_ => Task.FromCanceled(ct))); + + ct.ThrowIfCancellationRequested(); + return await compute; + } + } +} \ No newline at end of file diff --git a/RQ-Core/ComputeContext.cs.meta b/RQ-Core/ComputeContext.cs.meta new file mode 100644 index 00000000..447b792d --- /dev/null +++ b/RQ-Core/ComputeContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3de420e34aa94664bf0502d6d5d12579 +timeCreated: 1714253620 \ No newline at end of file diff --git a/RQ-Core/IInvalidationObserver.cs b/RQ-Core/IInvalidationObserver.cs new file mode 100644 index 00000000..2098240b --- /dev/null +++ b/RQ-Core/IInvalidationObserver.cs @@ -0,0 +1,7 @@ +namespace nadena.dev.ndmf.rq +{ + internal interface IInvalidationObserver + { + public void OnInvalidate(); + } +} \ No newline at end of file diff --git a/RQ-Core/IInvalidationObserver.cs.meta b/RQ-Core/IInvalidationObserver.cs.meta new file mode 100644 index 00000000..499285f8 --- /dev/null +++ b/RQ-Core/IInvalidationObserver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 06ff8c32244242f38a22a1089e8ce031 +timeCreated: 1714445520 \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations.meta b/RQ-Core/JetBrainsAnnotations.meta new file mode 100644 index 00000000..0a8d6a53 --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00058e3d0400da44098ae16a010e5792 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs b/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs new file mode 100644 index 00000000..5b0640dc --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs @@ -0,0 +1,2189 @@ +/* MIT License + +Copyright (c) 2016 JetBrains http://www.jetbrains.com + +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. */ + +#nullable disable + +#region + +using System; +using System.Diagnostics; + +#endregion + +// ReSharper disable UnusedType.Global + +// conflict with UnityEngine.CoreModule annotations +#pragma warning disable 0436 +#pragma warning disable 1591 +// ReSharper disable UnusedMember.Global +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable IntroduceOptionalParameters.Global +// ReSharper disable MemberCanBeProtected.Global +// ReSharper disable InconsistentNaming + +namespace JetBrains.Annotations +{ + /// + /// Indicates that the value of the marked element could be null sometimes, + /// so checking for null is required before its usage. + /// + /// + /// [CanBeNull] object Test() => null; + /// + /// void UseTest() { + /// var p = Test(); + /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException' + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class CanBeNullAttribute : Attribute + { + } + + /// + /// Indicates that the value of the marked element can never be null. + /// + /// + /// [NotNull] object Foo() { + /// return null; // Warning: Possible 'null' assignment + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class NotNullAttribute : Attribute + { + } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can never be null. + /// + /// + /// public void Foo([ItemNotNull]List<string> books) + /// { + /// foreach (var book in books) { + /// if (book != null) // Warning: Expression is always true + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ItemNotNullAttribute : Attribute + { + } + + /// + /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task + /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property + /// or of the Lazy.Value property can be null. + /// + /// + /// public void Foo([ItemCanBeNull]List<string> books) + /// { + /// foreach (var book in books) + /// { + /// // Warning: Possible 'System.NullReferenceException' + /// Console.WriteLine(book.ToUpper()); + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ItemCanBeNullAttribute : Attribute + { + } + + /// + /// Indicates that the marked method builds a string by the format pattern and (optional) arguments. + /// The parameter, which contains the format string, should be given in the constructor. The format string + /// should be in -like form. + /// + /// + /// [StringFormatMethod("message")] + /// void ShowError(string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method | + AttributeTargets.Property | AttributeTargets.Delegate)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class StringFormatMethodAttribute : Attribute + { + /// + /// Specifies which parameter of an annotated method should be treated as the format string. + /// + public StringFormatMethodAttribute([NotNull] string formatParameterName) + { + FormatParameterName = formatParameterName; + } + + [NotNull] public string FormatParameterName { get; } + } + + /// + /// Indicates that the marked parameter is a message template where placeholders are to be replaced by the following arguments + /// in the order in which they appear. + /// + /// + /// void LogInfo([StructuredMessageTemplate]string message, params object[] args) { /* do something */ } + /// + /// void Foo() { + /// LogInfo("User created: {username}"); // Warning: Non-existing argument in format string + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class StructuredMessageTemplateAttribute : Attribute + { + } + + /// + /// Use this annotation to specify a type that contains static or const fields + /// with values for the annotated property/field/parameter. + /// The specified type will be used to improve completion suggestions. + /// + /// + /// namespace TestNamespace + /// { + /// public class Constants + /// { + /// public static int INT_CONST = 1; + /// public const string STRING_CONST = "1"; + /// } + /// + /// public class Class1 + /// { + /// [ValueProvider("TestNamespace.Constants")] public int myField; + /// public void Foo([ValueProvider("TestNamespace.Constants")] string str) { } + /// + /// public void Test() + /// { + /// Foo(/*try completion here*/);// + /// myField = /*try completion here*/ + /// } + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ValueProviderAttribute : Attribute + { + public ValueProviderAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + /// + /// Indicates that the integral value falls into the specified interval. + /// It's allowed to specify multiple non-intersecting intervals. + /// Values of interval boundaries are inclusive. + /// + /// + /// void Foo([ValueRange(0, 100)] int value) { + /// if (value == -1) { // Warning: Expression is always 'false' + /// ... + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | + AttributeTargets.Method | AttributeTargets.Delegate, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ValueRangeAttribute : Attribute + { + public object From { get; } + public object To { get; } + + public ValueRangeAttribute(long from, long to) + { + From = from; + To = to; + } + + public ValueRangeAttribute(ulong from, ulong to) + { + From = from; + To = to; + } + + public ValueRangeAttribute(long value) + { + From = To = value; + } + + public ValueRangeAttribute(ulong value) + { + From = To = value; + } + } + + /// + /// Indicates that the integral value never falls below zero. + /// + /// + /// void Foo([NonNegativeValue] int value) { + /// if (value == -1) { // Warning: Expression is always 'false' + /// ... + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | + AttributeTargets.Method | AttributeTargets.Delegate)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class NonNegativeValueAttribute : Attribute + { + } + + /// + /// Indicates that the function argument should be a string literal and match + /// one of the parameters of the caller function. This annotation is used for parameters + /// like 'string paramName' parameter of the constructor. + /// + /// + /// void Foo(string param) { + /// if (param == null) + /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class InvokerParameterNameAttribute : Attribute + { + } + + /// + /// Indicates that the method is contained in a type that implements + /// System.ComponentModel.INotifyPropertyChanged interface and this method + /// is used to notify that some property value changed. + /// + /// + /// The method should be non-static and conform to one of the supported signatures: + /// + /// NotifyChanged(string) + /// NotifyChanged(params string[]) + /// NotifyChanged{T}(Expression{Func{T}}) + /// NotifyChanged{T,U}(Expression{Func{T,U}}) + /// SetProperty{T}(ref T, T, string) + /// + /// + /// + /// public class Foo : INotifyPropertyChanged { + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// [NotifyPropertyChangedInvocator] + /// protected virtual void NotifyChanged(string propertyName) { ... } + /// + /// string _name; + /// + /// public string Name { + /// get { return _name; } + /// set { _name = value; NotifyChanged("LastName"); /* Warning */ } + /// } + /// } + /// + /// Examples of generated notifications: + /// + /// NotifyChanged("Property") + /// NotifyChanged(() => Property) + /// NotifyChanged((VM x) => x.Property) + /// SetProperty(ref myField, value, "Property") + /// + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class NotifyPropertyChangedInvocatorAttribute : Attribute + { + public NotifyPropertyChangedInvocatorAttribute() + { + } + + public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName) + { + ParameterName = parameterName; + } + + [CanBeNull] public string ParameterName { get; } + } + + /// + /// Describes dependence between method input and output. + /// + /// + ///

Function Definition Table syntax:

+ /// + /// FDT ::= FDTRow [;FDTRow]* + /// FDTRow ::= Input => Output | Output <= Input + /// Input ::= ParameterName: Value [, Input]* + /// Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value} + /// Value ::= true | false | null | notnull | canbenull + /// + /// If the method has a single input parameter, its name could be omitted.
+ /// Using halt (or void/nothing, which is the same) for the method output + /// means that the method doesn't return normally (throws or terminates the process).
+ /// Value canbenull is only applicable for output parameters.
+ /// You can use multiple [ContractAnnotation] for each FDT row, or use single attribute + /// with rows separated by the semicolon. There is no notion of order rows, all rows are checked + /// for applicability and applied per each program state tracked by the analysis engine.
+ ///
+ /// + /// + /// [ContractAnnotation("=> halt")] + /// public void TerminationMethod() + /// + /// + /// [ContractAnnotation("null <= param:null")] // reverse condition syntax + /// public string GetName(string surname) + /// + /// + /// [ContractAnnotation("s:null => true")] + /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty() + /// + /// + /// // A method that returns null if the parameter is null, + /// // and not null if the parameter is not null + /// [ContractAnnotation("null => null; notnull => notnull")] + /// public object Transform(object data) + /// + /// + /// [ContractAnnotation("=> true, result: notnull; => false, result: null")] + /// public bool TryParse(string s, out Person result) + /// + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ContractAnnotationAttribute : Attribute + { + public ContractAnnotationAttribute([NotNull] string contract) + : this(contract, false) + { + } + + public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) + { + Contract = contract; + ForceFullStates = forceFullStates; + } + + [NotNull] public string Contract { get; } + + public bool ForceFullStates { get; } + } + + /// + /// Indicates whether the marked element should be localized. + /// + /// + /// [LocalizationRequiredAttribute(true)] + /// class Foo { + /// string str = "my string"; // Warning: Localizable string + /// } + /// + [AttributeUsage(AttributeTargets.All)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class LocalizationRequiredAttribute : Attribute + { + public LocalizationRequiredAttribute() : this(true) + { + } + + public LocalizationRequiredAttribute(bool required) + { + Required = required; + } + + public bool Required { get; } + } + + /// + /// Indicates that the value of the marked type (or its derivatives) + /// cannot be compared using '==' or '!=' operators and Equals() + /// should be used instead. However, using '==' or '!=' for comparison + /// with null is always permitted. + /// + /// + /// [CannotApplyEqualityOperator] + /// class NoEquality { } + /// + /// class UsesNoEquality { + /// void Test() { + /// var ca1 = new NoEquality(); + /// var ca2 = new NoEquality(); + /// if (ca1 != null) { // OK + /// bool condition = ca1 == ca2; // Warning + /// } + /// } + /// } + /// + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class CannotApplyEqualityOperatorAttribute : Attribute + { + } + + /// + /// When applied to a target attribute, specifies a requirement for any type marked + /// with the target attribute to implement or inherit the specific type or types. + /// + /// + /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement + /// class ComponentAttribute : Attribute { } + /// + /// [Component] // ComponentAttribute requires implementing IComponent interface + /// class MyComponent : IComponent { } + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [BaseTypeRequired(typeof(Attribute))] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class BaseTypeRequiredAttribute : Attribute + { + public BaseTypeRequiredAttribute([NotNull] Type baseType) + { + BaseType = baseType; + } + + [NotNull] public Type BaseType { get; } + } + + /// + /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), + /// so this symbol will be ignored by usage-checking inspections.
+ /// You can use and + /// to configure how this attribute is applied. + ///
+ /// + /// [UsedImplicitly] + /// public class TypeConverter {} + /// + /// public class SummaryData + /// { + /// [UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature)] + /// public SummaryData() {} + /// } + /// + /// [UsedImplicitly(ImplicitUseTargetFlags.WithInheritors | ImplicitUseTargetFlags.Default)] + /// public interface IService {} + /// + [AttributeUsage(AttributeTargets.All)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class UsedImplicitlyAttribute : Attribute + { + public UsedImplicitlyAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + public ImplicitUseKindFlags UseKindFlags { get; } + + public ImplicitUseTargetFlags TargetFlags { get; } + } + + /// + /// Can be applied to attributes, type parameters, and parameters of a type assignable from . + /// When applied to an attribute, the decorated attribute behaves the same as . + /// When applied to a type parameter or to a parameter of type , + /// indicates that the corresponding type is used implicitly. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter | AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class MeansImplicitUseAttribute : Attribute + { + public MeansImplicitUseAttribute() + : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) + : this(useKindFlags, ImplicitUseTargetFlags.Default) + { + } + + public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) + : this(ImplicitUseKindFlags.Default, targetFlags) + { + } + + public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) + { + UseKindFlags = useKindFlags; + TargetFlags = targetFlags; + } + + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; } + + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; } + } + + /// + /// Specifies the details of an implicitly used symbol when it is marked + /// with or . + /// + [Flags] + internal enum ImplicitUseKindFlags + { + Default = Access | Assign | InstantiatedWithFixedConstructorSignature, + + /// Only entity marked with attribute considered used. + Access = 1, + + /// Indicates implicit assignment to a member. + Assign = 2, + + /// + /// Indicates implicit instantiation of a type with fixed constructor signature. + /// That means any unused constructor parameters won't be reported as such. + /// + InstantiatedWithFixedConstructorSignature = 4, + + /// Indicates implicit instantiation of a type. + InstantiatedNoFixedConstructorSignature = 8, + } + + /// + /// Specifies what is considered to be used implicitly when marked + /// with or . + /// + [Flags] + internal enum ImplicitUseTargetFlags + { + Default = Itself, + Itself = 1, + + /// Members of the type marked with the attribute are considered used. + Members = 2, + + /// Inherited entities are considered used. + WithInheritors = 4, + + /// Entity marked with the attribute and all its members considered used. + WithMembers = Itself | Members + } + + /// + /// This attribute is intended to mark publicly available APIs, + /// which should not be removed and so is treated as used. + /// + [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] + [AttributeUsage(AttributeTargets.All, Inherited = false)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class PublicAPIAttribute : Attribute + { + public PublicAPIAttribute() + { + } + + public PublicAPIAttribute([NotNull] string comment) + { + Comment = comment; + } + + [CanBeNull] public string Comment { get; } + } + + /// + /// Tells the code analysis engine if the parameter is completely handled when the invoked method is on stack. + /// If the parameter is a delegate, indicates that the delegate can only be invoked during method execution + /// (the delegate can be invoked zero or multiple times, but not stored to some field and invoked later, + /// when the containing method is no longer on the execution stack). + /// If the parameter is an enumerable, indicates that it is enumerated while the method is executed. + /// If is true, the attribute will only take effect if the method invocation is located under the 'await' expression. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class InstantHandleAttribute : Attribute + { + /// + /// Require the method invocation to be used under the 'await' expression for this attribute to take effect on the code analysis engine. + /// Can be used for delegate/enumerable parameters of 'async' methods. + /// + public bool RequireAwait { get; set; } + } + + /// + /// Indicates that a method does not make any observable state changes. + /// The same as System.Diagnostics.Contracts.PureAttribute. + /// + /// + /// [Pure] int Multiply(int x, int y) => x * y; + /// + /// void M() { + /// Multiply(123, 42); // Warning: Return value of pure method is not used + /// } + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class PureAttribute : Attribute + { + } + + /// + /// Indicates that the return value of the method invocation must be used. + /// + /// + /// Methods decorated with this attribute (in contrast to pure methods) might change state, + /// but make no sense without using their return value.
+ /// Similarly to , this attribute + /// will help to detect usages of the method when the return value is not used. + /// Optionally, you can specify a message to use when showing warnings, e.g. + /// [MustUseReturnValue("Use the return value to...")]. + ///
+ [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class MustUseReturnValueAttribute : Attribute + { + public MustUseReturnValueAttribute() + { + } + + public MustUseReturnValueAttribute([NotNull] string justification) + { + Justification = justification; + } + + [CanBeNull] public string Justification { get; } + } + + /// + /// Indicates that the resource disposal must be handled by the use site, + /// meaning that the resource ownership is transferred to the callee. + /// This annotation can be used to annotate disposable types or their constructors individually to enable + /// the resource disposal IDE code analysis in every context where the new instance of this type is created. + /// Factory methods and 'out' parameters can also be annotated to indicate that the return value of disposable type + /// needs handling. + /// + /// + /// Annotation of input parameters with this attribute is meaningless.
+ /// Constructors inherit this attribute from their type, if it is annotated, + /// but not from the base constructors they delegate to (if any).
+ /// Resource disposal is expected to be expressed via either using (resource) statement, + /// using var declaration, explicit 'Dispose' method call, or an argument passing + /// to a parameter with the attribute applied. + ///
+ [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class MustDisposeResourceAttribute : Attribute + { + public MustDisposeResourceAttribute() + { + Value = true; + } + + public MustDisposeResourceAttribute(bool value) + { + Value = value; + } + + /// + /// When set to false, disposing of the resource is not obligatory. + /// The main use-case for explicit [MustDisposeResource(false)] annotation is to loosen inherited annotation. + /// + public bool Value { get; } + } + + /// + /// Indicates that method or class instance acquires resource ownership and will dispose it after use. + /// + /// + /// Annotation of 'out' parameter with this attribute is meaningless.
+ /// When a instance method is annotated with this attribute, + /// it means that it is handling the resource disposal of the corresponding resource instance.
+ /// When a field or a property is annotated with this attribute, it means that this type owns the resource + /// and will handle the resource disposal properly (e.g. in own IDisposable implementation). + ///
+ [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class HandlesResourceDisposalAttribute : Attribute + { + } + + /// + /// This annotation allows to enforce allocation-less usage patterns of delegates for performance-critical APIs. + /// When this annotation is applied to the parameter of delegate type, the IDE checks the input argument of this parameter: + /// * When a lambda expression or anonymous method is passed as an argument, the IDE verifies that the passed closure + /// has no captures of the containing local variables and the compiler is able to cache the delegate instance + /// to avoid heap allocations. Otherwise a warning is produced. + /// * The IDE warns when the method name or local function name is passed as an argument as this always results + /// in heap allocation of the delegate instance. + /// + /// + /// In C# 9.0+ code, the IDE will also suggest to annotate the anonymous function with the 'static' modifier + /// to make use of the similar analysis provided by the language/compiler. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RequireStaticDelegateAttribute : Attribute + { + public bool IsError { get; set; } + } + + /// + /// Indicates the type member or parameter of some type that should be used instead of all other ways + /// to get the value of that type. This annotation is useful when you have some "context" value evaluated + /// and stored somewhere, meaning that all other ways to get this value must be consolidated with the existing one. + /// + /// + /// class Foo { + /// [ProvidesContext] IBarService _barService = ...; + /// + /// void ProcessNode(INode node) { + /// DoSomething(node, node.GetGlobalServices().Bar); + /// // ^ Warning: use value of '_barService' field + /// } + /// } + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | + AttributeTargets.GenericParameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class ProvidesContextAttribute : Attribute + { + } + + /// + /// Indicates that a parameter is a path to a file or a folder within a web project. + /// Path can be relative or absolute, starting from web root (~). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class PathReferenceAttribute : Attribute + { + public PathReferenceAttribute() + { + } + + public PathReferenceAttribute([NotNull, PathReference] string basePath) + { + BasePath = basePath; + } + + [CanBeNull] public string BasePath { get; } + } + + /// + /// An extension method marked with this attribute is processed by code completion + /// as a 'Source Template'. When the extension method is completed over some expression, its source code + /// is automatically expanded like a template at the call site. + /// + /// + /// Template method bodies can contain valid source code and/or special comments starting with '$'. + /// Text inside these comments is added as source code when the template is applied. Template parameters + /// can be used either as additional method parameters or as identifiers wrapped in two '$' signs. + /// Use the attribute to specify macros for parameters. + /// The expression to be used in the expansion can be adjusted by the parameter. + /// + /// + /// In this example, the 'forEach' method is a source template available over all values + /// of enumerable types, producing ordinary C# 'foreach' statement and placing the caret inside the block: + /// + /// [SourceTemplate] + /// public static void forEach<T>(this IEnumerable<T> xs) { + /// foreach (var x in xs) { + /// //$ $END$ + /// } + /// } + /// + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class SourceTemplateAttribute : Attribute + { + /// + /// Allows specifying which expression to capture for template execution if more than one present on the expansion. + /// If not specified, is assumed. + /// + public SourceTemplateTargetExpression Target { get; set; } + } + + /// + /// Provides a value for the to define how to capture + /// the expression at the point of expansion + /// + internal enum SourceTemplateTargetExpression + { + /// Selects inner expression + /// value > 42.{caret} captures 42 + /// _args = args.{caret} captures args + Inner = 0, + + /// Selects outer expression + /// value > 42.{caret} captures value > 42 + /// _args = args.{caret} captures whole assignment + Outer = 1 + } + + /// + /// Allows specifying a macro for a parameter of a source template. + /// + /// + /// You can apply the attribute on the whole method or on any of its additional parameters. The macro expression + /// is defined in the property. When applied on a method, the target + /// template parameter is defined in the property. To apply the macro silently + /// for the parameter, set the property value to -1. + /// + /// + /// Applying the attribute on a source template method: + /// + /// [SourceTemplate, Macro(Target = "item", Expression = "suggestVariableName()")] + /// public static void forEach<T>(this IEnumerable<T> collection) { + /// foreach (var item in collection) { + /// //$ $END$ + /// } + /// } + /// + /// Applying the attribute on a template method parameter: + /// + /// [SourceTemplate] + /// public static void something(this Entity x, [Macro(Expression = "guid()", Editable = -1)] string newguid) { + /// /*$ var $x$Id = "$newguid$" + x.ToString(); + /// x.DoSomething($x$Id); */ + /// } + /// + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class MacroAttribute : Attribute + { + /// + /// Allows specifying a macro that will be executed for a source template + /// parameter when the template is expanded. + /// + [CanBeNull] + public string Expression { get; set; } + + /// + /// Allows specifying which occurrence of the target parameter becomes editable when the template is deployed. + /// + /// + /// If the target parameter is used several times in the template, only one occurrence becomes editable; + /// other occurrences are changed synchronously. To specify the zero-based index of the editable occurrence, + /// use values >= 0. To make the parameter non-editable when the template is expanded, use -1. + /// + public int Editable { get; set; } + + /// + /// Identifies the target parameter of a source template if the + /// is applied on a template method. + /// + [CanBeNull] + public string Target { get; set; } + } + + /// + /// Indicates how a method, constructor invocation, or property access + /// over a collection type affects the contents of the collection. + /// When applied to a return value of a method, indicates if the returned collection + /// is created exclusively for the caller (CollectionAccessType.UpdatedContent) or + /// can be read/updated from outside (CollectionAccessType.Read | CollectionAccessType.UpdatedContent) + /// Use to specify the access type. + /// + /// + /// Using this attribute only makes sense if all collection methods are marked with this attribute. + /// + /// + /// public class MyStringCollection : List<string> + /// { + /// [CollectionAccess(CollectionAccessType.Read)] + /// public string GetFirstString() + /// { + /// return this.ElementAt(0); + /// } + /// } + /// class Test + /// { + /// public void Foo() + /// { + /// // Warning: Contents of the collection is never updated + /// var col = new MyStringCollection(); + /// string x = col.GetFirstString(); + /// } + /// } + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | + AttributeTargets.ReturnValue)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class CollectionAccessAttribute : Attribute + { + public CollectionAccessAttribute(CollectionAccessType collectionAccessType) + { + CollectionAccessType = collectionAccessType; + } + + public CollectionAccessType CollectionAccessType { get; } + } + + /// + /// Provides a value for the to define + /// how the collection method invocation affects the contents of the collection. + /// + [Flags] + internal enum CollectionAccessType + { + /// Method does not use or modify content of the collection. + None = 0, + + /// Method only reads content of the collection but does not modify it. + Read = 1, + + /// Method can change content of the collection but does not add new elements. + ModifyExistingContent = 2, + + /// Method can add new elements to the collection. + UpdatedContent = ModifyExistingContent | 4 + } + + /// + /// Indicates that the marked method is an assertion method, i.e. it halts the control flow if + /// one of the conditions is satisfied. To set the condition, mark one of the parameters with + /// attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AssertionMethodAttribute : Attribute + { + } + + /// + /// Indicates the condition parameter of the assertion method. The method itself should be + /// marked by the attribute. The mandatory argument of + /// the attribute is the assertion type. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AssertionConditionAttribute : Attribute + { + public AssertionConditionAttribute(AssertionConditionType conditionType) + { + ConditionType = conditionType; + } + + public AssertionConditionType ConditionType { get; } + } + + /// + /// Specifies the assertion type. If the assertion method argument satisfies the condition, + /// then the execution continues. Otherwise, execution is assumed to be halted. + /// + internal enum AssertionConditionType + { + /// Marked parameter should be evaluated to true. + IS_TRUE = 0, + + /// Marked parameter should be evaluated to false. + IS_FALSE = 1, + + /// Marked parameter should be evaluated to null value. + IS_NULL = 2, + + /// Marked parameter should be evaluated to not null value. + IS_NOT_NULL = 3, + } + + /// + /// Indicates that the marked method unconditionally terminates control flow execution. + /// For example, it could unconditionally throw an exception. + /// + [Obsolete("Use [ContractAnnotation('=> halt')] instead")] + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class TerminatesProgramAttribute : Attribute + { + } + + /// + /// Indicates that the method is a pure LINQ method, with postponed enumeration (like Enumerable.Select, + /// .Where). This annotation allows inference of [InstantHandle] annotation for parameters + /// of delegate type by analyzing LINQ method chains. + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class LinqTunnelAttribute : Attribute + { + } + + /// + /// Indicates that IEnumerable passed as a parameter is not enumerated. + /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection. + /// + /// + /// static void ThrowIfNull<T>([NoEnumeration] T v, string n) where T : class + /// { + /// // custom check for null but no enumeration + /// } + /// + /// void Foo(IEnumerable<string> values) + /// { + /// ThrowIfNull(values, nameof(values)); + /// var x = values.ToList(); // No warnings about multiple enumeration + /// } + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class NoEnumerationAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter, field, or property is a regular expression pattern. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RegexPatternAttribute : Attribute + { + } + + /// + /// Language of injected code fragment inside marked by the string literal. + /// + internal enum InjectedLanguage + { + CSS = 0, + HTML = 1, + JAVASCRIPT = 2, + JSON = 3, + XML = 4 + } + + /// + /// Indicates that the marked parameter, field, or property is accepting a string literal + /// containing code fragments in a specified language. + /// + /// + /// void Foo([LanguageInjection(InjectedLanguage.CSS, Prefix = "body{", Suffix = "}")] string cssProps) + /// { + /// // cssProps should only contains a list of CSS properties + /// } + /// + /// + /// void Bar([LanguageInjection("json")] string json) + /// { + /// } + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class LanguageInjectionAttribute : Attribute + { + public LanguageInjectionAttribute(InjectedLanguage injectedLanguage) + { + InjectedLanguage = injectedLanguage; + } + + public LanguageInjectionAttribute([NotNull] string injectedLanguage) + { + InjectedLanguageName = injectedLanguage; + } + + /// Specifies a language of the injected code fragment. + public InjectedLanguage InjectedLanguage { get; } + + /// Specifies a language name of the injected code fragment. + [CanBeNull] + public string InjectedLanguageName { get; } + + /// Specifies a string that "precedes" the injected string literal. + [CanBeNull] + public string Prefix { get; set; } + + /// Specifies a string that "follows" the injected string literal. + [CanBeNull] + public string Suffix { get; set; } + } + + /// + /// Prevents the Member Reordering feature from tossing members of the marked class. + /// + /// + /// The attribute must be mentioned in your member reordering patterns. + /// + [AttributeUsage( + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class NoReorderAttribute : Attribute + { + } + + /// + /// + /// Defines the code search template using the Structural Search and Replace syntax. + /// It allows you to find and, if necessary, replace blocks of code that match a specific pattern. + /// Search and replace patterns consist of a textual part and placeholders. + /// Textural part must contain only identifiers allowed in the target language and will be matched exactly (white spaces, tabulation characters, and line breaks are ignored). + /// Placeholders allow matching variable parts of the target code blocks. + /// A placeholder has the following format: $placeholder_name$- where placeholder_name is an arbitrary identifier. + /// + /// + /// Available placeholders: + /// + /// $this$ - expression of containing type + /// $thisType$ - containing type + /// $member$ - current member placeholder + /// $qualifier$ - this placeholder is available in the replace pattern and can be used to insert a qualifier expression matched by the $member$ placeholder. + /// (Note that if $qualifier$ placeholder is used, then $member$ placeholder will match only qualified references) + /// $expression$ - expression of any type + /// $identifier$ - identifier placeholder + /// $args$ - any number of arguments + /// $arg$ - single argument + /// $arg1$ ... $arg10$ - single argument + /// $stmts$ - any number of statements + /// $stmt$ - single statement + /// $stmt1$ ... $stmt10$ - single statement + /// $name{Expression, 'Namespace.FooType'}$ - expression with 'Namespace.FooType' type + /// $expression{'Namespace.FooType'}$ - expression with 'Namespace.FooType' type + /// $name{Type, 'Namespace.FooType'}$ - 'Namespace.FooType' type + /// $type{'Namespace.FooType'}$ - 'Namespace.FooType' type + /// $statement{1,2}$ - 1 or 2 statements + /// + /// + /// + /// Note that you can also define your own placeholders of the supported types and specify arguments for each placeholder type. + /// This can be done using the following format: $name{type, arguments}$. Where 'name' - is the name of your placeholder, + /// 'type' - is the type of your placeholder (one of the following: Expression, Type, Identifier, Statement, Argument, Member), + /// 'arguments' - arguments list for your placeholder. Each placeholder type supports its own arguments, check examples below for more details. + /// The placeholder type may be omitted and determined from the placeholder name, if the name has one of the following prefixes: + /// + /// expr, expression - expression placeholder, e.g. $exprPlaceholder{}$, $expressionFoo{}$ + /// arg, argument - argument placeholder, e.g. $argPlaceholder{}$, $argumentFoo{}$ + /// ident, identifier - identifier placeholder, e.g. $identPlaceholder{}$, $identifierFoo{}$ + /// stmt, statement - statement placeholder, e.g. $stmtPlaceholder{}$, $statementFoo{}$ + /// type - type placeholder, e.g. $typePlaceholder{}$, $typeFoo{}$ + /// member - member placeholder, e.g. $memberPlaceholder{}$, $memberFoo{}$ + /// + /// + /// + /// Expression placeholder arguments: + /// + /// expressionType - string value in single quotes, specifies full type name to match (empty string by default) + /// exactType - boolean value, specifies if expression should have exact type match (false by default) + /// + /// Examples: + /// + /// $myExpr{Expression, 'Namespace.FooType', true}$ - defines expression placeholder, matching expressions of the 'Namespace.FooType' type with exact matching. + /// $myExpr{Expression, 'Namespace.FooType'}$ - defines expression placeholder, matching expressions of the 'Namespace.FooType' type or expressions which can be implicitly converted to 'Namespace.FooType'. + /// $myExpr{Expression}$ - defines expression placeholder, matching expressions of any type. + /// $exprFoo{'Namespace.FooType', true}$ - defines expression placeholder, matching expressions of the 'Namespace.FooType' type with exact matching. + /// + /// + /// + /// Type placeholder arguments: + /// + /// type - string value in single quotes, specifies full type name to match (empty string by default) + /// exactType - boolean value, specifies if expression should have exact type match (false by default) + /// + /// Examples: + /// + /// $myType{Type, 'Namespace.FooType', true}$ - defines type placeholder, matching 'Namespace.FooType' types with exact matching. + /// $myType{Type, 'Namespace.FooType'}$ - defines type placeholder, matching 'Namespace.FooType' types or types, which can be implicitly converted to 'Namespace.FooType'. + /// $myType{Type}$ - defines type placeholder, matching any type. + /// $typeFoo{'Namespace.FooType', true}$ - defines types placeholder, matching 'Namespace.FooType' types with exact matching. + /// + /// + /// + /// Identifier placeholder arguments: + /// + /// nameRegex - string value in single quotes, specifies regex to use for matching (empty string by default) + /// nameRegexCaseSensitive - boolean value, specifies if name regex is case sensitive (true by default) + /// type - string value in single quotes, specifies full type name to match (empty string by default) + /// exactType - boolean value, specifies if expression should have exact type match (false by default) + /// + /// Examples: + /// + /// $myIdentifier{Identifier, 'my.*', false, 'Namespace.FooType', true}$ - defines identifier placeholder, matching identifiers (ignoring case) starting with 'my' prefix with 'Namespace.FooType' type. + /// $myIdentifier{Identifier, 'my.*', true, 'Namespace.FooType', true}$ - defines identifier placeholder, matching identifiers (case sensitively) starting with 'my' prefix with 'Namespace.FooType' type. + /// $identFoo{'my.*'}$ - defines identifier placeholder, matching identifiers (case sensitively) starting with 'my' prefix. + /// + /// + /// + /// Statement placeholder arguments: + /// + /// minimalOccurrences - minimal number of statements to match (-1 by default) + /// maximalOccurrences - maximal number of statements to match (-1 by default) + /// + /// Examples: + /// + /// $myStmt{Statement, 1, 2}$ - defines statement placeholder, matching 1 or 2 statements. + /// $myStmt{Statement}$ - defines statement placeholder, matching any number of statements. + /// $stmtFoo{1, 2}$ - defines statement placeholder, matching 1 or 2 statements. + /// + /// + /// + /// Argument placeholder arguments: + /// + /// minimalOccurrences - minimal number of arguments to match (-1 by default) + /// maximalOccurrences - maximal number of arguments to match (-1 by default) + /// + /// Examples: + /// + /// $myArg{Argument, 1, 2}$ - defines argument placeholder, matching 1 or 2 arguments. + /// $myArg{Argument}$ - defines argument placeholder, matching any number of arguments. + /// $argFoo{1, 2}$ - defines argument placeholder, matching 1 or 2 arguments. + /// + /// + /// + /// Member placeholder arguments: + /// + /// docId - string value in single quotes, specifies XML documentation id of the member to match (empty by default) + /// + /// Examples: + /// + /// $myMember{Member, 'M:System.String.IsNullOrEmpty(System.String)'}$ - defines member placeholder, matching 'IsNullOrEmpty' member of the 'System.String' type. + /// $memberFoo{'M:System.String.IsNullOrEmpty(System.String)'}$ - defines member placeholder, matching 'IsNullOrEmpty' member of the 'System.String' type. + /// + /// + /// + /// For more information please refer to the Structural Search and Replace article. + /// + /// + [AttributeUsage( + AttributeTargets.Method + | AttributeTargets.Constructor + | AttributeTargets.Property + | AttributeTargets.Field + | AttributeTargets.Event + | AttributeTargets.Interface + | AttributeTargets.Class + | AttributeTargets.Struct + | AttributeTargets.Enum, + AllowMultiple = true, + Inherited = false)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class CodeTemplateAttribute : Attribute + { + public CodeTemplateAttribute(string searchTemplate) + { + SearchTemplate = searchTemplate; + } + + /// + /// Structural search pattern to use in the code template. + /// The pattern includes a textual part, which must contain only identifiers allowed in the target language, + /// and placeholders, which allow matching variable parts of the target code blocks. + /// + public string SearchTemplate { get; } + + /// + /// Message to show when the search pattern was found. + /// You can also prepend the message text with "Error:", "Warning:", "Suggestion:" or "Hint:" prefix to specify the pattern severity. + /// Code patterns with replace templates produce suggestions by default. + /// However, if a replace template is not provided, then warning severity will be used. + /// + public string Message { get; set; } + + /// + /// Structural search replace pattern to use in code template replacement. + /// + public string ReplaceTemplate { get; set; } + + /// + /// The replace message to show in the light bulb. + /// + public string ReplaceMessage { get; set; } + + /// + /// Apply code formatting after code replacement. + /// + public bool FormatAfterReplace { get; set; } = true; + + /// + /// Whether similar code blocks should be matched. + /// + public bool MatchSimilarConstructs { get; set; } + + /// + /// Automatically insert namespace import directives or remove qualifiers that become redundant after the template is applied. + /// + public bool ShortenReferences { get; set; } + + /// + /// The string to use as a suppression key. + /// By default the following suppression key is used 'CodeTemplate_SomeType_SomeMember', + /// where 'SomeType' and 'SomeMember' are names of the associated containing type and member to which this attribute is applied. + /// + public string SuppressionKey { get; set; } + } + + /// + /// Indicates that the string literal, passed as an argument matching this parameter, + /// should not be checked on spelling or grammar errors. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class IgnoreSpellingAndGrammarErrorsAttribute : Attribute + { + } + + #region ASP.NET + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspChildControlTypeAttribute : Attribute + { + public AspChildControlTypeAttribute([NotNull] string tagName, [NotNull] Type controlType) + { + TagName = tagName; + ControlType = controlType; + } + + [NotNull] public string TagName { get; } + + [NotNull] public Type ControlType { get; } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspDataFieldAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspDataFieldsAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMethodPropertyAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspRequiredAttributeAttribute : Attribute + { + public AspRequiredAttributeAttribute([NotNull] string attribute) + { + Attribute = attribute; + } + + [NotNull] public string Attribute { get; } + } + + [AttributeUsage(AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspTypePropertyAttribute : Attribute + { + public bool CreateConstructorReferences { get; } + + public AspTypePropertyAttribute(bool createConstructorReferences) + { + CreateConstructorReferences = createConstructorReferences; + } + } + + #endregion + + #region ASP.NET MVC + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute + { + public AspMvcAreaMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute + { + public AspMvcAreaPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcAreaViewComponentViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewComponentViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcAreaViewLocationFormatAttribute : Attribute + { + public AspMvcAreaViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcMasterLocationFormatAttribute : Attribute + { + public AspMvcMasterLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcPartialViewLocationFormatAttribute : Attribute + { + public AspMvcPartialViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcViewComponentViewLocationFormatAttribute : Attribute + { + public AspMvcViewComponentViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcViewLocationFormatAttribute : Attribute + { + public AspMvcViewLocationFormatAttribute([NotNull] string format) + { + Format = format; + } + + [NotNull] public string Format { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | + AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcActionAttribute : Attribute + { + public AspMvcActionAttribute() + { + } + + public AspMvcActionAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC area. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcAreaAttribute : Attribute + { + public AspMvcAreaAttribute() + { + } + + public AspMvcAreaAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is + /// an MVC controller. If applied to a method, the MVC controller name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | + AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcControllerAttribute : Attribute + { + public AspMvcControllerAttribute() + { + } + + public AspMvcControllerAttribute([NotNull] string anonymousProperty) + { + AnonymousProperty = anonymousProperty; + } + + [CanBeNull] public string AnonymousProperty { get; } + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC Master. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcMasterAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC model type. Use this attribute + /// for custom wrappers similar to System.Web.Mvc.Controller.View(String, Object). + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcModelTypeAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter is an MVC + /// partial view. If applied to a method, the MVC partial view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | + AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcPartialViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Allows disabling inspections for MVC views within a class or a method. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcSuppressViewErrorAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcDisplayTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC editor template. + /// Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcEditorTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. Indicates that the marked parameter is an MVC template. + /// Use this attribute for custom wrappers similar to + /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcTemplateAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component. If applied to a method, the MVC view name is calculated implicitly + /// from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Controller.View(Object). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | + AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component name. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcViewComponentAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC view component view. If applied to a method, the MVC view component view name is default. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Field | + AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcViewComponentViewAttribute : Attribute + { + } + + /// + /// ASP.NET MVC attribute. When applied to a parameter of an attribute, + /// indicates that this parameter is an MVC action name. + /// + /// + /// [ActionName("Foo")] + /// public ActionResult Login(string returnUrl) { + /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK + /// return RedirectToAction("Bar"); // Error: Cannot resolve action + /// } + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMvcActionSelectorAttribute : Attribute + { + } + + #endregion + + #region ASP.NET Routing + + /// + /// Indicates that the marked parameter, field, or property is a route template. + /// + /// + /// This attribute allows IDE to recognize the use of web frameworks' route templates + /// to enable syntax highlighting, code completion, navigation, rename and other features in string literals. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RouteTemplateAttribute : Attribute + { + } + + /// + /// Indicates that the marked type is custom route parameter constraint, + /// which is registered in the application's Startup with the name ConstraintName. + /// + /// + /// You can specify ProposedType if target constraint matches only route parameters of specific type, + /// it will allow IDE to create method's parameter from usage in route template + /// with specified type instead of default System.String + /// and check if constraint's proposed type conflicts with matched parameter's type. + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RouteParameterConstraintAttribute : Attribute + { + [NotNull] public string ConstraintName { get; } + [CanBeNull] public Type ProposedType { get; set; } + + public RouteParameterConstraintAttribute([NotNull] string constraintName) + { + ConstraintName = constraintName; + } + } + + /// + /// Indicates that the marked parameter, field, or property is an URI string. + /// + /// + /// This attribute enables code completion, navigation, renaming and other features + /// in URI string literals assigned to annotated parameters, fields, or properties. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class UriStringAttribute : Attribute + { + public UriStringAttribute() + { + } + + public UriStringAttribute(string httpVerb) + { + HttpVerb = httpVerb; + } + + [CanBeNull] public string HttpVerb { get; } + } + + /// + /// Indicates that the marked method declares routing convention for ASP.NET. + /// + /// + /// The IDE will analyze all usages of methods marked with this attribute, + /// and will add all routes to completion, navigation, and other features over URI strings. + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspRouteConventionAttribute : Attribute + { + public AspRouteConventionAttribute() + { + } + + public AspRouteConventionAttribute(string predefinedPattern) + { + PredefinedPattern = predefinedPattern; + } + + [CanBeNull] public string PredefinedPattern { get; } + } + + /// + /// Indicates that the marked method parameter contains default route values of routing convention for ASP.NET. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspDefaultRouteValuesAttribute : Attribute + { + } + + /// + /// Indicates that the marked method parameter contains constraints on route values of routing convention for ASP.NET. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspRouteValuesConstraintsAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter or property contains routing order provided by ASP.NET routing attribute. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspRouteOrderAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter or property contains HTTP verbs provided by ASP.NET routing attribute. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspRouteVerbsAttribute : Attribute + { + } + + /// + /// Indicates that the marked attribute is used for attribute routing in ASP.NET. + /// + /// + /// The IDE will analyze all usages of attributes marked with this attribute, + /// and will add all routes to completion, navigation and other features over URI strings. + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspAttributeRoutingAttribute : Attribute + { + public string HttpVerb { get; set; } + } + + /// + /// Indicates that the marked method declares an ASP.NET Minimal API endpoint. + /// + /// + /// The IDE will analyze all usages of methods marked with this attribute, + /// and will add all routes to completion, navigation and other features over URI strings. + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMinimalApiDeclarationAttribute : Attribute + { + public string HttpVerb { get; set; } + } + + /// + /// Indicates that the marked method declares an ASP.NET Minimal API endpoints group. + /// + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMinimalApiGroupAttribute : Attribute + { + } + + /// + /// Indicates that the marked parameter contains an ASP.NET Minimal API endpoint handler. + /// + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMinimalApiHandlerAttribute : Attribute + { + } + + /// + /// Indicates that the marked method contains Minimal API endpoint declaration. + /// + /// + /// The IDE will analyze all usages of methods marked with this attribute, + /// and will add all declared in attributes routes to completion, navigation and other features over URI strings. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class AspMinimalApiImplicitEndpointDeclarationAttribute : Attribute + { + public string HttpVerb { get; set; } + + public string RouteTemplate { get; set; } + + public Type BodyType { get; set; } + + /// + /// Comma-separated list of query parameters defined for endpoint + /// + public string QueryParameters { get; set; } + } + + #endregion + + #region Razor + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class HtmlElementAttributesAttribute : Attribute + { + public HtmlElementAttributesAttribute() + { + } + + public HtmlElementAttributesAttribute([NotNull] string name) + { + Name = name; + } + + [CanBeNull] public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class HtmlAttributeValueAttribute : Attribute + { + public HtmlAttributeValueAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + /// + /// Razor attribute. Indicates that the marked parameter or method is a Razor section. + /// Use this attribute for custom wrappers similar to + /// System.Web.WebPages.WebPageBase.RenderSection(String). + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorSectionAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorImportNamespaceAttribute : Attribute + { + public RazorImportNamespaceAttribute([NotNull] string name) + { + Name = name; + } + + [NotNull] public string Name { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorInjectionAttribute : Attribute + { + public RazorInjectionAttribute([NotNull] string type, [NotNull] string fieldName) + { + Type = type; + FieldName = fieldName; + } + + [NotNull] public string Type { get; } + + [NotNull] public string FieldName { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorDirectiveAttribute : Attribute + { + public RazorDirectiveAttribute([NotNull] string directive) + { + Directive = directive; + } + + [NotNull] public string Directive { get; } + } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorPageBaseTypeAttribute : Attribute + { + public RazorPageBaseTypeAttribute([NotNull] string baseType) + { + BaseType = baseType; + } + + public RazorPageBaseTypeAttribute([NotNull] string baseType, string pageName) + { + BaseType = baseType; + PageName = pageName; + } + + [NotNull] public string BaseType { get; } + [CanBeNull] public string PageName { get; } + } + + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorHelperCommonAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorLayoutAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorWriteLiteralMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Method)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorWriteMethodAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Parameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class RazorWriteMethodParameterAttribute : Attribute + { + } + + #endregion + + #region XAML + + /// + /// XAML attribute. Indicates the type that has an ItemsSource property and should be treated + /// as an ItemsControl-derived type, to enable inner items DataContext type resolution. + /// + [AttributeUsage(AttributeTargets.Class)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class XamlItemsControlAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the property of some BindingBase-derived type, that + /// is used to bind some item of an ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// The property should have the tree ancestor of the ItemsControl type, or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class XamlItemBindingOfItemsControlAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates the property of some Style-derived type that + /// is used to style items of an ItemsControl-derived type. This annotation will + /// enable the DataContext type resolve for XAML bindings for such properties. + /// + /// + /// Property should have the tree ancestor of the ItemsControl type or + /// marked with the attribute. + /// + [AttributeUsage(AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class XamlItemStyleOfItemsControlAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates that DependencyProperty has OneWay binding mode by default. + /// + /// + /// This attribute must be applied to DependencyProperty's CLR accessor property if it is present, or to a DependencyProperty descriptor field otherwise. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class XamlOneWayBindingModeByDefaultAttribute : Attribute + { + } + + /// + /// XAML attribute. Indicates that DependencyProperty has TwoWay binding mode by default. + /// + /// + /// This attribute must be applied to DependencyProperty's CLR accessor property if it is present, or to a DependencyProperty descriptor field otherwise. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class XamlTwoWayBindingModeByDefaultAttribute : Attribute + { + } + + #endregion + + #region Unit Testing + + /// + /// Specifies the subject being tested by a test class or a test method. + /// + /// + /// The can be applied to a test class or a test method to indicate what class + /// or interface the tests defined in them test. This information can be used by an IDE to provide better navigation + /// support or by test runners to group tests by subject and to provide better test reports. + /// + [AttributeUsage( + AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Interface, + AllowMultiple = true)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class TestSubjectAttribute : Attribute + { + /// + /// Gets the type of the subject being tested. + /// + [NotNull] + public Type Subject { get; } + + /// + /// Initializes a new instance of the class with the specified subject type. + /// + /// The type of the subject being tested. + public TestSubjectAttribute([NotNull] Type subject) + { + Subject = subject; + } + } + + /// + /// Signifies a generic argument as the test subject for a test class. + /// + /// + /// The can be applied to a generic parameter of a base test class to indicate that + /// the type passed as the argument is the class being tested. This information can be used by an IDE to provide better + /// navigation support or by test runners to group tests by subject and to provide better test reports. + /// + /// + /// public class BaseTestClass<[MeansTestSubject] T> + /// { + /// protected T Component { get; } + /// } + /// + /// public class CalculatorAdditionTests : BaseTestClass<Calculator> + /// { + /// [Test] + /// public void Should_add_two_numbers() + /// { + /// Assert.That(Component.Add(2, 3), Is.EqualTo(5)); + /// } + /// } + /// + [AttributeUsage(AttributeTargets.GenericParameter)] + [Conditional("JETBRAINS_ANNOTATIONS")] + internal sealed class MeansTestSubjectAttribute : Attribute + { + } + + #endregion +} \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs.meta b/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs.meta new file mode 100644 index 00000000..6be89dd6 --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/JetBrainsAnnotations.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a4cd97bf127e4089b87d103aea619621 +timeCreated: 1717367862 \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations/assembly-info.cs b/RQ-Core/JetBrainsAnnotations/assembly-info.cs new file mode 100644 index 00000000..8959d0a6 --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/assembly-info.cs @@ -0,0 +1,7 @@ +#region + +using System.Runtime.CompilerServices; + +#endregion + +[assembly: InternalsVisibleTo("nadena.dev.ndmf.reactive-query.core")] \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations/assembly-info.cs.meta b/RQ-Core/JetBrainsAnnotations/assembly-info.cs.meta new file mode 100644 index 00000000..5995c800 --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/assembly-info.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0254cf982db5436295033e3fc5a3b7dd +timeCreated: 1717367862 \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef b/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef new file mode 100644 index 00000000..76f4498a --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef @@ -0,0 +1,14 @@ +{ + "name": "nadena.dev.ndmf.reactive-query.jetbrains-annotations", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef.meta b/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef.meta new file mode 100644 index 00000000..5610683a --- /dev/null +++ b/RQ-Core/JetBrainsAnnotations/nadena.dev.ndmf.reactive-query.jetbrains-annotations.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 139f0abb049c44f18b29dd824ebf1f20 +timeCreated: 1717367862 \ No newline at end of file diff --git a/RQ-Core/ObjectIdentityComparer.cs b/RQ-Core/ObjectIdentityComparer.cs new file mode 100644 index 00000000..702b9f0e --- /dev/null +++ b/RQ-Core/ObjectIdentityComparer.cs @@ -0,0 +1,25 @@ +#region + +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + internal class ObjectIdentityComparer : IEqualityComparer + { + public static ObjectIdentityComparer Instance { get; } = new ObjectIdentityComparer(); + + + public bool Equals(T x, T y) + { + return ReferenceEquals(x, y); + } + + public int GetHashCode(T obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } +} \ No newline at end of file diff --git a/RQ-Core/ObjectIdentityComparer.cs.meta b/RQ-Core/ObjectIdentityComparer.cs.meta new file mode 100644 index 00000000..241edfc3 --- /dev/null +++ b/RQ-Core/ObjectIdentityComparer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bff596dec3994e08868aa0834f0cabfc +timeCreated: 1714257299 \ No newline at end of file diff --git a/RQ-Core/ReactiveField.cs b/RQ-Core/ReactiveField.cs new file mode 100644 index 00000000..e9aa9d66 --- /dev/null +++ b/RQ-Core/ReactiveField.cs @@ -0,0 +1,36 @@ +#region + +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public sealed class ReactiveField + { + private T _value; + + public T Value + { + get => _value; + set + { + _value = value; + _reactiveValue.Invalidate(); + } + } + + private ReactiveValue _reactiveValue; + + public ReactiveValue AsReactiveValue() + { + return _reactiveValue; + } + + public ReactiveField(T value) + { + _value = value; + _reactiveValue = ReactiveValue.Create("reactive field", _ => Task.FromResult(_value)); + } + } +} \ No newline at end of file diff --git a/RQ-Core/ReactiveField.cs.meta b/RQ-Core/ReactiveField.cs.meta new file mode 100644 index 00000000..5a49885f --- /dev/null +++ b/RQ-Core/ReactiveField.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7063bf7e2e2b4a4aa7ebd50cdc4b0706 +timeCreated: 1716151280 \ No newline at end of file diff --git a/RQ-Core/ReactiveQuery.cs b/RQ-Core/ReactiveQuery.cs new file mode 100644 index 00000000..0633f60c --- /dev/null +++ b/RQ-Core/ReactiveQuery.cs @@ -0,0 +1,134 @@ +#region + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + /// + /// Represents a mapping from T to ReactiveValue, which is computed and updated asynchronously. + /// + /// + /// + public sealed class ReactiveQuery where T : class + { + private readonly object _lock = new object(); + private readonly string _description; + private readonly Func> _compute; + private readonly Dictionary, WeakReference>> _cache = new(); + + private int additions = 0; + + public ReactiveQuery(string description, Func> compute) + { + _compute = compute; + _description = description; + } + + public ReactiveValue Get(T key) + { + lock (_lock) + { + if (_cache.TryGetValue(new WeakKey(key), out var weakQuery)) + { + if (weakQuery.TryGetTarget(out var query)) + { + return query; + } + } + + var newQuery = new CacheValue(key, _compute, _description); + _cache[new WeakKey(key)] = new WeakReference>(newQuery); + additions++; + + if (additions > _cache.Count / 2) + { + PruneCache(); + } + + return newQuery; + } + } + + private void PruneCache() + { + lock (_lock) + { + additions = 0; + + var keysToRemove = new List>(); + foreach (var pair in _cache) + { + if (!pair.Value.TryGetTarget(out _)) + { + keysToRemove.Add(pair.Key); + } + } + + foreach (var key in keysToRemove) + { + _cache.Remove(key); + } + } + } + + private class WeakKey where T : class + { + private readonly WeakReference _key; + private int _hashCode; + + public WeakKey(T key) + { + _key = new WeakReference(key); + _hashCode = key.GetHashCode(); + } + + public override int GetHashCode() + { + return _hashCode; + } + + public override bool Equals(object obj) + { + if (this == obj) return true; + + if (obj is WeakKey other) + { + if (_key.TryGetTarget(out var key) && other._key.TryGetTarget(out var otherKey)) + { + return key.Equals(otherKey); + } + } + + return false; + } + } + + private class CacheValue : ReactiveValue + { + private readonly string _description; + private readonly T _key; + private readonly Func> _compute; + + public CacheValue(T key, Func> compute, string description) + { + _key = key; + _compute = compute; + _description = description + " for " + key; + } + + protected override Task Compute(ComputeContext context) + { + return _compute(context, _key); + } + + public override string ToString() + { + return _description; + } + } + } +} \ No newline at end of file diff --git a/RQ-Core/ReactiveQuery.cs.meta b/RQ-Core/ReactiveQuery.cs.meta new file mode 100644 index 00000000..6b8ada11 --- /dev/null +++ b/RQ-Core/ReactiveQuery.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 92fcabc7f9824770bae2d4d16ef5f454 +timeCreated: 1716158294 \ No newline at end of file diff --git a/RQ-Core/ReactiveQueryScheduler.cs b/RQ-Core/ReactiveQueryScheduler.cs new file mode 100644 index 00000000..44b9431b --- /dev/null +++ b/RQ-Core/ReactiveQueryScheduler.cs @@ -0,0 +1,38 @@ +#region + +using System.Threading; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public static class ReactiveQueryScheduler + { + public static TaskFactory DefaultTaskFactory { get; set; } = new TaskFactory(TaskScheduler.Default); + + public static ThreadLocal SynchronizationContextOverride { get; } = new(() => null); + + public static SynchronizationContext SynchronizationContext => + SynchronizationContextOverride.Value ?? SynchronizationContext.Current; + + + public static TaskScheduler TaskScheduler + { + get + { + var oldContext = SynchronizationContext.Current; + if (SynchronizationContextOverride.Value != null) + { + SynchronizationContext.SetSynchronizationContext(SynchronizationContextOverride.Value); + } + + var scheduler = TaskScheduler.FromCurrentSynchronizationContext(); + + SynchronizationContext.SetSynchronizationContext(oldContext); + + return scheduler; + } + } + } +} \ No newline at end of file diff --git a/RQ-Core/ReactiveQueryScheduler.cs.meta b/RQ-Core/ReactiveQueryScheduler.cs.meta new file mode 100644 index 00000000..1234bb1b --- /dev/null +++ b/RQ-Core/ReactiveQueryScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 69391bc71b4c469fad11dfa8e29eb58f +timeCreated: 1714266067 \ No newline at end of file diff --git a/RQ-Core/ReactiveValue.cs b/RQ-Core/ReactiveValue.cs new file mode 100644 index 00000000..8ed8f2d4 --- /dev/null +++ b/RQ-Core/ReactiveValue.cs @@ -0,0 +1,486 @@ +#region + +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + /// + /// A ReactiveQuery represents a cached computation, which can be automatically invalidated and recomputed when + /// something it relied upon changes. + /// + /// ## Obtaining values from a ReactiveQuery + /// + /// There are four ways to obtain a value from a ReactiveQuery: + /// 1. Continually, by subscribing to the query using `Subscribe`. This option will trigger the computation of the + /// value if it is not already available, and will also trigger the computation of the value whenever the query is + /// invalidated. + /// 2. Speculatively, using `TryGetValue` (which will return `false` if the value is not yet available). This option + /// does not trigger the computation of the value in most cases. + /// 2. Asynchronously, using `GetValueAsync` (which will return a `Task` that will complete when the value is + /// available). This option will trigger the computation of the value if it is not already available. + /// 4. From within another ReactiveQuery, by using `ComputeContext.Observe`. This will record the dependency on the + /// other query, and will trigger the computation of the value if it is not already available. It will then + /// arrange for the calling query to be re-computed whenever the observed query is invalidated. + /// + /// ## Writing a ReactiveQuery + /// + /// To write a ReactiveQuery, you must implement the `Compute` and `ToString` methods. `Compute` will be invoked + /// when the query is invalidated, and should return the new value of the computation. Note that, if something + /// is invalidated while the query is updating, the computation will be cancelled (throwing `TaskCancelledException`s + /// when observing sub-queries) and restarted. + /// + /// Generally, it is important to cache the ReactiveQuery itself somehow (you won't get a lot of benefit from caching + /// if you create a new ReactiveQuery every time!) + /// + /// ## Threading notes + /// + /// ReactiveQuery will avoid invoking Compute more than once in parallel; even if invalidated, the last execution + /// will run to completion (and its result will be ignored), then the new computation will be started. + /// + /// Likewise, when using the IObservable interface to observe the state of a query, ReactiveQuery will not invoke + /// methods on any particular observer in parallel. It is not guaranteed that observers will see every computed + /// value; we only guarantee that eventually, if invalidations stop, all observers will see the last value. + /// + /// ## Using ReactiveQuery in Unity + /// + /// When using RQ in Unity, generally you'll want to use the `Subscribe` method to drive various unity editor UI + /// bits. If you need to access a ReactiveQuery _synchronously_ (for example, in a NDMF plugin), refer to + /// `ReactiveQueryUnityExt.GetSync`. + /// + /// The default TaskFactory for RQ on Unity projects will be one that runs on the Unity main thread. You can + /// override this by overriding the `Scheduler` property with an appropriate `TaskFactory`. + /// + /// + /// + public abstract class ReactiveValue : IObservable + { + [PublicAPI] protected virtual TaskScheduler TaskScheduler { get; } = ReactiveQueryScheduler.TaskScheduler; + + #region State + + private object _lock = new(); + + // Locked by _lock + private long _invalidationCount = 0; + + private CancellationToken _cancellationToken = CancellationToken.None; + private Task _cancelledTask = null; + private TaskCompletionSource _invalidated = null; + + private bool _currentValueIsValid = false; + + private Task _valueTask = null; + + // Used to drive DestroyObsoleteValue + private T _currentValue = default; + private Exception _currentValueException = null; + + #endregion + + #region Public API + + private class SimpleValue : ReactiveValue + { + private string _description; + private Func> _compute; + + public SimpleValue(string description, Func> compute) + { + _description = description; + _compute = compute; + } + + protected override Task Compute(ComputeContext context) + { + return _compute(context); + } + + public override string ToString() + { + return _description; + } + } + + /// + /// Creates a ReactiveQuery based on a computation delegate. + /// + /// The description of the query, used in error messages + /// The function to invoke to compute the query + /// + /// + public static ReactiveValue Create(string description, Func> compute) + { + return new SimpleValue(description, compute); + } + + public ReactiveValue Map(Func map) + { + return ReactiveValue.Create(ToString(), + async context => { return map(await context.Observe(this)); }); + } + + /// + /// Attempts to get the current value, but only if it is available immediately. + /// + /// If the value is unavailable immediately: + /// * If a value has been computed previously, a stale value will be placed in `value`, and the function will + /// return false. + /// * If no value has been computed yet, `value` will contain `default`. + /// * In either case, an asynchronous computation will be initiated. + /// + /// The value, if available + /// True if the value was available, false if not + /// If the last computation failed + public bool TryGetValue(out T value) + { + lock (_lock) + { + value = _currentValue; + if (_currentValueException != null) + { + throw _currentValueException; + } + + if (!_currentValueIsValid) + { + RequestCompute(); + return false; + } + + return true; + } + } + + /// + /// Returns a Task which will resolve to the query's latest value. + /// + /// + public async Task GetValueAsync() + { + while (true) + { + try + { + return await RequestCompute(); + } + catch (TaskCanceledException e) + { + continue; + } + } + } + + /// + /// Returns a task which will complete the next time this task is invalidated. + /// + public Task Invalidated + { + get + { + lock (_lock) + { + if (_invalidated == null) + { + _invalidated = new TaskCompletionSource(); + } + + return _invalidated.Task; + } + } + } + + #endregion + + #region IObservable API + + private class ObserverContext + { + private readonly TaskScheduler _scheduler; + private IObserver _observer; + private Task _priorInvocation = Task.CompletedTask; + + public ObserverContext(IObserver observer, TaskScheduler scheduler) + { + _observer = observer; + _scheduler = scheduler; + } + + public void Invoke(Action> action) + { + _priorInvocation = _priorInvocation.ContinueWith(_ => action(_observer), + CancellationToken.None, + // Ensure that we don't invoke an observation while holding our lock + TaskContinuationOptions.RunContinuationsAsynchronously, + _scheduler + ); + } + } + + private HashSet> _observers = new(new ObjectIdentityComparer>()); + + /// + /// Subscribes an observer to this query. The observer will be executed on the TaskScheduler associated with the + /// current synchronization context. + /// + /// + /// A disposable which will deregister the observer, once disposed + public IDisposable Subscribe(IObserver observer) + { + return Subscribe(observer, null); + } + + /// + /// Subscribes an observer to this query. The observer will be executed on the provided TaskScheduler. + /// If the provided scheduler is null, the observer will be executed on the TaskScheduler associated with the + /// current synchronization context. + /// + /// + /// + /// + [PublicAPI] + public IDisposable Subscribe(IObserver observer, TaskScheduler scheduler) + { + scheduler = scheduler ?? TaskScheduler.FromCurrentSynchronizationContext(); + + var observerContext = new ObserverContext(observer, scheduler); + + lock (_lock) + { + _observers.Add(observerContext); + + if (_currentValueIsValid) + { + var cv = _currentValue; + var ex = _currentValueException; + + observerContext.Invoke(o => + { + if (ex != null) + { + o.OnError(ex); + } + else + { + o.OnNext(cv); + } + }); + } + else + { + RequestCompute(); + } + } + + return new RemoveObserver(this, observerContext); + } + + private class RemoveObserver : IDisposable + { + private readonly ReactiveValue _parent; + private readonly ObserverContext _observer; + + public RemoveObserver(ReactiveValue parent, ObserverContext observer) + { + _parent = parent; + _observer = observer; + } + + public void Dispose() + { + lock (_parent._lock) + { + _parent._observers.Remove(_observer); + _observer.Invoke(o => o.OnCompleted()); + } + } + } + + /// + /// Immediately invalidates the query. If there are downstream computations or observers, the query will be + /// recomputed. + /// + public void Invalidate() + { + Invalidate(-1); + } + + #endregion + + #region Subclass API + + /// + /// Invoked when the query needs to be recomputed. This method should return the new value of the computation. + /// + /// + /// + protected abstract Task Compute(ComputeContext context); + + /// + /// Invoked when the query is invalidated and the current value is no longer needed. This method should clean up + /// any resources associated with the passed value. + /// + /// + protected virtual void DestroyObsoleteValue(T value) + { + // no-op + } + + // Implementing ToString is mandatory for all subclasses + public abstract override string ToString(); + + #endregion + + #region Internal API + + internal void Invalidate(long expectedSeq) + { + using (new SyncContextScope(ReactiveQueryScheduler.SynchronizationContext)) + { + TaskCompletionSource invalidationToken = null; + + lock (_lock) + { + if (expectedSeq == _invalidationCount || expectedSeq == -1) + { + if (_valueTask != null && !_valueTask.IsCompleted) + { + _cancelledTask = _valueTask; + } + + invalidationToken = _invalidated; + _invalidated = null; + _invalidationCount++; + _valueTask = null; + + _currentValueIsValid = false; + } + + if (_observers.Count > 0) + { + RequestCompute(); + + foreach (var observer in _observers) + { + observer.Invoke(o => (o as IInvalidationObserver)?.OnInvalidate()); + } + } + } + + // This triggers invalidation of downstream queries (as well as potentially other user code), so drop the + // lock before invoking it... + invalidationToken?.SetResult(null); + } + } + + internal async Task ComputeInternal(ComputeContext context) + { + await TaskThrottle.MaybeThrottle(); + + long seq = _invalidationCount; + + Task cancelledTask; + lock (_lock) + { + cancelledTask = _cancelledTask; + _cancelledTask = null; + + context.OnInvalidate = Invalidated; + } + + // Ensure we don't ever have multiple instances of the same RQ computation running in parallel + if (cancelledTask != null) + { + await cancelledTask.ContinueWith(_ => { }); // swallow exceptions + } + + T result; + ExceptionDispatchInfo e; + try + { + result = await Compute(context); + e = null; + } + catch (Exception ex) + { + result = default; + e = ExceptionDispatchInfo.Capture(ex); + } + + Console.WriteLine("ComputeInternal: before lock"); + lock (_lock) + { + if (_invalidationCount == seq) + { + if (e == null && !ReferenceEquals(result, _currentValue)) + { + DestroyObsoleteValue(_currentValue); + } + + _currentValue = result; + _currentValueException = e?.SourceException; + _currentValueIsValid = true; + + Action> op = observer => + { + if (e != null) + { + observer.OnError(e.SourceException); + } + else + { + observer.OnNext(result); + } + }; + + Console.WriteLine("ComputeInternal: before observers"); + foreach (var observer in _observers) + { + observer.Invoke(op); + } + } + } + + Console.WriteLine("ComputeInternal: before exit"); + e?.Throw(); + return result; + } + + internal Task RequestCompute() + { + lock (_lock) + { + if (_valueTask == null) + { + var context = new ComputeContext(() => ToString()); + + var invalidateSeq = _invalidationCount; + context.Invalidate = () => Invalidate(invalidateSeq); + // TODO: arrange for cancellation when we invalidate the task + context.CancellationToken = new CancellationToken(); + + using (new SyncContextScope(ReactiveQueryScheduler.SynchronizationContext)) + { + // _context.Activate(); + _valueTask = Task.Factory.StartNew( + () => ComputeInternal(context), + context.CancellationToken, + TaskCreationOptions.None, + TaskScheduler + ).Unwrap(); + } + } + + return _valueTask; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/RQ-Core/ReactiveValue.cs.meta b/RQ-Core/ReactiveValue.cs.meta new file mode 100644 index 00000000..4d3e5781 --- /dev/null +++ b/RQ-Core/ReactiveValue.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1f79bd7aba4a49b88bec8f2fbef092da +timeCreated: 1713143151 \ No newline at end of file diff --git a/RQ-Core/SyncContextScope.cs b/RQ-Core/SyncContextScope.cs new file mode 100644 index 00000000..b297c1e9 --- /dev/null +++ b/RQ-Core/SyncContextScope.cs @@ -0,0 +1,24 @@ +#region + +using System; +using System.Threading; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public sealed class SyncContextScope : IDisposable + { + SynchronizationContext _old = SynchronizationContext.Current; + + public SyncContextScope(SynchronizationContext context) + { + SynchronizationContext.SetSynchronizationContext(context); + } + + public void Dispose() + { + SynchronizationContext.SetSynchronizationContext(_old); + } + } +} \ No newline at end of file diff --git a/RQ-Core/SyncContextScope.cs.meta b/RQ-Core/SyncContextScope.cs.meta new file mode 100644 index 00000000..a0457f21 --- /dev/null +++ b/RQ-Core/SyncContextScope.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f19971b82c8c4b2d9ae62cddd183992f +timeCreated: 1714617144 \ No newline at end of file diff --git a/RQ-Core/SynchronousTaskScheduler.cs b/RQ-Core/SynchronousTaskScheduler.cs new file mode 100644 index 00000000..9ef4c80c --- /dev/null +++ b/RQ-Core/SynchronousTaskScheduler.cs @@ -0,0 +1,31 @@ +#region + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + internal sealed class SynchronousTaskScheduler : TaskScheduler + { + internal static SynchronousTaskScheduler Instance { get; } = new SynchronousTaskScheduler(); + + protected override IEnumerable GetScheduledTasks() + { + return Array.Empty(); + } + + protected override void QueueTask(Task task) + { + TryExecuteTask(task); + } + + protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + { + TryExecuteTask(task); + return true; + } + } +} \ No newline at end of file diff --git a/RQ-Core/SynchronousTaskScheduler.cs.meta b/RQ-Core/SynchronousTaskScheduler.cs.meta new file mode 100644 index 00000000..44de798e --- /dev/null +++ b/RQ-Core/SynchronousTaskScheduler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 00913519e61941999795b6ff98706689 +timeCreated: 1714260387 \ No newline at end of file diff --git a/RQ-Core/TaskExt.cs b/RQ-Core/TaskExt.cs new file mode 100644 index 00000000..8cb2c9d8 --- /dev/null +++ b/RQ-Core/TaskExt.cs @@ -0,0 +1,50 @@ +#region + +using System.Threading; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public static class TaskExt + { + /// + /// Prevents deep recursion by ensuring that this task, upon completion, returns to the thread pool instead of + /// immediately calling its continuation. This should be used carefully, as it can negatively impact performance. + /// + /// This differs from simply using TaskContinuationOptions.RunContinuationsAsynchronously in that it will + /// ensure that the correct synchronization context is used for the continuation. + /// + /// + /// + public static Task PreventRecursion(this Task t) + { + return t.ContinueWith( + t2 => t2, + CancellationToken.None, + TaskContinuationOptions.RunContinuationsAsynchronously, + TaskScheduler.FromCurrentSynchronizationContext() + ); + } + + /// + /// Prevents deep recursion by ensuring that this task, upon completion, returns to the thread pool instead of + /// immediately calling its continuation. This should be used carefully, as it can negatively impact performance. + /// + /// This differs from simply using TaskContinuationOptions.RunContinuationsAsynchronously in that it will + /// ensure that the correct synchronization context is used for the continuation. + /// + /// + /// + public static Task PreventRecursion(this Task t) + { + return t.ContinueWith( + t2 => t2.Result, + CancellationToken.None, + TaskContinuationOptions.RunContinuationsAsynchronously, + TaskScheduler.FromCurrentSynchronizationContext() + ); + } + } +} \ No newline at end of file diff --git a/RQ-Core/TaskExt.cs.meta b/RQ-Core/TaskExt.cs.meta new file mode 100644 index 00000000..0192d97e --- /dev/null +++ b/RQ-Core/TaskExt.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4803bf2a36f543059b3922ef6dba5e78 +timeCreated: 1714619078 \ No newline at end of file diff --git a/RQ-Core/TaskThrottle.cs b/RQ-Core/TaskThrottle.cs new file mode 100644 index 00000000..fbdd9c74 --- /dev/null +++ b/RQ-Core/TaskThrottle.cs @@ -0,0 +1,49 @@ +#region + +using System; +using System.Threading; +using System.Threading.Tasks; + +#endregion + +namespace nadena.dev.ndmf.rq +{ + public static class TaskThrottle + { + public static readonly ThreadLocal> ShouldThrottle = new(() => () => false); + + public static async ValueTask MaybeThrottle() + { + if (ShouldThrottle.Value()) + { + await Task.CompletedTask.ContinueWith( + _ => Task.CompletedTask, + CancellationToken.None, + TaskContinuationOptions.RunContinuationsAsynchronously, + TaskScheduler.Current + ); + } + } + + public static IDisposable WithThrottleCondition(Func condition) + { + return new ThrottleConditionScope(condition); + } + + private class ThrottleConditionScope : IDisposable + { + private readonly Func _previousCondition; + + public ThrottleConditionScope(Func condition) + { + _previousCondition = ShouldThrottle.Value; + ShouldThrottle.Value = condition; + } + + public void Dispose() + { + ShouldThrottle.Value = _previousCondition; + } + } + } +} \ No newline at end of file diff --git a/RQ-Core/TaskThrottle.cs.meta b/RQ-Core/TaskThrottle.cs.meta new file mode 100644 index 00000000..5d9d04b7 --- /dev/null +++ b/RQ-Core/TaskThrottle.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e7ea458ccf8b4864a5539cd8eaa0bc74 +timeCreated: 1714354386 \ No newline at end of file diff --git a/RQ-Core/assembly-info.cs b/RQ-Core/assembly-info.cs new file mode 100644 index 00000000..b88f465f --- /dev/null +++ b/RQ-Core/assembly-info.cs @@ -0,0 +1,7 @@ +#region + +using System.Runtime.CompilerServices; + +#endregion + +[assembly: InternalsVisibleTo("nadena.dev.ndmf")] \ No newline at end of file diff --git a/RQ-Core/assembly-info.cs.meta b/RQ-Core/assembly-info.cs.meta new file mode 100644 index 00000000..9e541117 --- /dev/null +++ b/RQ-Core/assembly-info.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ae28ada1f2524bbba57e038ec9a0e1e1 +timeCreated: 1714360247 \ No newline at end of file diff --git a/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef b/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef new file mode 100644 index 00000000..8ad22006 --- /dev/null +++ b/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef @@ -0,0 +1,16 @@ +{ + "name": "nadena.dev.ndmf.reactive-query.core", + "rootNamespace": "", + "references": [ + "nadena.dev.ndmf.reactive-query.jetbrains-annotations" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef.meta b/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef.meta new file mode 100644 index 00000000..c00b8199 --- /dev/null +++ b/RQ-Core/nadena.dev.ndmf.reactive-query.core.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dea0612daadfed648b1e06f1a009ab5e +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/SelfDestructComponent.cs b/Runtime/SelfDestructComponent.cs new file mode 100644 index 00000000..69226799 --- /dev/null +++ b/Runtime/SelfDestructComponent.cs @@ -0,0 +1,29 @@ +#region + +using System; +using UnityEditor; +using UnityEngine; + +#endregion + +/// +/// This component will self destruct one frame after load, unless the KeepAlive field is set to a live object. +/// +[AddComponentMenu("")] +public class SelfDestructComponent : MonoBehaviour +{ + [NonSerialized] public object KeepAlive; // don't destroy when non-null (non-serialized field) + + void OnValidate() + { +#if UNITY_EDITOR + EditorApplication.delayCall += () => + { + if (this != null && KeepAlive == null) + { + DestroyImmediate(gameObject); + } + }; +#endif + } +} \ No newline at end of file diff --git a/Runtime/SelfDestructComponent.cs.meta b/Runtime/SelfDestructComponent.cs.meta new file mode 100644 index 00000000..359a6617 --- /dev/null +++ b/Runtime/SelfDestructComponent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 85007fe4bf2143538d606445019b01a2 +timeCreated: 1717367902 \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests.meta b/UnitTests~/RQ-EditorTests.meta new file mode 100644 index 00000000..3b47ec19 --- /dev/null +++ b/UnitTests~/RQ-EditorTests.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 25904f74e2894a23916b8081830b7498 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs b/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs new file mode 100644 index 00000000..d79cc47c --- /dev/null +++ b/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs @@ -0,0 +1,67 @@ +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using nadena.dev.ndmf.rq; +using nadena.dev.ndmf.rq.StandaloneTests; +using NUnit.Framework; +using UnityEditor; +using UnityEngine; + +namespace UnitTests.EditorTests +{ + public class RQUnityIntegrationTest + { + private static int mainThreadId; + + [InitializeOnLoadMethod] + private static void Initialize() + { + mainThreadId = Thread.CurrentThread.ManagedThreadId; + } + + [Test] + public async Task ReactiveQueriesRunInMainThread() + { + ReactiveValue rq = + ReactiveValue.Create("", _ => Task.FromResult(Thread.CurrentThread.ManagedThreadId)); + + Assert.AreEqual(mainThreadId, await rq.GetValueAsync().Timeout()); + } + + [Test] + public async Task ReactiveQueriesThrottle() + { + int startedCount = 0; + List> queries = new List>(); + + var pq = ReactiveValue.Create("", _ => Task.FromResult(1)); + + for (int i = 0; i < 10; i++) + { + queries.Insert(0, ReactiveValue.Create("", async ctx => + { + Interlocked.Increment(ref startedCount); + //.Debug.Log("sleep start"); + Thread.Sleep(50); + //Debug.Log("sleep end"); + return 1; + }).GetValueAsync().ContinueWith(t => + { + //Debug.Log("Task complete"); + return t.Result; + })); + } + + await Task.Delay(25);//.ContinueWith(_ => Debug.Log("Delay complete")); + + var completedCount = queries.Count(q => q.IsCompleted); + Debug.Log("Completed: " + completedCount); + Assert.IsTrue(completedCount > 0); + Assert.IsTrue(completedCount < queries.Count); + + var allDone = Task.WhenAll(queries); + Assert.AreSame(allDone, await Task.WhenAny(allDone, Task.Delay(2000))); + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs.meta b/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs.meta new file mode 100644 index 00000000..b7dba987 --- /dev/null +++ b/UnitTests~/RQ-EditorTests/RQUnityIntegrationTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ecfc1aaa02224c569dfb32e8cd3a1272 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs b/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs new file mode 100644 index 00000000..84bdc1d6 --- /dev/null +++ b/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs @@ -0,0 +1,461 @@ +using System; +using System.Collections.Generic; +using nadena.dev.ndmf.rq.unity.editor; +using NUnit.Framework; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace UnitTests.EditorTests +{ + public class ShadowHierarchyTest + { + private List createdObjects = new List(); + + private T c(T obj) where T: UnityEngine.Object + { + createdObjects.Add(obj); + return obj; + } + + private GameObject c(string s) + { + return c(new GameObject(s)); + } + + [TearDown] + public void TearDown() + { + foreach (var obj in createdObjects) + { + Object.DestroyImmediate(obj); + } + + createdObjects.Clear(); + } + + [Test] + public void TestBasic() + { + var shadow = new ShadowHierarchy(); + + var gameObject = c(new GameObject("tmp")); + + var target = new object(); + bool wasFired = false; + + shadow.RegisterGameObjectListener(gameObject, (o, e) => + { + Assert.AreEqual(target, o); + Assert.AreEqual(HierarchyEvent.ObjectDirty, e); + wasFired = true; + return false; + }, target); + + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + Assert.IsTrue(wasFired); + + wasFired = false; + + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + Assert.IsTrue(wasFired); + } + + [Test] + public void ListenerDeregisteredAfterTrueReturn() + { + var shadow = new ShadowHierarchy(); + var gameObject = c(new GameObject("tmp")); + + int count = 0; + var target = new object(); + + shadow.RegisterGameObjectListener(gameObject, (o, e) => + { + count++; + return true; + }, target); + + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + + Assert.AreEqual(1, count); + } + + void MakeListener__WhenTargetGCd_ListenerIsRemoved(ShadowHierarchy h, GameObject gameObject, bool[] wasFired) + { + h.RegisterGameObjectListener(gameObject, (o,e ) => + { + wasFired[0] = true; + return false; + }, new object()); + } + [Test] + public void WhenTargetGCd_ListenerIsRemoved() + { + var shadow = new ShadowHierarchy(); + + var gameObject = c(new GameObject("tmp")); + + var target = new object(); + bool[] wasFired = {false}; + + // Ensure we don't have extra references on the stack still by creating the target object in a separate + // stack frame + MakeListener__WhenTargetGCd_ListenerIsRemoved(shadow, gameObject, wasFired); + + System.GC.Collect(999, GCCollectionMode.Forced, true); + System.GC.WaitForPendingFinalizers(); + + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + + Assert.IsFalse(wasFired[0]); + } + + [Test] + public void WhenDisposed_ListenerIsRemoved() + { + var shadow = new ShadowHierarchy(); + + var gameObject = c(new GameObject("tmp")); + + var target = new object(); + bool wasFired = false; + + var listener = shadow.RegisterGameObjectListener(gameObject, (o, e) => + { + Assert.AreEqual(target, e); + Assert.AreEqual(HierarchyEvent.ObjectDirty, o); + wasFired = true; + return false; + }, target); + + listener.Dispose(); + shadow.FireObjectChangeNotification(gameObject.GetInstanceID()); + + Assert.IsFalse(wasFired); + } + + [Test] + public void PathNotifications_GeneratedWhenImmediateParentChanged() + { + var shadow = new ShadowHierarchy(); + var p1 = c("p1"); + var p2 = c("p2"); + + var target = new object(); + bool wasFired = false; + + shadow.RegisterGameObjectListener(p2, (o, e) => + { + if (e == HierarchyEvent.PathChange) + { + wasFired = true; + } + + return false; + }, target); + shadow.EnablePathMonitoring(p2); + + p2.transform.SetParent(p1.transform); + + shadow.FireReparentNotification(p2.GetInstanceID()); + + Assert.IsTrue(wasFired); + } + + [Test] + public void PathNotifications_GeneratedWhenGrandparentChanged() + { + var shadow = new ShadowHierarchy(); + var p1 = c("p1"); + var p2 = c("p2"); + var p3 = c("p3"); + + var target = new object(); + bool wasFired = false; + + p1.transform.SetParent(p2.transform); + + shadow.RegisterGameObjectListener(p1, (o, e) => + { + if (e == HierarchyEvent.PathChange) + { + wasFired = true; + } + + return false; + }, target); + shadow.EnablePathMonitoring(p1); + + p2.transform.SetParent(p3.transform); + + shadow.FireReparentNotification(p2.GetInstanceID()); + + Assert.IsTrue(wasFired); + } + + [Test] + public void ComponentChangeNotifications_GeneratedWhenObjectItselfChanges() + { + var shadow = new ShadowHierarchy(); + var obj = c("obj"); + + List events = new List(); + + shadow.RegisterGameObjectListener(obj, (o, e) => + { + events.Add(e); + return false; + }, events); + + shadow.FireStructureChangeEvent(obj.GetInstanceID()); + + Assert.AreEqual(1, events.Count); + Assert.AreEqual(HierarchyEvent.SelfComponentsChanged, events[0]); + } + + [Test] + public void ComponentChangeNotifications_GeneratedWhenChildChanges() + { + var shadow = new ShadowHierarchy(); + var parent = c("p"); + var child = c("c"); + + child.transform.SetParent(parent.transform); + + List events = new List(); + + shadow.RegisterGameObjectListener(parent, (o, e) => + { + events.Add(e); + return false; + }, events); + + shadow.EnableComponentMonitoring(parent); + shadow.FireStructureChangeEvent(child.GetInstanceID()); + + Assert.AreEqual(1, events.Count); + Assert.AreEqual(HierarchyEvent.ChildComponentsChanged, events[0]); + } + + [Test] + public void ComponentChangeNotifications_FiredAfterReparents() + { + var shadow = new ShadowHierarchy(); + var p1 = c("p1"); + var p2 = c("p2"); + var p3 = c("p3"); + + p3.transform.SetParent(p2.transform); + + List events = new List(); + + shadow.RegisterGameObjectListener(p1, (o, e) => + { + events.Add(e); + return false; + }, events); + + shadow.EnableComponentMonitoring(p1); + + p2.transform.SetParent(p1.transform); + shadow.FireReparentNotification(p2.GetInstanceID()); + + // Assert.AreEqual(1, events.Count); - TODO - deduplicate events + Assert.IsFalse(events.Contains(HierarchyEvent.PathChange)); // we didn't register for this + Assert.IsTrue(events.Contains(HierarchyEvent.ChildComponentsChanged)); + + events.Clear(); + + shadow.FireStructureChangeEvent(p3.GetInstanceID()); + + // Assert.AreEqual(1, events.Count); - TODO - deduplicate events + Assert.IsTrue(events.Contains(HierarchyEvent.ChildComponentsChanged)); + } + + [Test] + public void ComponentChangeNotification_FiredAfterReorderEvent() + { + var shadow = new ShadowHierarchy(); + var p = c("p"); + var c1 = c("c1"); + + c1.transform.SetParent(p.transform); + + List events = new List(); + + shadow.RegisterGameObjectListener(p, (o, e) => + { + events.Add(e); + return false; + }, events); + + shadow.EnableComponentMonitoring(p); + + shadow.FireReorderNotification(c1.GetInstanceID()); + + Assert.AreEqual(1, events.Count); + Assert.IsTrue(events.Contains(HierarchyEvent.ChildComponentsChanged)); + } + + [Test] + public void OnDestroy_NotificationsBlasted() + { + var shadow = new ShadowHierarchy(); + + var o1 = c("o1"); + var o2 = c("o2"); + var o3 = c("o3"); + + o2.transform.SetParent(o1.transform); + o3.transform.SetParent(o2.transform); + + List<(int, HierarchyEvent)> events = new List<(int, HierarchyEvent)>(); + shadow.RegisterGameObjectListener(o1, (o, e) => + { + events.Add(((int) o, e)); + return false; + }, 1); + shadow.RegisterGameObjectListener(o2, (o, e) => + { + events.Add(((int) o, e)); + return false; + }, 2); + shadow.RegisterGameObjectListener(o3, (o, e) => + { + events.Add(((int) o, e)); + return false; + }, 3); + + shadow.EnableComponentMonitoring(o1); + + var o2_id = o2.GetInstanceID(); + Object.DestroyImmediate(o2); + + shadow.FireDestroyNotification(o2_id); + + Assert.Contains((1, HierarchyEvent.ChildComponentsChanged), events); + Assert.Contains((2, HierarchyEvent.ForceInvalidate), events); + Assert.Contains((3, HierarchyEvent.ForceInvalidate), events); + } + + private ListenerSet.Invokee AddToList(List<(int, HierarchyEvent)> events) + { + return (o, e) => + { + events.Add(((int) o, e)); + return false; + }; + } + + [Test] + public void OnReparentDestroyedObject_NotificationsBlasted() + { + var shadow = new ShadowHierarchy(); + + var o1 = c("o1"); + var o2 = c("o2"); + var o3 = c("o3"); + + o2.transform.SetParent(o1.transform); + o3.transform.SetParent(o2.transform); + + List<(int, HierarchyEvent)> events = new List<(int, HierarchyEvent)>(); + shadow.RegisterGameObjectListener(o1, AddToList(events), 1); + shadow.RegisterGameObjectListener(o2, AddToList(events), 2); + shadow.RegisterGameObjectListener(o3, AddToList(events), 3); + + shadow.EnableComponentMonitoring(o1); + + var o2_id = o2.GetInstanceID(); + Object.DestroyImmediate(o2); + + shadow.FireReparentNotification(o2_id); + + Assert.Contains((1, HierarchyEvent.ChildComponentsChanged), events); + Assert.Contains((2, HierarchyEvent.ForceInvalidate), events); + Assert.Contains((3, HierarchyEvent.ForceInvalidate), events); + } + + [Test] + public void OnInvalidateAll_EverythingIsInvalidated() + { + var shadow = new ShadowHierarchy(); + + var o1 = c("o1"); + var o2 = c("o2"); + var o3 = c("o3"); + + o2.transform.SetParent(o1.transform); + o3.transform.SetParent(o2.transform); + + List<(int, HierarchyEvent)> events = new List<(int, HierarchyEvent)>(); + shadow.RegisterGameObjectListener(o1, AddToList(events), 1); + shadow.RegisterGameObjectListener(o2, AddToList(events), 2); + shadow.RegisterGameObjectListener(o3, AddToList(events), 3); + + shadow.InvalidateAll(); + shadow.FireObjectChangeNotification(o1.GetInstanceID()); // should be ignored + + Assert.Contains((1, HierarchyEvent.ForceInvalidate), events); + Assert.Contains((2, HierarchyEvent.ForceInvalidate), events); + Assert.Contains((3, HierarchyEvent.ForceInvalidate), events); + Assert.IsFalse(events.Contains((1, HierarchyEvent.ObjectDirty))); + } + + [Test] + public void ComponentMonitoringTest() + { + var shadow = new ShadowHierarchy(); + + var o1 = c("o1"); + var component = o1.AddComponent(); + + List<(int, HierarchyEvent)> events = new List<(int, HierarchyEvent)>(); + shadow.RegisterObjectListener(component, AddToList(events), 1); + + shadow.FireObjectChangeNotification(component.GetInstanceID()); + + Assert.Contains((1, HierarchyEvent.ObjectDirty), events); + } + + [Test] + public void ComponentReorder_TriggersStructureChange() + { + var shadow = new ShadowHierarchy(); + + var o1 = c("o1"); + var o2 = c("o2"); + + var c1 = o2.AddComponent(); + var c2 = o2.AddComponent(); + + var (iid1, iid2) = (c1.GetInstanceID(), c2.GetInstanceID()); + + o2.transform.SetParent(o1.transform); + + List<(int, HierarchyEvent)> events = new List<(int, HierarchyEvent)>(); + shadow.RegisterGameObjectListener(o1, AddToList(events), 1); + shadow.RegisterGameObjectListener(o2, AddToList(events), 2); + + shadow.EnableComponentMonitoring(o1); + + UnityEditorInternal.ComponentUtility.MoveComponentUp(c2); + var newComponents = o2.GetComponents(); + var (iid1a, iid2a) = (newComponents[0].GetInstanceID(), newComponents[1].GetInstanceID()); + + Assert.AreEqual(iid1, iid2a); + Assert.AreEqual(iid2, iid1a); + + shadow.FireObjectChangeNotification(iid1); + shadow.FireObjectChangeNotification(iid2); + + Assert.Contains((1, HierarchyEvent.ChildComponentsChanged), events); + Assert.Contains((2, HierarchyEvent.SelfComponentsChanged), events); + } + + // TODO - hierarchy pruning + // TODO - test create game object notifications + // TODO - test asset objects + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs.meta b/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs.meta new file mode 100644 index 00000000..8fc9fbbe --- /dev/null +++ b/UnitTests~/RQ-EditorTests/ShadowHierarchyTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8a9e3b2f42454cf086c8986e4ddd8e11 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef b/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef new file mode 100644 index 00000000..98223188 --- /dev/null +++ b/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef @@ -0,0 +1,20 @@ +{ + "name": "nadena.dev.ndmf.reactive-query.tests.editor", + "rootNamespace": "", + "references": [ + "nadena.dev.ndmf.reactive-query.core", + "nadena.dev.ndmf.reactive-query.tests", + "nadena.dev.ndmf" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef.meta b/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef.meta new file mode 100644 index 00000000..f8fe9ee0 --- /dev/null +++ b/UnitTests~/RQ-EditorTests/nadena.dev.ndmf.reactive-query.tests.editor.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8c5771c0a6864b6b85da6f23b1b831aa +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests.meta b/UnitTests~/RQ-StandaloneTests.meta new file mode 100644 index 00000000..afddb7a0 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f21f3d75ed5b4cba856641c4f732ed15 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs b/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs new file mode 100644 index 00000000..4913ef40 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs @@ -0,0 +1,144 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace nadena.dev.ndmf.rq.StandaloneTests +{ + public class BasicQueryTest : StandaloneTestBase + { + [Test] + [Timeout(5000)] + public async Task TrivialQuery() + { + var q = new TestQuery(_ => Task.FromResult(42)); + + Assert.IsFalse(q.TryGetValue(out var _)); + var task = q.GetValueAsync(); + + Assert.AreEqual(42, await task.Timeout()); + Assert.IsTrue(q.TryGetValue(out var result)); + Assert.AreEqual(42, result); + } + + [Test] + [Timeout(5000)] + public async Task CacheAndInvalidate() + { + int value = 1; + + var q = new TestQuery(_ => Task.FromResult(value)); + + Assert.AreEqual(1, await q.GetValueAsync().Timeout()); + value = 2; + Assert.AreEqual(1, await q.GetValueAsync().Timeout()); + q.Invalidate(); + Assert.AreEqual(2, await q.GetValueAsync().Timeout()); + } + + [Test] + [Timeout(5000)] + public async Task ChainedInvalidation() + { + int value = 1; + + var q1 = new TestQuery(_ => Task.FromResult(value)); + var q2 = new TestQuery(async ctx => await ctx.Observe(q1)); + + Assert.AreEqual(1, await q2.GetValueAsync().Timeout()); + + value = 2; + q1.Invalidate(); + + Assert.AreEqual(2, await q2.GetValueAsync().Timeout()); + } + + [Test] + [Timeout(5000)] + public async Task TaskDelay() + { + TaskCompletionSource tcs = new TaskCompletionSource(); + var q = new TestQuery(_ => tcs.Task); + var q2 = new TestQuery(async ctx => await ctx.Observe(q)); + + var t2 = q2.GetValueAsync(); + await Task.Delay(100); + Assert.IsFalse(t2.IsCompleted); + + tcs.SetResult(42); + Assert.AreEqual(42, await t2.Timeout()); + } + + [Test] + [Timeout(5000)] + public async Task CancellationAwaitsPreviousExecution() + { + TaskCompletionSource tcs = new TaskCompletionSource(); + var q = new TestQuery(_ => tcs.Task); + + var task = q.GetValueAsync(); + await Task.Delay(100); + + q.Value = _ => Task.FromResult(42); + + var task2 = q.GetValueAsync(); + await Task.Delay(100); + Assert.IsFalse(task2.IsCompleted); + + tcs.SetResult(123); + Assert.AreEqual(42, await task2.Timeout(100)); + } + + [Test] + [Timeout(5000)] + public async Task ObserveMultipleQueries() + { + var q1 = new TestQuery(_ => Task.FromResult(1)); + var q2 = new TestQuery(_ => Task.FromResult(2)); + var q3 = new TestQuery(async ctx => await ctx.Observe(q1) + await ctx.Observe(q2)); + + Assert.AreEqual(3, await q3.GetValueAsync().Timeout()); + + q2.Value = _ => Task.FromResult(30); + Assert.AreEqual(31, await q3.GetValueAsync().Timeout()); + + q1.Value = _ => Task.FromResult(10); + Assert.AreEqual(40, await q3.GetValueAsync().Timeout()); + } + + [Test] + //[Timeout(5000)] + public async Task StopObserving() + { + var counter = 1; + var q1 = new TestQuery(_ => Task.FromResult(counter++)); + + var shouldCheck = new TestQuery(_ => Task.FromResult(true)); + var q2 = new TestQuery(async ctx => + { + Console.WriteLine("L1"); + var check = await ctx.Observe(shouldCheck); + Console.WriteLine("L2 " + check); + if (check) + { + var observe = await ctx.Observe(q1); + Console.WriteLine("L3 " + observe); + return observe; + } + else + { + Console.WriteLine("L4"); + return 0; + } + }); + + Assert.AreEqual(1, await q2.GetValueAsync().Timeout()); + q1.Invalidate(); + Assert.AreEqual(2, await q2.GetValueAsync().Timeout()); + shouldCheck.Value = _ => Task.FromResult(false); + Assert.AreEqual(0, await q2.GetValueAsync().Timeout()); + q1.Invalidate(); + Assert.AreEqual(0, await q2.GetValueAsync().Timeout()); + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs.meta b/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs.meta new file mode 100644 index 00000000..d2aad53b --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/BasicQueryTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d0401f4531a24ed394830a0dc2db3c56 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs b/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs new file mode 100644 index 00000000..4098d0cf --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace nadena.dev.ndmf.rq.StandaloneTests +{ + public class ObservableInterfaceTest : StandaloneTestBase + { + class TestObserver : IObserver + { + public volatile TaskCompletionSource TaskCompletionSource = new TaskCompletionSource(); + public List Sequence = new List(); + + public void OnCompleted() + { + if (TaskCompletionSource?.Task.IsCompleted != true) TaskCompletionSource?.SetResult(null); + Sequence.Add(null); + } + + public void OnError(Exception error) + { + if (TaskCompletionSource?.Task.IsCompleted != true) TaskCompletionSource?.SetResult(null); + Sequence.Add(error); + } + + public void OnNext(T value) + { + if (TaskCompletionSource?.Task.IsCompleted != true) TaskCompletionSource?.SetResult(null); + Sequence.Add(value); + } + } + + // We don't want things to be running on the unity main thread as that'll be busy in a blocking wait... + + private class ThreadPoolSyncContext : SynchronizationContext + { + public override void Post(SendOrPostCallback d, object state) + { + ThreadPool.QueueUserWorkItem(_ => d(state)); + } + + public override void Send(SendOrPostCallback d, object state) + { + d(state); + } + } + + private SynchronizationContext _priorSyncContext, _priorOverrideSyncContext; + [OneTimeSetUp] + public void Setup() + { + SynchronizationContext threadPoolSyncContext = new ThreadPoolSyncContext(); + + _priorSyncContext = SynchronizationContext.Current; + _priorOverrideSyncContext = ReactiveQueryScheduler.SynchronizationContextOverride.Value; + + SynchronizationContext.SetSynchronizationContext(threadPoolSyncContext); + ReactiveQueryScheduler.SynchronizationContextOverride.Value = threadPoolSyncContext; + } + + [OneTimeTearDown] + public void TearDown() + { + SynchronizationContext.SetSynchronizationContext(_priorSyncContext); + ReactiveQueryScheduler.SynchronizationContextOverride.Value = _priorOverrideSyncContext; + } + + [Test] + [Timeout(2000)] + public void ObservableBasicTest() + { + var rq = new TestQuery(_ => Task.FromResult(42)); + var observer = new TestObserver(); + observer.TaskCompletionSource = new TaskCompletionSource(); + + var remover = rq.Subscribe(observer); + Task.WaitAll(new Task[] { observer.TaskCompletionSource.Task }, 100); + Assert.AreEqual(new List() { 42 }, observer.Sequence); + + observer.TaskCompletionSource = new TaskCompletionSource(); + rq.Value = _ => Task.FromResult(43); + Task.WaitAll(new Task[] { observer.TaskCompletionSource.Task }, 100); + Assert.AreEqual(new List() { 42, 43 }, observer.Sequence); + + remover.Dispose(); + + observer.TaskCompletionSource = new TaskCompletionSource(); + rq.Value = _ => Task.FromResult(44); + Task.WaitAll(new Task[] { observer.TaskCompletionSource.Task }, 100); + Assert.AreEqual(new List() { 42, 43, null }, observer.Sequence); + } + + class BarrierObserver : IObserver + { + public volatile int ObservationCount = 0; + public volatile bool Broken = false; + public Barrier Barrier = new Barrier(2); + + private int _isActive; + private int _index; + + public BarrierObserver(int index) + { + _isActive = 0; + _index = index; + } + + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + } + + public void OnNext(int value) + { + System.Console.Error.WriteLine($"Observer {_index} got value {value}"); + Interlocked.Increment(ref ObservationCount); + + var wasActive = Interlocked.Exchange(ref _isActive, 1); + if (wasActive == 1) + { + Broken = true; + Barrier.Dispose(); + } + + Barrier.SignalAndWait(); + Barrier.SignalAndWait(); + + _isActive = 0; + } + } + + [Test] + [Timeout(2000)] + public void LimitsParallelismInObserverScope() + { + Barrier barrier = new Barrier(2); + + var rq = new TestQuery(_ => Task.FromResult(42)); + + var o1 = new BarrierObserver(1); + var o2 = new BarrierObserver(2); + + IDisposable d1, d2; + + d1 = rq.Subscribe(o1); + d2 = rq.Subscribe(o2); + + Thread.Sleep(100); + + try + { + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + Assert.IsFalse(o1.Broken); + Assert.AreEqual(1, o1.ObservationCount); + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + + rq.Invalidate(); + + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + Assert.IsFalse(o1.Broken); + Assert.AreEqual(2, o1.ObservationCount); + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + + rq.Invalidate(); + + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + Assert.IsFalse(o1.Broken); + Assert.AreEqual(3, o1.ObservationCount); + Assert.IsTrue(o1.Barrier.SignalAndWait(100)); + + // o2 was blocked all this time, let's go check on it now + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + Assert.IsFalse(o2.Broken); + Assert.AreEqual(1, o2.ObservationCount); + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + Assert.IsFalse(o2.Broken); + Assert.AreEqual(2, o2.ObservationCount); + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + Assert.IsFalse(o2.Broken); + Assert.AreEqual(3, o2.ObservationCount); + Assert.IsTrue(o2.Barrier.SignalAndWait(100)); + + d1.Dispose(); + d2.Dispose(); + } + finally + { + o1.Barrier.Dispose(); + o2.Barrier.Dispose(); + } + } + + [Test] + [Timeout(2000)] + public void ErrorReportingTest() + { + var ex = new Exception("Test exception"); + var rq = new TestQuery(_ => Task.FromException(ex)); + + var observer = new TestObserver(); + observer.TaskCompletionSource = new TaskCompletionSource(); + + rq.Subscribe(observer); + + Task.WaitAll(new Task[] { observer.TaskCompletionSource.Task }, 100); + Assert.AreEqual(new List() { ex }, observer.Sequence); + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs.meta b/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs.meta new file mode 100644 index 00000000..74b9fd40 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/ObservableInterfaceTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8c1be259a5264f1a83cd448647cf9934 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs b/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs new file mode 100644 index 00000000..3a6d3872 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace nadena.dev.ndmf.rq.StandaloneTests +{ + public class StandaloneTestBase + { + private TaskFactory priorFactory = ReactiveQueryScheduler.DefaultTaskFactory; + + [OneTimeSetUp] + public void SetTaskFactory() + { + ReactiveQueryScheduler.DefaultTaskFactory = new TaskFactory(TaskScheduler.Default); + } + + [OneTimeTearDown] + public void ResetTaskFactory() + { + ReactiveQueryScheduler.DefaultTaskFactory = priorFactory; + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs.meta b/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs.meta new file mode 100644 index 00000000..df39d8ca --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/StandaloneTestBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 582fdcaf791942e894ab9ba45475ca6d +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/TestHelpers.cs b/UnitTests~/RQ-StandaloneTests/TestHelpers.cs new file mode 100644 index 00000000..34251b76 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/TestHelpers.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; + +namespace nadena.dev.ndmf.rq.StandaloneTests +{ + public static class TestHelpers + { + public static async Task Timeout(this Task task, int timeout = 1000) + { + if (await Task.WhenAny(task, Task.Delay(timeout)) == task) + { + return task.Result; + } + else + { + throw new TimeoutException("Task did not complete in time"); + } + } + + public static async Task Timeout(this Task task, int timeout = 1000) + { + if (await Task.WhenAny(task, Task.Delay(timeout)) == task) + { + await task; + } + else + { + throw new TimeoutException("Task did not complete in time"); + } + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/TestHelpers.cs.meta b/UnitTests~/RQ-StandaloneTests/TestHelpers.cs.meta new file mode 100644 index 00000000..95fceae8 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/TestHelpers.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e2236bee522f4f36953529fe2a1324a0 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/TestQuery.cs b/UnitTests~/RQ-StandaloneTests/TestQuery.cs new file mode 100644 index 00000000..4156384a --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/TestQuery.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using nadena.dev.ndmf.rq; + +namespace nadena.dev.ndmf.rq.StandaloneTests +{ + internal class TestQuery : ReactiveValue + { + private Func> _value; + + public Func> Value + { + get => _value; + set + { + _value = value; + Invalidate(); + } + } + + public TestQuery(Func> func) + { + _value = func; + } + + protected override async Task Compute(ComputeContext context) + { + return await _value(context); + } + + public override string ToString() + { + return "TestQuery"; + } + } +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/TestQuery.cs.meta b/UnitTests~/RQ-StandaloneTests/TestQuery.cs.meta new file mode 100644 index 00000000..e4e0ce38 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/TestQuery.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2bcd69687b28404d9d739a881293be91 +timeCreated: 1717367926 \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef b/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef new file mode 100644 index 00000000..6f9abc1a --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef @@ -0,0 +1,18 @@ +{ + "name": "nadena.dev.ndmf.reactive-query.tests", + "rootNamespace": "", + "references": [ + "nadena.dev.ndmf.reactive-query.core" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": true +} \ No newline at end of file diff --git a/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef.meta b/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef.meta new file mode 100644 index 00000000..2a95e765 --- /dev/null +++ b/UnitTests~/RQ-StandaloneTests/nadena.dev.ndmf.reactive-query.tests.standalone.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 41f1b2e171db4a0c9ea2fc1de678108e +timeCreated: 1717367926 \ No newline at end of file