-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
some experiments with observable tracking
- Loading branch information
Daniil Korostelev
committed
Jun 19, 2024
1 parent
2de4b52
commit e14fa62
Showing
13 changed files
with
275 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
projects/TinkState-Unity-Editor/TinkState-Unity-Editor.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<LangVersion>9.0</LangVersion> | ||
<AssemblyName>Nadako.TinkState.Unity.Editor</AssemblyName> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<EnableDefaultItems>false</EnableDefaultItems> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="../../src/TinkState-Unity/Editor/**/*.cs"/> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Reference Include="UnityEngine"> | ||
<HintPath>../../unity-dlls/UnityEngine.dll</HintPath> | ||
</Reference> | ||
<Reference Include="UnityEditor"> | ||
<HintPath>../../unity-dlls/UnityEditor.dll</HintPath> | ||
</Reference> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="../TinkState/TinkState.csproj"/> | ||
</ItemGroup> | ||
</Project> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
6 changes: 6 additions & 0 deletions
6
src/TinkState-Unity/Editor/Nadako.TinkState.Unity.Editor.asmdef
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "Nadako.TinkState.Unity.Editor", | ||
"references": [ | ||
"Nadako.TinkState" | ||
] | ||
} |
7 changes: 7 additions & 0 deletions
7
src/TinkState-Unity/Editor/Nadako.TinkState.Unity.Editor.asmdef.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.CompilerServices; | ||
using TinkState.Internal; | ||
using UnityEditor; | ||
using UnityEngine; | ||
using UnityEngine.UIElements; | ||
|
||
namespace TinkState.Editor | ||
{ | ||
public class ObservableTrackerWindow : EditorWindow | ||
{ | ||
readonly List<ObservableTracker.TrackingData> data = new(); | ||
|
||
ListView listView; | ||
|
||
[MenuItem("Window/Observable Tracker")] | ||
public static void Open() | ||
{ | ||
var window = GetWindow<ObservableTrackerWindow>(); | ||
window.titleContent = new GUIContent("Observable Tracker"); | ||
} | ||
|
||
void OnEnable() | ||
{ | ||
ObservableTracker.EnableTracking = true; | ||
} | ||
|
||
void OnDisable() | ||
{ | ||
ObservableTracker.EnableTracking = false; | ||
} | ||
|
||
public void CreateGUI() | ||
{ | ||
const string uxmlGUID = "bc0d80c10c9ac4d5ab4a26571a0e49e3"; | ||
var treeAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(AssetDatabase.GUIDToAssetPath(uxmlGUID)); | ||
var tree = treeAsset.Instantiate(); | ||
tree.style.flexGrow = 1; | ||
rootVisualElement.Add(tree); | ||
|
||
var stackTraceView = tree.Q<Label>("stack-trace"); | ||
|
||
listView = tree.Q<ListView>("observable-list"); | ||
listView.itemsSource = data; | ||
listView.selectionType = SelectionType.Single; | ||
listView.makeItem = () => new Label(); | ||
listView.bindItem = (element, index) => | ||
{ | ||
var label = (Label)element; | ||
label.text = data[index].Type; | ||
}; | ||
listView.onSelectedIndicesChange += indices => | ||
{ | ||
foreach (var index in indices) | ||
{ | ||
var trackingData = data[index]; | ||
Debug.Log("Choosing " + index); | ||
stackTraceView.text = trackingData.Stack; | ||
return; | ||
} | ||
|
||
stackTraceView.text = ""; | ||
}; | ||
} | ||
|
||
private void Update() | ||
{ | ||
if (ObservableTracker.CheckDirty()) | ||
{ | ||
Debug.Log("Updating"); | ||
data.Clear(); | ||
ObservableTracker.IterateEntries((observer, trackingData) => | ||
{ | ||
Debug.Log("Adding: " + trackingData.Type); | ||
data.Add(trackingData); | ||
}); | ||
listView.Rebuild(); | ||
} | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/TinkState-Unity/Editor/ObservableTrackerWindow.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True"> | ||
<ui:TwoPaneSplitView orientation="Vertical"> | ||
<ui:ListView focusable="true" name="observable-list" /> | ||
<ui:Label name="stack-trace" /> | ||
</ui:TwoPaneSplitView> | ||
</ui:UXML> |
10 changes: 10 additions & 0 deletions
10
src/TinkState-Unity/Editor/ObservableTrackerWindow.uxml.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Runtime.CompilerServices; | ||
|
||
[assembly: InternalsVisibleTo("Nadako.TinkState.Unity.Editor")] | ||
|
||
namespace TinkState.Internal | ||
{ | ||
static class ObservableTracker | ||
{ | ||
public static bool EnableTracking = false; | ||
|
||
static bool isDirty; | ||
|
||
internal readonly struct TrackingData | ||
{ | ||
public readonly string Type; | ||
public readonly string Stack; | ||
|
||
public TrackingData(string type, string stack) | ||
{ | ||
Type = type; | ||
Stack = stack; | ||
} | ||
} | ||
|
||
static readonly Dictionary<WeakReference<Observer>, TrackingData> tracking = new(); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void TrackSubscription(Dispatcher dispatcher, Observer observer) | ||
{ | ||
if (EnableTracking) DoTrackSubscription(dispatcher, observer); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void UntrackSubscription(Dispatcher dispatcher, Observer observer) | ||
{ | ||
if (EnableTracking) DoUntrackSubscription(dispatcher, observer); | ||
} | ||
|
||
public static bool CheckDirty() | ||
{ | ||
var wasDirty = isDirty; | ||
isDirty = false; | ||
return wasDirty; | ||
} | ||
|
||
public static void IterateEntries(Action<Observer, TrackingData> callback) | ||
{ | ||
foreach (var (weakRef, trackingData) in tracking) | ||
{ | ||
if (weakRef.TryGetTarget(out var observer)) | ||
{ | ||
callback(observer, trackingData); | ||
} | ||
} | ||
} | ||
|
||
static void DoTrackSubscription(Dispatcher dispatcher, Observer observer) | ||
{ | ||
var weakRef = new WeakReference<Observer>(observer); | ||
tracking[weakRef] = new TrackingData( | ||
observer.GetType().ToString(), | ||
new StackTrace(2, true).ToString() | ||
); | ||
isDirty = true; | ||
} | ||
|
||
static void DoUntrackSubscription(Dispatcher dispatcher, Observer observer) | ||
{ | ||
WeakReference<Observer> weakRef = null; | ||
foreach (var entry in tracking.Keys) | ||
{ | ||
if (entry.TryGetTarget(out var target) && target == observer) | ||
{ | ||
weakRef = entry; | ||
break; | ||
} | ||
} | ||
|
||
if (weakRef != null) | ||
{ | ||
tracking.Remove(weakRef); | ||
isDirty = true; | ||
} | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.