fr.jeanf.eventsystem 0.1.125 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.attestation.p7m +0 -0
- package/.github/workflows/publish.yml +45 -6
- package/Documentation~/images/.gitkeep +0 -0
- package/Documentation~/images/debugger-channels.png +0 -0
- package/Documentation~/images/debugger-eventlog.png +0 -0
- package/Editor/EventSystemDebuggerWindow.cs +562 -0
- package/Editor/EventSystemDebuggerWindow.cs.meta +2 -0
- package/Editor/jeanf.eventsystem.editor.asmdef +18 -0
- package/Editor/jeanf.eventsystem.editor.asmdef.meta +7 -0
- package/{Samples.meta → Editor.meta} +1 -1
- package/README.md +122 -10
- package/Runtime/BaseClasses/CanonicalChannelResolver.cs +60 -0
- package/Runtime/BaseClasses/CanonicalChannelResolver.cs.meta +11 -0
- package/Runtime/Diagnostics/EventDiagnostics.cs +395 -0
- package/Runtime/Diagnostics/EventDiagnostics.cs.meta +2 -0
- package/Runtime/Diagnostics.meta +8 -0
- package/Runtime/PingSystem/PingableScriptableObject.cs +3 -3
- package/Runtime/ScriptableObjects/ActionRebindEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/DecimalBoolEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/DecimalDecimalEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/DecimalFloatEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/DecimalGameObjectEventChannelSO.cs +11 -4
- package/Runtime/ScriptableObjects/Advanced/DecimalIntEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/DecimalStringEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/InputActionIntEventChannelSO.cs +10 -4
- package/Runtime/ScriptableObjects/Advanced/IntBoolEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/IntEnumEventChannelSO.cs +10 -4
- package/Runtime/ScriptableObjects/Advanced/IntFloatEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/IntGameObjectEventChannelSO.cs +11 -4
- package/Runtime/ScriptableObjects/Advanced/IntIntEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/IntStringEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/StringBoolEventChannelSO.cs +10 -4
- package/Runtime/ScriptableObjects/Advanced/StringFloatEventChannelSO.cs +13 -6
- package/Runtime/ScriptableObjects/Advanced/StringStringtEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/Advanced/TimelineTriggerEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/BoolEventChannelSO.cs +13 -5
- package/Runtime/ScriptableObjects/BoolFloatEventChannelSO.cs +10 -4
- package/Runtime/ScriptableObjects/DecimalEventChannelSO.cs +13 -7
- package/Runtime/ScriptableObjects/FloatEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/GameObjectEventChannelSO.cs +10 -2
- package/Runtime/ScriptableObjects/GameObjectIntBoolEventChannelSO.cs +10 -7
- package/Runtime/ScriptableObjects/InputActionEventChannelSO.cs +10 -5
- package/Runtime/ScriptableObjects/IntEventChannelSO.cs +12 -5
- package/Runtime/ScriptableObjects/QuaternionEventChannelSO.cs +10 -7
- package/Runtime/ScriptableObjects/ScriptableObjectEventChannelSO.cs +19 -5
- package/Runtime/ScriptableObjects/StringEventChannelSO.cs +15 -4
- package/Runtime/ScriptableObjects/StringListEventChannelSO.cs +10 -5
- package/Runtime/ScriptableObjects/TeleportEventChannelSO.cs +12 -4
- package/Runtime/ScriptableObjects/TransformEventChannelSO.cs +12 -4
- package/Runtime/ScriptableObjects/Vector2EventChannelSO.cs +10 -7
- package/Runtime/ScriptableObjects/Vector3EventChannelSO.cs +10 -7
- package/Runtime/ScriptableObjects/VoidEventChannelSO.cs +10 -3
- package/Runtime/SenderInterfaces/Advanced/DecimalBoolEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/DecimalDecimalEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/DecimalFloatEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/DecimalGameObjectEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/DecimalIntEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/DecimalStringEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntBoolEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntEnumEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntFloatEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntGameObjectEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntIntEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/IntStringEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/StringBoolEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/StringFloatEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/Advanced/StringStringEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/BoolEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/DecimalEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/FloatEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/GameObjectEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/IEventPublisher.cs +19 -0
- package/Runtime/SenderInterfaces/IEventPublisher.cs.meta +2 -0
- package/Runtime/SenderInterfaces/IInputActionIntEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/IntEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/ScriptableObjectEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/StringEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/StringListEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/TimelineBoolEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/TransformEventSender.cs +3 -2
- package/Runtime/SenderInterfaces/VoidEventSender.cs +3 -2
- package/Samples~/PlayerChannels/GeneralPause.asset +16 -0
- package/Samples~/PlayerChannels/GeneralPause.asset.meta +8 -0
- package/package.json +12 -7
- /package/{Samples → Samples~}/Filters/DefaultFilter.asset +0 -0
- /package/{Samples → Samples~}/Filters/DefaultFilter.asset.meta +0 -0
- /package/{Samples → Samples~}/Filters.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ChangedControlSchemeChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ChangedControlSchemeChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/DropTakenObjectEventChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/DropTakenObjectEventChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/GloveState Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/GloveState Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabCount Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabCount Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabEvent_LeftHandState.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabEvent_LeftHandState.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabEvent_RightHandState.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/GrabEvent_RightHandState.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/Grab_LeftHand_SetAttachTransform.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/Grab_LeftHand_SetAttachTransform.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/Grab_RightHand_SetAttachTransform.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/Grab_RightHand_SetAttachTransform.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/NoHandIsGrabbing.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/NoHandIsGrabbing.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/SendHandCollidedWith.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab/SendHandCollidedWith.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Grab.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/HMDState Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/HMDState Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MainMenuState Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MainMenuState Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MouseLookCameraReset Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MouseLookCameraReset Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MouseLookState Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/MouseLookState Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectDroppedChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectDroppedChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectTakenChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectTakenChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectTakenInSpecificLocationChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ObjectTakenInSpecificLocationChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PokeEvent.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PokeEvent.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/HandDetectedEvent.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/HandDetectedEvent.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/HandDisapearedEvent.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/HandDisapearedEvent.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/LeftHandIsPointingEventChannel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/LeftHandIsPointingEventChannel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/RightHandIsPointingEventChannel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent/RightHandIsPointingEventChannel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PoseEvent.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemState Event Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemState Event Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemState Event VR_Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemState Event VR_Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemStateWithUsedHandChannelSO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/PrimaryItemStateWithUsedHandChannelSO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/RefreshPingableObjects 1.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/RefreshPingableObjects 1.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/RefreshPingableObjects.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/RefreshPingableObjects.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ResetChannel.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/ResetChannel.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/SceneIsLoading EventChannel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/SceneIsLoading EventChannel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Teleport Event Object Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Teleport Event Object Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Teleport Event Player Channel SO.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/Teleport Event Player Channel SO.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels/TeleportationState.asset +0 -0
- /package/{Samples → Samples~}/PlayerChannels/TeleportationState.asset.meta +0 -0
- /package/{Samples → Samples~}/PlayerChannels.meta +0 -0
package/.attestation.p7m
ADDED
|
Binary file
|
|
@@ -5,19 +5,58 @@ on:
|
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
7
|
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # Required for npm OIDC and Provenance
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
8
12
|
jobs:
|
|
9
13
|
release:
|
|
10
14
|
name: 🚀 publish
|
|
11
15
|
runs-on: ubuntu-latest
|
|
12
16
|
steps:
|
|
13
17
|
- name: 📚 checkout
|
|
14
|
-
uses: actions/checkout@
|
|
18
|
+
uses: actions/checkout@v6
|
|
19
|
+
|
|
15
20
|
- name: 🟢 node
|
|
16
|
-
uses: actions/setup-node@
|
|
21
|
+
uses: actions/setup-node@v6
|
|
17
22
|
with:
|
|
18
|
-
node-version:
|
|
23
|
+
node-version: 24
|
|
19
24
|
registry-url: https://registry.npmjs.org
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
|
|
26
|
+
# --- Pack & sign with Unity's official Package Manager CLI ---
|
|
27
|
+
# https://docs.unity3d.com/6000.3/Documentation/Manual/upm-cli.html
|
|
28
|
+
# Service account must hold the "Package Manager Package Signer" role.
|
|
29
|
+
- name: 🔏 pack & sign unity package
|
|
22
30
|
env:
|
|
23
|
-
|
|
31
|
+
UPM_SERVICE_ACCOUNT_KEY_ID: ${{ secrets.UPM_SERVICE_ACCOUNT_KEY_ID }}
|
|
32
|
+
UPM_SERVICE_ACCOUNT_KEY_SECRET: ${{ secrets.UPM_SERVICE_ACCOUNT_KEY_SECRET }}
|
|
33
|
+
UNITY_ORGANIZATION_ID: ${{ secrets.UNITY_ORG_ID }}
|
|
34
|
+
run: |
|
|
35
|
+
set -euo pipefail
|
|
36
|
+
|
|
37
|
+
# Install the official UPM CLI (adds `upm` to PATH via shell profile,
|
|
38
|
+
# which a non-interactive CI shell does NOT pick up — so resolve the
|
|
39
|
+
# binary directly below).
|
|
40
|
+
curl -fsSL https://cdn.packages.unity.com/upm-cli/install.sh | bash
|
|
41
|
+
|
|
42
|
+
UPM_BIN="$(command -v upm || true)"
|
|
43
|
+
if [ -z "${UPM_BIN}" ]; then
|
|
44
|
+
UPM_BIN="$(find "${HOME}" -type f -name upm 2>/dev/null | head -n1)"
|
|
45
|
+
fi
|
|
46
|
+
if [ -z "${UPM_BIN}" ]; then
|
|
47
|
+
echo "::error::Could not locate the 'upm' binary after install." >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
"${UPM_BIN}" --version
|
|
52
|
+
|
|
53
|
+
# Packs the package in the repo root and writes the SIGNED tarball to ./dist
|
|
54
|
+
"${UPM_BIN}" pack . --organization-id "${UNITY_ORGANIZATION_ID}" --destination ./dist
|
|
55
|
+
|
|
56
|
+
# --- Publish the SIGNED tarball (do NOT let npm repack the source) ---
|
|
57
|
+
- name: 🚀 publish
|
|
58
|
+
run: |
|
|
59
|
+
set -euo pipefail
|
|
60
|
+
TARBALL="$(ls ./dist/*.tgz | head -n1)"
|
|
61
|
+
echo "Publishing ${TARBALL}"
|
|
62
|
+
npm publish "${TARBALL}" --access public --provenance
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Reflection;
|
|
4
|
+
using System.Runtime.CompilerServices;
|
|
5
|
+
using UnityEditor;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
using Object = UnityEngine.Object;
|
|
8
|
+
|
|
9
|
+
namespace jeanf.EventSystem.EditorTools
|
|
10
|
+
{
|
|
11
|
+
public class EventSystemDebuggerWindow : EditorWindow
|
|
12
|
+
{
|
|
13
|
+
public const string PrefAutoSender = "jeanf.evtdbg.autoSender";
|
|
14
|
+
public const string PrefAutoReceiver = "jeanf.evtdbg.autoReceiver";
|
|
15
|
+
|
|
16
|
+
enum Tab { Channels, EventLog }
|
|
17
|
+
|
|
18
|
+
Tab _tab = Tab.Channels;
|
|
19
|
+
Vector2 _channelScroll;
|
|
20
|
+
Vector2 _logScroll;
|
|
21
|
+
string _channelSearch = "";
|
|
22
|
+
string _logSearch = "";
|
|
23
|
+
bool _duplicatesOnly;
|
|
24
|
+
readonly HashSet<int> _expanded = new HashSet<int>();
|
|
25
|
+
|
|
26
|
+
EventDiagnostics.RaiseRecord[] _logBuffer = new EventDiagnostics.RaiseRecord[EventDiagnostics.BufferCapacity];
|
|
27
|
+
int _logCount;
|
|
28
|
+
|
|
29
|
+
readonly Dictionary<string, List<Component>> _senderScan = new Dictionary<string, List<Component>>();
|
|
30
|
+
double _nextScan;
|
|
31
|
+
|
|
32
|
+
const BindingFlags FieldFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
|
33
|
+
|
|
34
|
+
[MenuItem("Window/jeanf/Event System Debugger")]
|
|
35
|
+
static void Open()
|
|
36
|
+
{
|
|
37
|
+
var w = GetWindow<EventSystemDebuggerWindow>();
|
|
38
|
+
w.titleContent = new GUIContent("Event Debugger");
|
|
39
|
+
w.minSize = new Vector2(540, 320);
|
|
40
|
+
w.Show();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void OnEnable()
|
|
44
|
+
{
|
|
45
|
+
EditorApplication.update += OnEditorUpdate;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void OnDisable()
|
|
49
|
+
{
|
|
50
|
+
EditorApplication.update -= OnEditorUpdate;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
double _nextRepaint;
|
|
54
|
+
|
|
55
|
+
void OnEditorUpdate()
|
|
56
|
+
{
|
|
57
|
+
if (!EditorApplication.isPlaying) return;
|
|
58
|
+
if (EditorApplication.timeSinceStartup >= _nextScan)
|
|
59
|
+
{
|
|
60
|
+
_nextScan = EditorApplication.timeSinceStartup + 1.0;
|
|
61
|
+
RebuildSenderScan();
|
|
62
|
+
}
|
|
63
|
+
if (EditorApplication.timeSinceStartup < _nextRepaint) return;
|
|
64
|
+
_nextRepaint = EditorApplication.timeSinceStartup + 0.2;
|
|
65
|
+
Repaint();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void RebuildSenderScan()
|
|
69
|
+
{
|
|
70
|
+
_senderScan.Clear();
|
|
71
|
+
var comps = Object.FindObjectsOfType<MonoBehaviour>(true);
|
|
72
|
+
foreach (var comp in comps)
|
|
73
|
+
{
|
|
74
|
+
if (comp == null) continue;
|
|
75
|
+
foreach (var itf in comp.GetType().GetInterfaces())
|
|
76
|
+
{
|
|
77
|
+
if (itf.Namespace != "jeanf.EventSystem") continue;
|
|
78
|
+
if (!itf.Name.EndsWith("EventSender", StringComparison.Ordinal)) continue;
|
|
79
|
+
foreach (var p in itf.GetProperties())
|
|
80
|
+
{
|
|
81
|
+
if (!typeof(DescriptionBaseSO).IsAssignableFrom(p.PropertyType)) continue;
|
|
82
|
+
if (!(p.GetValue(comp) is DescriptionBaseSO ch)) continue;
|
|
83
|
+
string gk = EventDiagnostics.GroupKey(ch.Guid, RuntimeHelpers.GetHashCode(ch));
|
|
84
|
+
if (!_senderScan.TryGetValue(gk, out var list))
|
|
85
|
+
{
|
|
86
|
+
list = new List<Component>();
|
|
87
|
+
_senderScan[gk] = list;
|
|
88
|
+
}
|
|
89
|
+
if (!list.Contains(comp)) list.Add(comp);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void OnGUI()
|
|
96
|
+
{
|
|
97
|
+
DrawToolbar();
|
|
98
|
+
if (_tab == Tab.Channels) DrawChannels();
|
|
99
|
+
else DrawEventLog();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void DrawToolbar()
|
|
103
|
+
{
|
|
104
|
+
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
|
|
105
|
+
{
|
|
106
|
+
if (GUILayout.Toggle(_tab == Tab.Channels, "Channels", EditorStyles.toolbarButton)) _tab = Tab.Channels;
|
|
107
|
+
if (GUILayout.Toggle(_tab == Tab.EventLog, "Event Log", EditorStyles.toolbarButton)) _tab = Tab.EventLog;
|
|
108
|
+
GUILayout.FlexibleSpace();
|
|
109
|
+
bool resolver = CanonicalChannelResolver.Resolve != null;
|
|
110
|
+
var c = GUI.color;
|
|
111
|
+
GUI.color = resolver ? new Color(0.5f, 1f, 0.5f) : new Color(1f, 0.6f, 0.4f);
|
|
112
|
+
GUILayout.Label(resolver ? "● resolver installed" : "○ no resolver", EditorStyles.miniLabel);
|
|
113
|
+
GUI.color = c;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!EditorApplication.isPlaying)
|
|
117
|
+
EditorGUILayout.HelpBox("Enter Play mode to capture live channels and events.", MessageType.Info);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
void DrawChannels()
|
|
121
|
+
{
|
|
122
|
+
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
|
|
123
|
+
{
|
|
124
|
+
_channelSearch = GUILayout.TextField(_channelSearch, EditorStyles.toolbarSearchField, GUILayout.MinWidth(120));
|
|
125
|
+
_duplicatesOnly = GUILayout.Toggle(_duplicatesOnly, "Duplicates only", EditorStyles.toolbarButton, GUILayout.Width(110));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
var groups = BuildGroups();
|
|
129
|
+
|
|
130
|
+
GUILayout.Label($"Live channels: {groups.Count}", EditorStyles.miniBoldLabel);
|
|
131
|
+
|
|
132
|
+
_channelScroll = EditorGUILayout.BeginScrollView(_channelScroll);
|
|
133
|
+
foreach (var g in groups)
|
|
134
|
+
{
|
|
135
|
+
if (!string.IsNullOrEmpty(_channelSearch) &&
|
|
136
|
+
g.displayName.IndexOf(_channelSearch, StringComparison.OrdinalIgnoreCase) < 0)
|
|
137
|
+
continue;
|
|
138
|
+
if (_duplicatesOnly && g.instances.Count <= 1) continue;
|
|
139
|
+
DrawGroup(g);
|
|
140
|
+
}
|
|
141
|
+
EditorGUILayout.EndScrollView();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
class Group
|
|
145
|
+
{
|
|
146
|
+
public string groupKey;
|
|
147
|
+
public string displayName;
|
|
148
|
+
public string typeName;
|
|
149
|
+
public List<(EventDiagnostics.ChannelRecord rec, ScriptableObject so)> instances =
|
|
150
|
+
new List<(EventDiagnostics.ChannelRecord, ScriptableObject)>();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
List<Group> BuildGroups()
|
|
154
|
+
{
|
|
155
|
+
var byKey = new Dictionary<string, Group>();
|
|
156
|
+
var records = EventDiagnostics.SnapshotChannels();
|
|
157
|
+
foreach (var rec in records)
|
|
158
|
+
{
|
|
159
|
+
ScriptableObject so = null;
|
|
160
|
+
rec.instance?.TryGetTarget(out so);
|
|
161
|
+
if (so == null)
|
|
162
|
+
{
|
|
163
|
+
EventDiagnostics.PruneChannel(rec.key);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
string gk = EventDiagnostics.GroupKey(rec.guid, rec.key);
|
|
168
|
+
if (!byKey.TryGetValue(gk, out var g))
|
|
169
|
+
{
|
|
170
|
+
g = new Group { groupKey = gk, displayName = so.name, typeName = rec.typeName };
|
|
171
|
+
byKey[gk] = g;
|
|
172
|
+
}
|
|
173
|
+
g.instances.Add((rec, so));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
var list = new List<Group>(byKey.Values);
|
|
177
|
+
list.Sort((a, b) => string.Compare(a.displayName, b.displayName, StringComparison.OrdinalIgnoreCase));
|
|
178
|
+
return list;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
void DrawGroup(Group g)
|
|
182
|
+
{
|
|
183
|
+
bool dup = g.instances.Count > 1;
|
|
184
|
+
int subTotal = 0;
|
|
185
|
+
foreach (var inst in g.instances) subTotal += CountSubscribers(inst.so);
|
|
186
|
+
|
|
187
|
+
int gkHash = g.groupKey.GetHashCode();
|
|
188
|
+
bool open = _expanded.Contains(gkHash);
|
|
189
|
+
|
|
190
|
+
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox))
|
|
191
|
+
{
|
|
192
|
+
bool nowOpen = EditorGUILayout.Foldout(open, GUIContent.none, true, EditorStyles.foldout);
|
|
193
|
+
if (nowOpen != open)
|
|
194
|
+
{
|
|
195
|
+
if (nowOpen) _expanded.Add(gkHash); else _expanded.Remove(gkHash);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
GUILayout.Label(g.displayName, EditorStyles.boldLabel, GUILayout.Width(200));
|
|
199
|
+
GUILayout.Label(g.typeName, EditorStyles.miniLabel, GUILayout.Width(150));
|
|
200
|
+
GUILayout.Label($"inst {g.instances.Count}", EditorStyles.miniLabel, GUILayout.Width(54));
|
|
201
|
+
GUILayout.Label($"subs {subTotal}", EditorStyles.miniLabel, GUILayout.Width(54));
|
|
202
|
+
|
|
203
|
+
GUILayout.FlexibleSpace();
|
|
204
|
+
if (dup)
|
|
205
|
+
{
|
|
206
|
+
var c = GUI.color; GUI.color = new Color(1f, 0.55f, 0.4f);
|
|
207
|
+
GUILayout.Label("▲ DUPLICATE", EditorStyles.miniBoldLabel, GUILayout.Width(90));
|
|
208
|
+
GUI.color = c;
|
|
209
|
+
}
|
|
210
|
+
else if (subTotal == 0)
|
|
211
|
+
{
|
|
212
|
+
GUILayout.Label("◌ no listeners", EditorStyles.miniLabel, GUILayout.Width(90));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (GUILayout.Button("Select GOs", EditorStyles.miniButton, GUILayout.Width(80)))
|
|
216
|
+
SelectAllListeners(g);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (open) DrawGroupDetails(g);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
void DrawGroupDetails(Group g)
|
|
223
|
+
{
|
|
224
|
+
EditorGUI.indentLevel++;
|
|
225
|
+
ScriptableObject canonical = null;
|
|
226
|
+
try { canonical = CanonicalChannelResolver.GetCanonical((ScriptableObject)g.instances[0].so); }
|
|
227
|
+
catch { }
|
|
228
|
+
|
|
229
|
+
foreach (var inst in g.instances)
|
|
230
|
+
{
|
|
231
|
+
var so = inst.so;
|
|
232
|
+
var rec = inst.rec;
|
|
233
|
+
bool isCanonical = canonical != null && ReferenceEquals(canonical, so);
|
|
234
|
+
|
|
235
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
236
|
+
{
|
|
237
|
+
GUILayout.Space(16);
|
|
238
|
+
GUILayout.Label(isCanonical ? "[CANONICAL]" : "[duplicate]",
|
|
239
|
+
isCanonical ? EditorStyles.miniBoldLabel : EditorStyles.miniLabel, GUILayout.Width(86));
|
|
240
|
+
GUILayout.Label($"id {so.GetInstanceID()}", EditorStyles.miniLabel, GUILayout.Width(96));
|
|
241
|
+
GUILayout.Label($"thread {rec.firstSeenThreadId}" + (rec.seenOffMainThread ? " ⚠" : ""),
|
|
242
|
+
EditorStyles.miniLabel, GUILayout.Width(90));
|
|
243
|
+
if (GUILayout.Button("Ping asset", EditorStyles.miniButton, GUILayout.Width(74)))
|
|
244
|
+
EditorGUIUtility.PingObject(so);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
var subs = GetSubscribers(so);
|
|
248
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
249
|
+
{
|
|
250
|
+
GUILayout.Space(22);
|
|
251
|
+
RoleBadge("RECV", RecvColor);
|
|
252
|
+
GUILayout.Label($"receivers ({subs.Count})", EditorStyles.miniBoldLabel);
|
|
253
|
+
}
|
|
254
|
+
foreach (var s in subs)
|
|
255
|
+
{
|
|
256
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
257
|
+
{
|
|
258
|
+
GUILayout.Space(40);
|
|
259
|
+
GUILayout.Label("↳ " + s.label, EditorStyles.miniLabel, GUILayout.Width(320));
|
|
260
|
+
GUILayout.FlexibleSpace();
|
|
261
|
+
using (new EditorGUI.DisabledScope(s.target == null))
|
|
262
|
+
{
|
|
263
|
+
if (GUILayout.Button("Select", EditorStyles.miniButton, GUILayout.Width(60)))
|
|
264
|
+
{
|
|
265
|
+
Selection.activeObject = s.SelectionTarget;
|
|
266
|
+
EditorGUIUtility.PingObject(s.SelectionTarget);
|
|
267
|
+
}
|
|
268
|
+
if (GUILayout.Button("Ping", EditorStyles.miniButton, GUILayout.Width(50)))
|
|
269
|
+
EditorGUIUtility.PingObject(s.SelectionTarget);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
var publishers = GetPublishers(g);
|
|
276
|
+
var stackSenders = EventDiagnostics.SnapshotStackSenders(g.groupKey);
|
|
277
|
+
int senderTotal = publishers.Count + stackSenders.Length;
|
|
278
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
279
|
+
{
|
|
280
|
+
GUILayout.Space(16);
|
|
281
|
+
RoleBadge("SEND", SendColor);
|
|
282
|
+
GUILayout.Label($"senders ({senderTotal})", EditorStyles.miniBoldLabel);
|
|
283
|
+
if (senderTotal == 0)
|
|
284
|
+
GUILayout.Label("— none yet (enable “Track sender” to auto-detect by class, or this.Publish(…) for exact GameObject)", EditorStyles.miniLabel);
|
|
285
|
+
}
|
|
286
|
+
foreach (var ss in stackSenders)
|
|
287
|
+
{
|
|
288
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
289
|
+
{
|
|
290
|
+
GUILayout.Space(40);
|
|
291
|
+
string m = string.IsNullOrEmpty(ss.method) ? "" : "." + ss.method + "()";
|
|
292
|
+
var prev = GUI.color;
|
|
293
|
+
GUI.color = new Color(prev.r, prev.g, prev.b, 0.75f);
|
|
294
|
+
GUILayout.Label($"⇧ {ss.typeName}{m} ×{ss.count} (by stack, no GameObject)", EditorStyles.miniLabel, GUILayout.Width(420));
|
|
295
|
+
GUI.color = prev;
|
|
296
|
+
GUILayout.FlexibleSpace();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
foreach (var p in publishers)
|
|
300
|
+
{
|
|
301
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
302
|
+
{
|
|
303
|
+
GUILayout.Space(40);
|
|
304
|
+
string name = p.comp != null ? p.comp.GetType().Name + " ▸ \"" + p.comp.gameObject.name + "\"" : p.label;
|
|
305
|
+
GUILayout.Label("⇧ " + name, EditorStyles.miniLabel, GUILayout.Width(320));
|
|
306
|
+
GUILayout.FlexibleSpace();
|
|
307
|
+
using (new EditorGUI.DisabledScope(p.comp == null))
|
|
308
|
+
{
|
|
309
|
+
if (GUILayout.Button("Select", EditorStyles.miniButton, GUILayout.Width(60)))
|
|
310
|
+
{
|
|
311
|
+
Selection.activeObject = p.comp != null ? p.comp.gameObject : null;
|
|
312
|
+
if (p.comp != null) EditorGUIUtility.PingObject(p.comp.gameObject);
|
|
313
|
+
}
|
|
314
|
+
if (GUILayout.Button("Ping", EditorStyles.miniButton, GUILayout.Width(50)))
|
|
315
|
+
if (p.comp != null) EditorGUIUtility.PingObject(p.comp.gameObject);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
EditorGUI.indentLevel--;
|
|
321
|
+
GUILayout.Space(4);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
static readonly Color RecvColor = new Color(0.45f, 0.8f, 1f);
|
|
325
|
+
static readonly Color SendColor = new Color(1f, 0.72f, 0.4f);
|
|
326
|
+
|
|
327
|
+
static void RoleBadge(string text, Color color)
|
|
328
|
+
{
|
|
329
|
+
var prev = GUI.color;
|
|
330
|
+
GUI.color = color;
|
|
331
|
+
GUILayout.Label(text, EditorStyles.miniBoldLabel, GUILayout.Width(38));
|
|
332
|
+
GUI.color = prev;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
struct PubInfo
|
|
336
|
+
{
|
|
337
|
+
public string label;
|
|
338
|
+
public Component comp;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
List<PubInfo> GetPublishers(Group g)
|
|
342
|
+
{
|
|
343
|
+
var list = new List<PubInfo>();
|
|
344
|
+
var seen = new HashSet<int>();
|
|
345
|
+
|
|
346
|
+
foreach (var pr in EventDiagnostics.SnapshotPublishers(g.groupKey))
|
|
347
|
+
{
|
|
348
|
+
Component c = null;
|
|
349
|
+
pr.component?.TryGetTarget(out c);
|
|
350
|
+
if (c == null) continue;
|
|
351
|
+
if (!seen.Add(c.GetInstanceID())) continue;
|
|
352
|
+
list.Add(new PubInfo { comp = c, label = pr.typeName });
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (_senderScan.TryGetValue(g.groupKey, out var scanned))
|
|
356
|
+
{
|
|
357
|
+
foreach (var c in scanned)
|
|
358
|
+
{
|
|
359
|
+
if (c == null) continue;
|
|
360
|
+
if (!seen.Add(c.GetInstanceID())) continue;
|
|
361
|
+
list.Add(new PubInfo { comp = c, label = c.GetType().Name });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return list;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
struct SubInfo
|
|
368
|
+
{
|
|
369
|
+
public string label;
|
|
370
|
+
public Object target;
|
|
371
|
+
public GameObject go;
|
|
372
|
+
public Object SelectionTarget => go != null ? go : target;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
int CountSubscribers(ScriptableObject so)
|
|
376
|
+
{
|
|
377
|
+
int n = 0;
|
|
378
|
+
ForEachSubscriber(so, (_, __) => n++);
|
|
379
|
+
return n;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
List<SubInfo> GetSubscribers(ScriptableObject so)
|
|
383
|
+
{
|
|
384
|
+
var list = new List<SubInfo>();
|
|
385
|
+
ForEachSubscriber(so, (target, method) =>
|
|
386
|
+
{
|
|
387
|
+
var go = (target as Component)?.gameObject;
|
|
388
|
+
string typeName = method?.DeclaringType?.Name ?? target?.GetType().Name ?? "static";
|
|
389
|
+
string goName = go != null ? " ▸ \"" + go.name + "\"" : "";
|
|
390
|
+
list.Add(new SubInfo
|
|
391
|
+
{
|
|
392
|
+
label = $"{typeName}.{method?.Name}(){goName}",
|
|
393
|
+
target = target as Object,
|
|
394
|
+
go = go,
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
return list;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
static void ForEachSubscriber(ScriptableObject so, Action<object, MethodInfo> action)
|
|
401
|
+
{
|
|
402
|
+
if (so == null) return;
|
|
403
|
+
var t = so.GetType();
|
|
404
|
+
while (t != null && t != typeof(ScriptableObject))
|
|
405
|
+
{
|
|
406
|
+
foreach (var f in t.GetFields(FieldFlags))
|
|
407
|
+
{
|
|
408
|
+
if (!typeof(Delegate).IsAssignableFrom(f.FieldType)) continue;
|
|
409
|
+
if (!(f.GetValue(so) is Delegate del)) continue;
|
|
410
|
+
foreach (var d in del.GetInvocationList())
|
|
411
|
+
action(d.Target, d.Method);
|
|
412
|
+
}
|
|
413
|
+
t = t.BaseType;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
void SelectAllListeners(Group g)
|
|
418
|
+
{
|
|
419
|
+
var objs = new List<Object>();
|
|
420
|
+
foreach (var inst in g.instances)
|
|
421
|
+
foreach (var s in GetSubscribers(inst.so))
|
|
422
|
+
if (s.SelectionTarget != null) objs.Add(s.SelectionTarget);
|
|
423
|
+
if (objs.Count > 0)
|
|
424
|
+
{
|
|
425
|
+
Selection.objects = objs.ToArray();
|
|
426
|
+
EditorGUIUtility.PingObject(objs[0]);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
void DrawEventLog()
|
|
431
|
+
{
|
|
432
|
+
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
|
|
433
|
+
{
|
|
434
|
+
GUILayout.Label("On play:", EditorStyles.miniLabel, GUILayout.Width(54));
|
|
435
|
+
DrawPrefToggle(PrefAutoSender, "Track sender", v =>
|
|
436
|
+
{
|
|
437
|
+
EventDiagnostics.CaptureSenderStack = v;
|
|
438
|
+
EventDiagnostics.TrackingEnabled = v || EventDiagnostics.CaptureReceivers;
|
|
439
|
+
});
|
|
440
|
+
DrawPrefToggle(PrefAutoReceiver, "Track receiver", v =>
|
|
441
|
+
{
|
|
442
|
+
EventDiagnostics.CaptureReceivers = v;
|
|
443
|
+
EventDiagnostics.TrackingEnabled = v || EventDiagnostics.CaptureSenderStack;
|
|
444
|
+
});
|
|
445
|
+
if (GUILayout.Button("Clear", EditorStyles.toolbarButton, GUILayout.Width(50)))
|
|
446
|
+
EventDiagnostics.Clear();
|
|
447
|
+
GUILayout.FlexibleSpace();
|
|
448
|
+
_logSearch = GUILayout.TextField(_logSearch, EditorStyles.toolbarSearchField, GUILayout.MinWidth(120));
|
|
449
|
+
GUILayout.Label($"{EventDiagnostics.RaiseCount}/{EventDiagnostics.BufferCapacity}", EditorStyles.miniLabel);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
_logCount = EventDiagnostics.SnapshotRaises(_logBuffer);
|
|
453
|
+
|
|
454
|
+
DrawCounts();
|
|
455
|
+
|
|
456
|
+
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox))
|
|
457
|
+
{
|
|
458
|
+
GUILayout.Label("Seq", EditorStyles.miniBoldLabel, GUILayout.Width(54));
|
|
459
|
+
GUILayout.Label("Time", EditorStyles.miniBoldLabel, GUILayout.Width(64));
|
|
460
|
+
GUILayout.Label("Channel", EditorStyles.miniBoldLabel, GUILayout.Width(180));
|
|
461
|
+
GUILayout.Label("Payload", EditorStyles.miniBoldLabel, GUILayout.Width(110));
|
|
462
|
+
GUILayout.Label("Sender", EditorStyles.miniBoldLabel, GUILayout.Width(180));
|
|
463
|
+
GUILayout.Label("Receiver(s)", EditorStyles.miniBoldLabel);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
_logScroll = EditorGUILayout.BeginScrollView(_logScroll);
|
|
467
|
+
for (int i = _logCount - 1; i >= 0; i--)
|
|
468
|
+
{
|
|
469
|
+
var r = _logBuffer[i];
|
|
470
|
+
if (!string.IsNullOrEmpty(_logSearch) &&
|
|
471
|
+
(r.typeName?.IndexOf(_logSearch, StringComparison.OrdinalIgnoreCase) ?? -1) < 0 &&
|
|
472
|
+
(r.payload?.IndexOf(_logSearch, StringComparison.OrdinalIgnoreCase) ?? -1) < 0)
|
|
473
|
+
continue;
|
|
474
|
+
|
|
475
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
476
|
+
{
|
|
477
|
+
GUILayout.Label("#" + r.seq, EditorStyles.miniLabel, GUILayout.Width(54));
|
|
478
|
+
GUILayout.Label(r.time.ToString("0.000"), EditorStyles.miniLabel, GUILayout.Width(64));
|
|
479
|
+
GUILayout.Label(r.typeName, EditorStyles.miniLabel, GUILayout.Width(180));
|
|
480
|
+
GUILayout.Label(r.payload, EditorStyles.miniLabel, GUILayout.Width(110));
|
|
481
|
+
string sender = r.senderObject != null
|
|
482
|
+
? r.senderType
|
|
483
|
+
: r.senderType != null ? r.senderType + "." + r.senderMethod + "()" : "—";
|
|
484
|
+
if (r.offMainThread) sender = "⚠ t" + r.threadId + " " + sender;
|
|
485
|
+
GUILayout.Label(sender, EditorStyles.miniLabel, GUILayout.Width(146));
|
|
486
|
+
using (new EditorGUI.DisabledScope(r.senderObject == null))
|
|
487
|
+
{
|
|
488
|
+
if (GUILayout.Button("Sel", EditorStyles.miniButton, GUILayout.Width(32)) && r.senderObject != null)
|
|
489
|
+
{
|
|
490
|
+
Selection.activeObject = r.senderObject;
|
|
491
|
+
EditorGUIUtility.PingObject(r.senderObject);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
GUILayout.Label(string.IsNullOrEmpty(r.receivers) ? "—" : r.receivers, EditorStyles.miniLabel);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
EditorGUILayout.EndScrollView();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
static void DrawPrefToggle(string key, string label, Action<bool> applyLive)
|
|
501
|
+
{
|
|
502
|
+
bool cur = EditorPrefs.GetBool(key, false);
|
|
503
|
+
bool next = GUILayout.Toggle(cur, label, EditorStyles.toolbarButton, GUILayout.Width(100));
|
|
504
|
+
if (next != cur)
|
|
505
|
+
{
|
|
506
|
+
EditorPrefs.SetBool(key, next);
|
|
507
|
+
if (EditorApplication.isPlaying) applyLive?.Invoke(next);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
void DrawCounts()
|
|
512
|
+
{
|
|
513
|
+
if (_logCount == 0) return;
|
|
514
|
+
var counts = new Dictionary<string, int>();
|
|
515
|
+
int max = 1;
|
|
516
|
+
for (int i = 0; i < _logCount; i++)
|
|
517
|
+
{
|
|
518
|
+
var name = _logBuffer[i].typeName ?? "?";
|
|
519
|
+
counts.TryGetValue(name, out int n);
|
|
520
|
+
n++;
|
|
521
|
+
counts[name] = n;
|
|
522
|
+
if (n > max) max = n;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
|
526
|
+
{
|
|
527
|
+
foreach (var kv in counts)
|
|
528
|
+
{
|
|
529
|
+
using (new EditorGUILayout.HorizontalScope())
|
|
530
|
+
{
|
|
531
|
+
GUILayout.Label(kv.Key, EditorStyles.miniLabel, GUILayout.Width(180));
|
|
532
|
+
var rect = GUILayoutUtility.GetRect(120, 10);
|
|
533
|
+
EditorGUI.DrawRect(new Rect(rect.x, rect.y + 1, 120f * kv.Value / max, 8),
|
|
534
|
+
new Color(0.4f, 0.7f, 1f));
|
|
535
|
+
GUILayout.Label(kv.Value.ToString(), EditorStyles.miniLabel, GUILayout.Width(50));
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
[InitializeOnLoad]
|
|
543
|
+
static class EventDiagnosticsAutoStart
|
|
544
|
+
{
|
|
545
|
+
static EventDiagnosticsAutoStart()
|
|
546
|
+
{
|
|
547
|
+
EditorApplication.playModeStateChanged += OnPlayModeChanged;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
static void OnPlayModeChanged(PlayModeStateChange state)
|
|
551
|
+
{
|
|
552
|
+
if (state != PlayModeStateChange.EnteredPlayMode) return;
|
|
553
|
+
|
|
554
|
+
bool sender = EditorPrefs.GetBool(EventSystemDebuggerWindow.PrefAutoSender, false);
|
|
555
|
+
bool receiver = EditorPrefs.GetBool(EventSystemDebuggerWindow.PrefAutoReceiver, false);
|
|
556
|
+
|
|
557
|
+
EventDiagnostics.CaptureSenderStack = sender;
|
|
558
|
+
EventDiagnostics.CaptureReceivers = receiver;
|
|
559
|
+
EventDiagnostics.TrackingEnabled = sender || receiver;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jeanf.eventsystem.editor",
|
|
3
|
+
"rootNamespace": "",
|
|
4
|
+
"references": [
|
|
5
|
+
"jeanf.eventsystem"
|
|
6
|
+
],
|
|
7
|
+
"includePlatforms": [
|
|
8
|
+
"Editor"
|
|
9
|
+
],
|
|
10
|
+
"excludePlatforms": [],
|
|
11
|
+
"allowUnsafeCode": false,
|
|
12
|
+
"overrideReferences": false,
|
|
13
|
+
"precompiledReferences": [],
|
|
14
|
+
"autoReferenced": true,
|
|
15
|
+
"defineConstraints": [],
|
|
16
|
+
"versionDefines": [],
|
|
17
|
+
"noEngineReferences": false
|
|
18
|
+
}
|