diff --git a/RuntimeUnityEditor.Bepin5/PatchInspector/PatchInspector.cs b/RuntimeUnityEditor.Bepin5/PatchInspector/PatchInspector.cs index 4afbf50..661a050 100644 --- a/RuntimeUnityEditor.Bepin5/PatchInspector/PatchInspector.cs +++ b/RuntimeUnityEditor.Bepin5/PatchInspector/PatchInspector.cs @@ -40,6 +40,11 @@ protected override void Initialize(InitSettings initSettings) DefaultScreenPosition = ScreenPartition.LeftUpper; DisplayName = "Patch Inspector"; Title = "Harmony Patch Inspector"; + + ContextMenu.MenuContents.Add(new ContextMenuEntry((GUIContent)null, (o, info) => info != null, null)); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Manage harmony patches", (o, info) => info is MethodBase, (o, info, name) => OpenILViewer((MethodBase)info))); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Manage harmony patches (get)", (o, info) => info is PropertyInfo p && p.CanRead, (o, info, name) => OpenILViewer(((PropertyInfo)info).GetGetMethod(true)))); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Manage harmony patches (set)", (o, info) => info is PropertyInfo p && p.CanWrite, (o, info, name) => OpenILViewer(((PropertyInfo)info).GetSetMethod(true)))); } /// diff --git a/RuntimeUnityEditor.Core/Features/ContextMenu.cs b/RuntimeUnityEditor.Core/Features/ContextMenu.cs index dd588dc..a54b8a1 100644 --- a/RuntimeUnityEditor.Core/Features/ContextMenu.cs +++ b/RuntimeUnityEditor.Core/Features/ContextMenu.cs @@ -5,13 +5,10 @@ using HarmonyLib; using RuntimeUnityEditor.Core.ChangeHistory; using RuntimeUnityEditor.Core.Inspector.Entries; -using RuntimeUnityEditor.Core.ObjectTree; -using RuntimeUnityEditor.Core.ObjectView; using RuntimeUnityEditor.Core.Utils; using RuntimeUnityEditor.Core.Utils.Abstractions; using RuntimeUnityEditor.Core.Utils.ObjectDumper; using UnityEngine; -using UnityEngine.Events; using UnityEngine.UI; namespace RuntimeUnityEditor.Core @@ -47,58 +44,26 @@ public override bool Enabled /// /// Contents of the context menu. /// - public List MenuContents { get; } = new List(); - private List _currentContents; + public static List MenuContents { get; } = new List(); + private List _currentContents; /// protected override void Initialize(InitSettings initSettings) { - // TODO This mess needs a rewrite with a sane API - MenuContents.AddRange(new[] - { - new MenuEntry("! Destroyed unity Object !", obj => obj is UnityEngine.Object uobj && !uobj, null), - - new MenuEntry("Preview", o => o != null && ObjectViewWindow.Initialized && ObjectViewWindow.Instance.CanPreview(o), o => ObjectViewWindow.Instance.SetShownObject(o, _objName)), - - new MenuEntry("Show event details", o => o is UnityEventBase && ObjectViewWindow.Initialized, - o => ObjectViewWindow.Instance.SetShownObject(ReflectionUtils.GetEventDetails((UnityEventBase)o), o + " - Event details")), - - new MenuEntry("Find in object tree", o => o is GameObject || o is Component, o => ObjectTreeViewer.Instance.SelectAndShowObject((o as GameObject)?.transform ?? ((Component)o).transform)), - - new MenuEntry(), - - new MenuEntry("Send to inspector", o => o != null && Inspector.Inspector.Initialized, o => - { - if (o is Type t) - Inspector.Inspector.Instance.Push(new StaticStackEntry(t, _objName), true); - else - Inspector.Inspector.Instance.Push(new InstanceStackEntry(o, _objName), true); - }), - - new MenuEntry("Send to REPL", o => o != null && REPL.ReplWindow.Initialized, o => REPL.ReplWindow.Instance.IngestObject(o)), - - new MenuEntry(), - }); - - AddBreakpointControls(MenuContents); + MenuContents.Insert(0, ContextMenuEntry.Create("! Destroyed unity Object !", (o, info) => !o, null)); MenuContents.AddRange(new[] { - new MenuEntry("Copy to clipboard", o => o != null && Clipboard.ClipboardWindow.Initialized, o => - { - if (Clipboard.ClipboardWindow.Contents.LastOrDefault() != o) - Clipboard.ClipboardWindow.Contents.Add(o); - }), - //todo Paste from clipboard, kind of difficult + ContextMenuEntry.Separator, - new MenuEntry("Export texture...", - o => o is Texture || + new ContextMenuEntry("Export texture...", + (o, info) => o is Texture || o is Sprite || (o is Material m && m.mainTexture != null) || (o is Image i && i.mainTexture != null) || (o is RawImage ri && ri.mainTexture != null) || (o is Renderer r && (r.sharedMaterial ?? r.material) != null && (r.sharedMaterial ?? r.material).mainTexture != null), - o => + (o, info, name) => { if (o is Texture t) t.SaveTextureToFileWithDialog(); @@ -114,13 +79,13 @@ o is Sprite || (r.sharedMaterial ?? r.material).mainTexture.SaveTextureToFileWithDialog(); }), - new MenuEntry("Replace texture...", - o => o is Texture2D || + new ContextMenuEntry("Replace texture...", + (o, info) => o is Texture2D || o is Texture && _setValue != null || o is Material || o is RawImage || (o is Renderer r && (r.sharedMaterial != null || r.material != null)), - o => + (o, info, name) => { string filename = "null"; var newTex = TextureUtils.LoadTextureFromFileWithDialog(ref filename); @@ -187,20 +152,13 @@ o is RawImage || } }), - new MenuEntry("Export mesh to .obj", o => o is Renderer r && MeshExport.CanExport(r), o => MeshExport.ExportObj((Renderer)o, false, false)), - new MenuEntry("Export mesh to .obj (Baked)", o => o is Renderer r && MeshExport.CanExport(r), o => MeshExport.ExportObj((Renderer)o, true, false)), - new MenuEntry("Export mesh to .obj (World)", o => o is Renderer r && MeshExport.CanExport(r), o => MeshExport.ExportObj((Renderer)o, true, true)), + ContextMenuEntry.Create("Export mesh to .obj", (o, info) => MeshExport.CanExport(o), (o, info, name) => MeshExport.ExportObj(o, false, false)), + ContextMenuEntry.Create("Export mesh to .obj (Baked)", (o, info) => MeshExport.CanExport(o), (o, info, name) => MeshExport.ExportObj(o, true, false)), + ContextMenuEntry.Create("Export mesh to .obj (World)", (o, info) => MeshExport.CanExport(o), (o, info, name) => MeshExport.ExportObj(o, true, true)), - new MenuEntry("Dump object to file...", o => o != null, o => Dumper.DumpToTempFile(o, _objName)), + new ContextMenuEntry("Dump object to file...", (o, _) => o != null, (o, info, name) => Dumper.DumpToTempFile(o, name)), - new MenuEntry("Destroy", o => o is UnityEngine.Object uo && uo, o => Change.Action("(ContextMenu)::UnityEngine.Object.Destroy({0})", o is Transform t ? t.gameObject : (UnityEngine.Object)o, UnityEngine.Object.Destroy)), - - new MenuEntry(), - - new MenuEntry("Find references in scene", o => o != null && ObjectViewWindow.Initialized && o.GetType().IsClass, o => ObjectTreeViewer.Instance.FindReferencesInScene(o)), - - new MenuEntry("Find member in dnSpy", o => DnSpyHelper.IsAvailable && _objMemberInfo != null, o => DnSpyHelper.OpenInDnSpy(_objMemberInfo)), - new MenuEntry("Find member type in dnSpy", o => o != null && DnSpyHelper.IsAvailable, o => DnSpyHelper.OpenInDnSpy(o.GetType())) + ContextMenuEntry.Create("Destroy", (o, info) => o, (o, info, name) => Change.Action("(ContextMenu)::UnityEngine.Object.Destroy({0})", o is Transform t ? t.gameObject : o, UnityEngine.Object.Destroy)), }); _windowId = base.GetHashCode(); @@ -208,42 +166,6 @@ o is RawImage || DisplayType = FeatureDisplayType.Hidden; } - private void AddBreakpointControls(List menuContents) - { - menuContents.AddRange(AddGroup("call", (o, info) => info as MethodBase)); - menuContents.AddRange(AddGroup("getter", (o, info) => info is PropertyInfo pi ? pi.GetGetMethod(true) : null)); - menuContents.AddRange(AddGroup("setter", (o, info) => info is PropertyInfo pi ? pi.GetSetMethod(true) : null)); - menuContents.Add(new MenuEntry()); - return; - - IEnumerable AddGroup(string name, Func getMethod) - { - yield return new MenuEntry("Attach " + name + " breakpoint (this instance)", o => - { - if (o == null) return false; - var target = getMethod(o, _objMemberInfo); - return target != null && !Breakpoints.Breakpoints.IsAttached(target, o); - }, o => Breakpoints.Breakpoints.AttachBreakpoint(getMethod(o, _objMemberInfo), o)); - yield return new MenuEntry("Detach " + name + " breakpoint (this instance)", o => - { - if (o == null) return false; - var target = getMethod(o, _objMemberInfo); - return target != null && Breakpoints.Breakpoints.IsAttached(target, o); - }, o => Breakpoints.Breakpoints.DetachBreakpoint(getMethod(o, _objMemberInfo), o)); - - yield return new MenuEntry("Attach " + name + " breakpoint (all instances)", o => - { - var target = getMethod(o, _objMemberInfo); - return target != null && !Breakpoints.Breakpoints.IsAttached(target, null); - }, o => Breakpoints.Breakpoints.AttachBreakpoint(getMethod(o, _objMemberInfo), null)); - yield return new MenuEntry("Detach " + name + " breakpoint (all instances)", o => - { - var target = getMethod(o, _objMemberInfo); - return target != null && Breakpoints.Breakpoints.IsAttached(target, null); - }, o => Breakpoints.Breakpoints.DetachBreakpoint(getMethod(o, _objMemberInfo), null)); - } - } - /// /// Show the context menu at current cursor position. /// @@ -277,7 +199,7 @@ public void Show(object obj, ICacheEntry objEntry) var entryValid = objEntry.CanSetValue(); Show(obj, objEntry.MemberInfo, name, entryValid ? objEntry.SetValue : (Action)null, entryValid ? objEntry.GetValue : (Func)null); } - + /// /// Show the context menu at current cursor position. /// @@ -315,7 +237,9 @@ public void Show(object obj, MemberInfo memberInfo, string memberFullName, Actio _setValue = setObj; _getValue = getObj; - _currentContents = MenuContents.Where(x => x.IsVisible(_obj)).ToList(); + _currentContents = MenuContents.Where(x => x.IsVisible(_obj, _objMemberInfo)).ToList(); + if (_currentContents.Count > 0 && _currentContents[0].IsSeparator()) + _currentContents.RemoveAt(0); // hack to discard old state of the window and make sure it appears correctly when rapidly opened on different items _windowId++; @@ -387,75 +311,13 @@ private void DrawMenu(int id) GUILayout.BeginVertical(); { - foreach (var menuEntry in _currentContents) + for (var i = 0; i < _currentContents.Count; i++) { - if (menuEntry.Draw(_obj)) + if (_currentContents[i].Draw(_obj, _objMemberInfo, _objName)) Enabled = false; } } GUILayout.EndVertical(); } - - /// - /// A single entry in the context menu. - /// - public readonly struct MenuEntry - { - /// - /// Create a new context menu entry. - /// - /// Name of the enry. - /// Callback that checks if this item is visible for a given object. - /// Callback invoked when user clicks on this menu entry with the object as argument. - public MenuEntry(string name, Func onCheckVisible, Action onClick) : this(new GUIContent(name), onCheckVisible, onClick) { } - - /// - public MenuEntry(GUIContent name, Func onCheckVisible, Action onClick) - { - _name = name; - _onCheckVisible = onCheckVisible; - _onClick = onClick; - } - - private readonly GUIContent _name; - private readonly Func _onCheckVisible; - private readonly Action _onClick; - - /// - /// Check if this menu entry should be visible for a given object. - /// - public bool IsVisible(object obj) - { - return _onCheckVisible == null || _onCheckVisible(obj); - } - - /// - /// Draw this menu entry. Handles user clicking on the entry too. - /// - public bool Draw(object obj) - { - if (_onClick != null) - { - if (GUILayout.Button(_name)) - { - if (IMGUIUtils.IsMouseRightClick()) - return false; - - _onClick(obj); - return true; - } - } - else if (_name != null) - { - GUILayout.Label(_name); - } - else - { - GUILayout.Space(4); - } - - return false; - } - } } } diff --git a/RuntimeUnityEditor.Core/Features/ContextMenuEntry.cs b/RuntimeUnityEditor.Core/Features/ContextMenuEntry.cs new file mode 100644 index 0000000..d6d86b0 --- /dev/null +++ b/RuntimeUnityEditor.Core/Features/ContextMenuEntry.cs @@ -0,0 +1,93 @@ +using System; +using System.Reflection; +using RuntimeUnityEditor.Core.Utils; +using UnityEngine; + +namespace RuntimeUnityEditor.Core +{ + /// + /// A single entry in the context menu. + /// + public readonly struct ContextMenuEntry + { + /// + /// A list separator. + /// + public static readonly ContextMenuEntry Separator = new ContextMenuEntry(); + + /// + public static ContextMenuEntry Create(string name, Func onCheckVisible, Action onClick) => Create(new GUIContent(name), onCheckVisible, onClick); + + /// + public static ContextMenuEntry Create(GUIContent name, Func onCheckVisible, Action onClick) + { + return new ContextMenuEntry(name, + onCheckVisible != null ? (o, info) => o is T oT && onCheckVisible(oT, info) : (Func)null, + onClick != null ? (o, info, objName) => onClick((T)o, info, objName) : (Action)null); + } + + /// + /// Create a new context menu entry. + /// + /// Name of the entry. + /// Callback that checks if this item is visible for a given object. + /// Callback invoked when user clicks on this menu entry with the object as argument. + public ContextMenuEntry(string name, Func onCheckVisible, Action onClick) : this(new GUIContent(name), onCheckVisible, onClick) { } + + /// + public ContextMenuEntry(GUIContent name, Func onCheckVisible, Action onClick) + { + _name = name; + _onCheckVisible = onCheckVisible; + _onClick = onClick; + } + + private readonly GUIContent _name; + private readonly Func _onCheckVisible; + private readonly Action _onClick; + + /// + /// Determines whether the current instance represents a separator. + /// + public bool IsSeparator() + { + return _name == null && _onClick == null; + } + + /// + /// Check if this menu entry should be visible for a given object. + /// + public bool IsVisible(object obj, MemberInfo info) + { + return _onCheckVisible == null || _onCheckVisible(obj, info); + } + + /// + /// Draw this menu entry. Handles user clicking on the entry too. + /// + public bool Draw(object obj, MemberInfo info, string name) + { + if (_onClick != null) + { + if (GUILayout.Button(_name)) + { + if (IMGUIUtils.IsMouseRightClick()) + return false; + + _onClick(obj, info, name ?? _name?.text ?? ""); + return true; + } + } + else if (_name != null) + { + GUILayout.Label(_name); + } + else + { + GUILayout.Space(4); + } + + return false; + } + } +} diff --git a/RuntimeUnityEditor.Core/RuntimeUnityEditor.Core.projitems b/RuntimeUnityEditor.Core/RuntimeUnityEditor.Core.projitems index d5e69a0..84ffa42 100644 --- a/RuntimeUnityEditor.Core/RuntimeUnityEditor.Core.projitems +++ b/RuntimeUnityEditor.Core/RuntimeUnityEditor.Core.projitems @@ -12,6 +12,7 @@ + diff --git a/RuntimeUnityEditor.Core/Utils/Abstractions/DnSpyHelper.cs b/RuntimeUnityEditor.Core/Utils/Abstractions/DnSpyHelper.cs index 4b29f4d..da348cd 100644 --- a/RuntimeUnityEditor.Core/Utils/Abstractions/DnSpyHelper.cs +++ b/RuntimeUnityEditor.Core/Utils/Abstractions/DnSpyHelper.cs @@ -22,6 +22,10 @@ void IFeature.OnInitialize(InitSettings initSettings) OnPathChanged(_dnSpyPath.Value); _dnSpyArgs = initSettings.RegisterSetting("Inspector", "Optional dnSpy arguments", string.Empty, "Additional parameters that are added to the end of each call to dnSpy."); + + ContextMenu.MenuContents.Add(new ContextMenuEntry((GUIContent)null, (o, info) => IsAvailable, null)); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Find member in dnSpy", (o, info) => IsAvailable && info != null, (o, info, name) => OpenInDnSpy(info))); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Find member type in dnSpy", (o, info) => IsAvailable, (o, info, name) => OpenInDnSpy(o.GetType()))); } private static void OnPathChanged(string newPath) diff --git a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs index 1732613..dc657b7 100644 --- a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs +++ b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System; using HarmonyLib; using RuntimeUnityEditor.Core.Inspector.Entries; using RuntimeUnityEditor.Core.Utils; using RuntimeUnityEditor.Core.Utils.Abstractions; +using System.Collections.Generic; +using System.Reflection; using UnityEngine; namespace RuntimeUnityEditor.Core.Breakpoints @@ -23,6 +25,44 @@ protected override void Initialize(InitSettings initSettings) DefaultScreenPosition = ScreenPartition.CenterLower; Breakpoints.OnBreakpointHit += hit => _hits.Add(hit); + + AddToContextMenu(); + } + + private static void AddToContextMenu() + { + ContextMenu.MenuContents.Add(ContextMenuEntry.Separator); + ContextMenu.MenuContents.AddRange(AddGroup("call", (o, info) => info as MethodBase)); + ContextMenu.MenuContents.AddRange(AddGroup("getter", (o, info) => info is PropertyInfo pi ? pi.GetGetMethod(true) : null)); + ContextMenu.MenuContents.AddRange(AddGroup("setter", (o, info) => info is PropertyInfo pi ? pi.GetSetMethod(true) : null)); + return; + + IEnumerable AddGroup(string kind, Func getMethod) + { + yield return new ContextMenuEntry("Attach " + kind + " breakpoint (this instance)", (o, info) => + { + if (o == null) return false; + var target = getMethod(o, info); + return target != null && !Breakpoints.IsAttached(target, o); + }, (o, info, name) => Breakpoints.AttachBreakpoint(getMethod(o, info), o)); + yield return new ContextMenuEntry("Detach " + kind + " breakpoint (this instance)", (o, info) => + { + if (o == null) return false; + var target = getMethod(o, info); + return target != null && Breakpoints.IsAttached(target, o); + }, (o, info, name) => Breakpoints.DetachBreakpoint(getMethod(o, info), o)); + + yield return new ContextMenuEntry("Attach " + kind + " breakpoint (all instances)", (o, info) => + { + var target = getMethod(o, info); + return target != null && !Breakpoints.IsAttached(target, null); + }, (o, info, name) => Breakpoints.AttachBreakpoint(getMethod(o, info), null)); + yield return new ContextMenuEntry("Detach " + kind + " breakpoint (all instances)", (o, info) => + { + var target = getMethod(o, info); + return target != null && Breakpoints.IsAttached(target, null); + }, (o, info, name) => Breakpoints.DetachBreakpoint(getMethod(o, info), null)); + } } /// diff --git a/RuntimeUnityEditor.Core/Windows/Clipboard/ClipboardWindow.cs b/RuntimeUnityEditor.Core/Windows/Clipboard/ClipboardWindow.cs index 4ace314..7bdb459 100644 --- a/RuntimeUnityEditor.Core/Windows/Clipboard/ClipboardWindow.cs +++ b/RuntimeUnityEditor.Core/Windows/Clipboard/ClipboardWindow.cs @@ -28,6 +28,9 @@ protected override void Initialize(InitSettings initSettings) Title = "Clipboard"; MinimumSize = new Vector2(250, 100); DefaultScreenPosition = ScreenPartition.LeftUpper; + + ContextMenu.MenuContents.Add(new ContextMenuEntry("Copy to clipboard", null, (o, info, name) => { if (Contents.LastOrDefault() != (o ?? info)) Contents.Add(o ?? info); })); + //todo Paste from clipboard, kind of difficult } protected override void DrawContents() diff --git a/RuntimeUnityEditor.Core/Windows/Inspector/Inspector.cs b/RuntimeUnityEditor.Core/Windows/Inspector/Inspector.cs index 86a4c15..42e1b06 100644 --- a/RuntimeUnityEditor.Core/Windows/Inspector/Inspector.cs +++ b/RuntimeUnityEditor.Core/Windows/Inspector/Inspector.cs @@ -43,6 +43,14 @@ protected override void Initialize(InitSettings initSettings) MinimumSize = new Vector2(570, 170); Enabled = false; DefaultScreenPosition = ScreenPartition.CenterUpper; + + ContextMenu.MenuContents.Add(new ContextMenuEntry("Send to inspector", (o, _) => o != null, (o, info, name) => + { + if (o is Type t) + Instance.Push(new StaticStackEntry(t, name), true); + else + Instance.Push(new InstanceStackEntry(o, name), true); + })); } private bool _focusSearchBox; @@ -430,7 +438,7 @@ private void DrawContentScrollView(InspectorTab tab) visibleFieldsQuery = visibleFieldsQuery.Where(x => { // TODO add filtering option - if (x is IFakeCacheEntry) + if (x is IFakeCacheEntry) return true; #if IL2CPP if (IL2CPPCacheEntryHelper.IsIl2CppCacheEntry(x)) diff --git a/RuntimeUnityEditor.Core/Windows/ObjectTree/ObjectTreeViewer.cs b/RuntimeUnityEditor.Core/Windows/ObjectTree/ObjectTreeViewer.cs index 1930d41..69e5e82 100644 --- a/RuntimeUnityEditor.Core/Windows/ObjectTree/ObjectTreeViewer.cs +++ b/RuntimeUnityEditor.Core/Windows/ObjectTree/ObjectTreeViewer.cs @@ -77,6 +77,10 @@ protected override void Initialize(InitSettings initSettings) _searchComponents = initSettings.RegisterSetting(Title, "Search component names", true, "Include names of components on a GameObject when searching with the search box."); _searchProperties = initSettings.RegisterSetting(Title, "Search component properties", false, "Include values of properties of components on a GameObject when searching with the search box. Very slow and may have side effects!"); + + ContextMenu.MenuContents.Add(ContextMenuEntry.Create("Find in object tree", (o, info) => o, (o, info, name) => Instance.SelectAndShowObject(o.transform))); + ContextMenu.MenuContents.Add(ContextMenuEntry.Create("Find in object tree", (o, info) => o, (o, info, name) => Instance.SelectAndShowObject(o.transform))); + ContextMenu.MenuContents.Add(new ContextMenuEntry("Find references in scene", (o, info) => o != null && o.GetType().IsClass, (o, info, name) => Instance.FindReferencesInScene(o))); } /// diff --git a/RuntimeUnityEditor.Core/Windows/ObjectView/ObjectViewWindow.cs b/RuntimeUnityEditor.Core/Windows/ObjectView/ObjectViewWindow.cs index 65a2057..cb00e6f 100644 --- a/RuntimeUnityEditor.Core/Windows/ObjectView/ObjectViewWindow.cs +++ b/RuntimeUnityEditor.Core/Windows/ObjectView/ObjectViewWindow.cs @@ -5,6 +5,7 @@ using RuntimeUnityEditor.Core.Utils; using RuntimeUnityEditor.Core.Utils.Abstractions; using UnityEngine; +using UnityEngine.Events; namespace RuntimeUnityEditor.Core.ObjectView { @@ -102,6 +103,10 @@ protected override void Initialize(InitSettings initSettings) Title = "Object viewer - Empty"; DisplayName = "Viewer"; DefaultScreenPosition = ScreenPartition.LeftUpper; + + //ContextMenu.MenuContents.Add(ContextMenuEntry.Separator); + ContextMenu.MenuContents.Add(ContextMenuEntry.Create("Preview", (o, info) => Instance.CanPreview(o), (o, info, name) => Instance.SetShownObject(o, name))); + ContextMenu.MenuContents.Add(ContextMenuEntry.Create("Show event details", null, (o, info, name) => Instance.SetShownObject(ReflectionUtils.GetEventDetails(o), o + " - Event details"))); } } } \ No newline at end of file diff --git a/RuntimeUnityEditor.Core/Windows/REPL/REPLWindow.cs b/RuntimeUnityEditor.Core/Windows/REPL/REPLWindow.cs index 207bba4..37013f0 100644 --- a/RuntimeUnityEditor.Core/Windows/REPL/REPLWindow.cs +++ b/RuntimeUnityEditor.Core/Windows/REPL/REPLWindow.cs @@ -91,6 +91,8 @@ protected override void Initialize(InitSettings initSettings) MinimumSize = new Vector2(280, 130); Enabled = false; DefaultScreenPosition = ScreenPartition.CenterLower; + + ContextMenu.MenuContents.Add(new ContextMenuEntry("Send to REPL", (o, _) => o != null, (o, info, name) => Instance.IngestObject(o))); } ///