Compare commits

...

9 Commits
4.7.7 ... 4.7.9

Author SHA1 Message Date
7be7daf4d7 Bump version 2022-04-24 19:24:43 +10:00
8f54415ae0 Remove small logic error with SymbolLexer 2022-04-24 19:23:05 +10:00
aef4e11c01 C# Console: Implement Home and End keys 2022-04-24 19:13:43 +10:00
af7e32ec49 Add a null check 2022-04-24 18:16:13 +10:00
6f44a3376b Bump UniverseLib 2022-04-24 05:58:36 +10:00
3a6b573ac3 Bump version 2022-04-24 05:57:29 +10:00
cbe17927fb Ensure valid panel size after loading save data 2022-04-24 05:57:22 +10:00
15f3f37948 Clean up all objects in editor 2022-04-24 05:56:47 +10:00
de6760e427 Add more convenient editor config serialization 2022-04-24 05:56:36 +10:00
15 changed files with 221 additions and 115 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "com.sinai-dev.unityexplorer", "name": "com.sinai-dev.unityexplorer",
"version": "4.7.7", "version": "4.7.9",
"displayName": "UnityExplorer", "displayName": "UnityExplorer",
"description": "An in-game UI for exploring, debugging and modifying Unity games.", "description": "An in-game UI for exploring, debugging and modifying Unity games.",
"unity": "2017.1", "unity": "2017.1",

View File

@ -23,28 +23,33 @@ namespace UnityExplorer.CSConsole
{ {
public static class ConsoleController public static class ConsoleController
{ {
public static ScriptEvaluator Evaluator; public static ScriptEvaluator Evaluator { get; private set; }
public static LexerBuilder Lexer; public static LexerBuilder Lexer { get; private set; }
public static CSAutoCompleter Completer; public static CSAutoCompleter Completer { get; private set; }
private static HashSet<string> usingDirectives;
private static StringBuilder evaluatorOutput;
private static StringWriter evaluatorStringWriter;
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
public static InputFieldRef Input => Panel.Input;
public static bool SRENotSupported { get; private set; }
public static int LastCaretPosition { get; private set; } public static int LastCaretPosition { get; private set; }
internal static float defaultInputFieldAlpha; public static float DefaultInputFieldAlpha { get; set; }
// Todo save as config?
public static bool EnableCtrlRShortcut { get; private set; } = true; public static bool EnableCtrlRShortcut { get; private set; } = true;
public static bool EnableAutoIndent { get; private set; } = true; public static bool EnableAutoIndent { get; private set; } = true;
public static bool EnableSuggestions { get; private set; } = true; public static bool EnableSuggestions { get; private set; } = true;
internal static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts"); public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
public static InputFieldRef Input => Panel.Input;
internal static readonly string[] DefaultUsing = new string[] public static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
static HashSet<string> usingDirectives;
static StringBuilder evaluatorOutput;
static StringWriter evaluatorStringWriter;
static float timeOfLastCtrlR;
static bool settingCaretCoroutine;
static string previousInput;
static int previousContentLength = 0;
static readonly string[] DefaultUsing = new string[]
{ {
"System", "System",
"System.Linq", "System.Linq",
@ -59,9 +64,10 @@ namespace UnityExplorer.CSConsole
#endif #endif
}; };
const int CSCONSOLE_LINEHEIGHT = 18;
public static void Init() public static void Init()
{ {
// Make sure console is supported on this platform
try try
{ {
ResetConsole(false); ResetConsole(false);
@ -111,31 +117,10 @@ namespace UnityExplorer.CSConsole
} }
} }
#region UI Listeners and options
// TODO save
private static void OnToggleAutoIndent(bool value)
{
EnableAutoIndent = value;
}
private static void OnToggleCtrlRShortcut(bool value)
{
EnableCtrlRShortcut = value;
}
private static void OnToggleSuggestions(bool value)
{
EnableSuggestions = value;
}
#endregion
#region Evaluating #region Evaluating
private static void GenerateTextWriter() static void GenerateTextWriter()
{ {
evaluatorOutput = new StringBuilder(); evaluatorOutput = new StringBuilder();
evaluatorStringWriter = new StringWriter(evaluatorOutput); evaluatorStringWriter = new StringWriter(evaluatorOutput);
@ -247,16 +232,45 @@ namespace UnityExplorer.CSConsole
#endregion #endregion
// Updating and event listeners #region Update loop and event listeners
private static bool settingCaretCoroutine; public static void Update()
{
if (SRENotSupported)
return;
private static void OnInputScrolled() => HighlightVisibleInput(); if (InputManager.GetKeyDown(KeyCode.Home))
JumpToStartOrEndOfLine(true);
else if (InputManager.GetKeyDown(KeyCode.End))
JumpToStartOrEndOfLine(false);
private static string previousInput; UpdateCaret(out bool caretMoved);
// Invoked at most once per frame if (!settingCaretCoroutine && EnableSuggestions)
private static void OnInputChanged(string value) {
if (AutoCompleteModal.CheckEscape(Completer))
{
OnAutocompleteEscaped();
return;
}
if (caretMoved)
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
}
if (EnableCtrlRShortcut
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
&& InputManager.GetKeyDown(KeyCode.R)
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
{
timeOfLastCtrlR = Time.realtimeSinceStartup;
Evaluate(Panel.Input.Text);
}
}
static void OnInputScrolled() => HighlightVisibleInput(out _);
static void OnInputChanged(string value)
{ {
if (SRENotSupported) if (SRENotSupported)
return; return;
@ -283,7 +297,7 @@ namespace UnityExplorer.CSConsole
DoAutoIndent(); DoAutoIndent();
} }
bool inStringOrComment = HighlightVisibleInput(); HighlightVisibleInput(out bool inStringOrComment);
if (!settingCaretCoroutine) if (!settingCaretCoroutine)
{ {
@ -299,40 +313,27 @@ namespace UnityExplorer.CSConsole
UpdateCaret(out _); UpdateCaret(out _);
} }
private static float timeOfLastCtrlR; static void OnToggleAutoIndent(bool value)
public static void Update()
{ {
if (SRENotSupported) EnableAutoIndent = value;
return;
UpdateCaret(out bool caretMoved);
if (!settingCaretCoroutine && EnableSuggestions)
{
if (AutoCompleteModal.CheckEscape(Completer))
{
OnAutocompleteEscaped();
return;
}
if (caretMoved)
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
}
if (EnableCtrlRShortcut
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
&& InputManager.GetKeyDown(KeyCode.R)
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
{
timeOfLastCtrlR = Time.realtimeSinceStartup;
Evaluate(Panel.Input.Text);
}
} }
private const int CSCONSOLE_LINEHEIGHT = 18; static void OnToggleCtrlRShortcut(bool value)
{
EnableCtrlRShortcut = value;
}
private static void UpdateCaret(out bool caretMoved) static void OnToggleSuggestions(bool value)
{
EnableSuggestions = value;
}
#endregion
#region Caret position
static void UpdateCaret(out bool caretMoved)
{ {
int prevCaret = LastCaretPosition; int prevCaret = LastCaretPosition;
caretMoved = false; caretMoved = false;
@ -377,14 +378,18 @@ namespace UnityExplorer.CSConsole
} }
} }
private static void SetCaretPosition(int caretPosition) public static void SetCaretPosition(int caretPosition)
{ {
Input.Component.caretPosition = caretPosition;
// Fix to make sure we always really set the caret position.
// Yields a frame and fixes text-selection issues.
settingCaretCoroutine = true; settingCaretCoroutine = true;
Input.Component.readOnly = true; Input.Component.readOnly = true;
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition)); RuntimeHelper.StartCoroutine(DoSetCaretCoroutine(caretPosition));
} }
private static IEnumerator SetCaretCoroutine(int caretPosition) static IEnumerator DoSetCaretCoroutine(int caretPosition)
{ {
Color color = Input.Component.selectionColor; Color color = Input.Component.selectionColor;
color.a = 0f; color.a = 0f;
@ -399,25 +404,71 @@ namespace UnityExplorer.CSConsole
Input.Component.selectionFocusPosition = caretPosition; Input.Component.selectionFocusPosition = caretPosition;
LastCaretPosition = Input.Component.caretPosition; LastCaretPosition = Input.Component.caretPosition;
color.a = defaultInputFieldAlpha; color.a = DefaultInputFieldAlpha;
Input.Component.selectionColor = color; Input.Component.selectionColor = color;
Input.Component.readOnly = false; Input.Component.readOnly = false;
settingCaretCoroutine = false; settingCaretCoroutine = false;
} }
// For Home and End keys
static void JumpToStartOrEndOfLine(bool toStart)
{
// Determine the current and next line
UILineInfo thisline = default;
UILineInfo nextLine = default;
for (int i = 0; i < Input.Component.cachedInputTextGenerator.lineCount; i++)
{
UILineInfo line = Input.Component.cachedInputTextGenerator.lines[i];
if (line.startCharIdx > LastCaretPosition)
{
nextLine = line;
break;
}
thisline = line;
}
if (toStart)
{
// Determine where the non-whitespace text begins
int nonWhitespaceStartIdx = thisline.startCharIdx;
while (char.IsWhiteSpace(Input.Text[nonWhitespaceStartIdx]))
nonWhitespaceStartIdx++;
// Jump to either the true start or the non-whitespace position,
// depending on which one we are not at.
if (LastCaretPosition == nonWhitespaceStartIdx)
SetCaretPosition(thisline.startCharIdx);
else // jump to the next line start index - 1, ie. end of this line
SetCaretPosition(nonWhitespaceStartIdx);
}
else
{
// If there is no next line, jump to the end of this line (+1, to the invisible next character position)
if (nextLine.startCharIdx <= 0)
SetCaretPosition(Input.Text.Length);
else
SetCaretPosition(nextLine.startCharIdx - 1);
}
}
#endregion
#region Lexer Highlighting #region Lexer Highlighting
/// <summary> /// <summary>
/// Returns true if caret is inside string or comment, false otherwise /// Returns true if caret is inside string or comment, false otherwise
/// </summary> /// </summary>
private static bool HighlightVisibleInput() private static void HighlightVisibleInput(out bool inStringOrComment)
{ {
inStringOrComment = false;
if (string.IsNullOrEmpty(Input.Text)) if (string.IsNullOrEmpty(Input.Text))
{ {
Panel.HighlightText.text = ""; Panel.HighlightText.text = "";
Panel.LineNumberText.text = "1"; Panel.LineNumberText.text = "1";
return false; return;
} }
// Calculate the visible lines // Calculate the visible lines
@ -452,7 +503,7 @@ namespace UnityExplorer.CSConsole
// Highlight the visible text with the LexerBuilder // Highlight the visible text with the LexerBuilder
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out bool ret); Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out inStringOrComment);
// Set the line numbers // Set the line numbers
@ -490,7 +541,7 @@ namespace UnityExplorer.CSConsole
Panel.LineNumberText.text = sb.ToString(); Panel.LineNumberText.text = sb.ToString();
return ret; return;
} }
#endregion #endregion
@ -530,13 +581,11 @@ namespace UnityExplorer.CSConsole
#region Auto indenting #region Auto indenting
private static int prevContentLen = 0;
private static void DoAutoIndent() private static void DoAutoIndent()
{ {
if (Input.Text.Length > prevContentLen) if (Input.Text.Length > previousContentLength)
{ {
int inc = Input.Text.Length - prevContentLen; int inc = Input.Text.Length - previousContentLength;
if (inc == 1) if (inc == 1)
{ {
@ -555,7 +604,7 @@ namespace UnityExplorer.CSConsole
} }
} }
prevContentLen = Input.Text.Length; previousContentLength = Input.Text.Length;
} }
#endregion #endregion
@ -563,8 +612,6 @@ namespace UnityExplorer.CSConsole
#region "Help" interaction #region "Help" interaction
private static bool SRENotSupported;
private static void DisableConsole(Exception ex) private static void DisableConsole(Exception ex)
{ {
SRENotSupported = true; SRENotSupported = true;

View File

@ -17,8 +17,6 @@ namespace UnityExplorer.CSConsole
public class LexerBuilder public class LexerBuilder
{ {
#region Core and initialization
public const char WHITESPACE = ' '; public const char WHITESPACE = ' ';
public readonly HashSet<char> IndentOpenChars = new() { '{', '(' }; public readonly HashSet<char> IndentOpenChars = new() { '{', '(' };
public readonly HashSet<char> IndentCloseChars = new() { '}', ')' }; public readonly HashSet<char> IndentCloseChars = new() { '}', ')' };
@ -50,8 +48,6 @@ namespace UnityExplorer.CSConsole
} }
} }
#endregion
/// <summary>The last committed index for a match or no-match. Starts at -1 for a new parse.</summary> /// <summary>The last committed index for a match or no-match. Starts at -1 for a new parse.</summary>
public int CommittedIndex { get; private set; } public int CommittedIndex { get; private set; }
/// <summary>The index of the character we are currently parsing, at minimum it will be CommittedIndex + 1.</summary> /// <summary>The index of the character we are currently parsing, at minimum it will be CommittedIndex + 1.</summary>

View File

@ -32,13 +32,7 @@ namespace UnityExplorer.CSConsole.Lexers
if (IsSymbol(lexer.Current)) if (IsSymbol(lexer.Current))
{ {
do lexer.Commit();
{
lexer.Commit();
lexer.PeekNext();
}
while (IsSymbol(lexer.Current));
return true; return true;
} }

View File

@ -54,6 +54,10 @@ namespace UnityExplorer.Config
Handler.LoadConfig(); Handler.LoadConfig();
InternalHandler.LoadConfig(); InternalHandler.LoadConfig();
#if STANDALONE
Loader.Standalone.ExplorerEditorBehaviour.Instance?.LoadConfigs();
#endif
//InitConsoleCallback(); //InitConsoleCallback();
} }

View File

@ -1,4 +1,8 @@
using UnityEngine; using System;
using System.Reflection;
using UnityEngine;
using UnityExplorer.UI;
using UniverseLib;
#if CPP #if CPP
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
#endif #endif
@ -29,5 +33,39 @@ namespace UnityExplorer
{ {
ExplorerCore.Update(); ExplorerCore.Update();
} }
// For editor, to clean up objects
internal void OnDestroy()
{
OnApplicationQuit();
}
internal bool quitting;
internal void OnApplicationQuit()
{
if (quitting) return;
quitting = true;
TryDestroy(UIManager.UIRoot?.transform.root.gameObject);
TryDestroy((typeof(Universe).Assembly.GetType("UniverseLib.UniversalBehaviour")
.GetProperty("Instance", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null, null)
as Component).gameObject);
TryDestroy(this.gameObject);
}
internal void TryDestroy(GameObject obj)
{
try
{
if (obj)
Destroy(obj);
}
catch { }
}
} }
} }

View File

@ -14,7 +14,7 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "4.7.7"; public const string VERSION = "4.7.9";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";

View File

@ -6,27 +6,53 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Config;
using UnityExplorer.UI;
using UniverseLib;
namespace UnityExplorer.Loader.Standalone namespace UnityExplorer.Loader.Standalone
{ {
public class ExplorerEditorBehaviour : MonoBehaviour public class ExplorerEditorBehaviour : MonoBehaviour
{ {
internal static ExplorerEditorBehaviour Instance { get; private set; }
public bool Hide_On_Startup = true;
public KeyCode Master_Toggle_Key = KeyCode.F7;
public UIManager.VerticalAnchor Main_Navbar_Anchor = UIManager.VerticalAnchor.Top;
public bool Log_Unity_Debug = false;
public float Startup_Delay_Time = 1f;
public KeyCode World_MouseInspect_Keybind;
public KeyCode UI_MouseInspect_Keybind;
public bool Force_Unlock_Mouse = true;
public KeyCode Force_Unlock_Toggle;
public bool Disable_EventSystem_Override;
internal void Awake() internal void Awake()
{ {
Instance = this;
ExplorerEditorLoader.Initialize(); ExplorerEditorLoader.Initialize();
DontDestroyOnLoad(this); DontDestroyOnLoad(this);
this.gameObject.hideFlags = HideFlags.HideAndDontSave; this.gameObject.hideFlags = HideFlags.HideAndDontSave;
} }
internal void OnDestroy()
{
OnApplicationQuit();
}
internal void OnApplicationQuit() internal void OnApplicationQuit()
{ {
if (UI.UIManager.UIRoot) Destroy(this.gameObject);
Destroy(UI.UIManager.UIRoot.transform.root.gameObject); }
internal void LoadConfigs()
{
ConfigManager.Hide_On_Startup.Value = this.Hide_On_Startup;
ConfigManager.Master_Toggle.Value = this.Master_Toggle_Key;
ConfigManager.Main_Navbar_Anchor.Value = this.Main_Navbar_Anchor;
ConfigManager.Log_Unity_Debug.Value = this.Log_Unity_Debug;
ConfigManager.Startup_Delay_Time.Value = this.Startup_Delay_Time;
ConfigManager.World_MouseInspect_Keybind.Value = this.World_MouseInspect_Keybind;
ConfigManager.UI_MouseInspect_Keybind.Value = this.UI_MouseInspect_Keybind;
ConfigManager.Force_Unlock_Mouse.Value = this.Force_Unlock_Mouse;
ConfigManager.Force_Unlock_Toggle.Value = this.Force_Unlock_Toggle;
ConfigManager.Disable_EventSystem_Override.Value = this.Disable_EventSystem_Override;
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace UnityExplorer.Loader.Standalone
protected override void CheckExplorerFolder() protected override void CheckExplorerFolder()
{ {
if (explorerFolderDest == null) if (explorerFolderDest == null)
explorerFolderDest = Application.dataPath; explorerFolderDest = Path.GetDirectoryName(Application.dataPath);
} }
} }
} }

View File

@ -145,7 +145,7 @@ namespace UnityExplorer.UI.Panels
GameObject inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT, GameObject inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
out InputFieldScroller inputScroller, fontSize); out InputFieldScroller inputScroller, fontSize);
InputScroller = inputScroller; InputScroller = inputScroller;
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a; ConsoleController.DefaultInputFieldAlpha = Input.Component.selectionColor.a;
Input.OnValueChanged += InvokeOnValueChanged; Input.OnValueChanged += InvokeOnValueChanged;
// move line number text with input field // move line number text with input field

View File

@ -119,6 +119,8 @@ namespace UnityExplorer.UI.Panels
{ {
Rect.SetAnchorsFromString(split[1]); Rect.SetAnchorsFromString(split[1]);
Rect.SetPositionFromString(split[2]); Rect.SetPositionFromString(split[2]);
this.EnsureValidSize();
this.EnsureValidPosition();
this.SetActive(bool.Parse(split[0])); this.SetActive(bool.Parse(split[0]));
} }
catch catch

View File

@ -26,7 +26,6 @@ namespace UnityExplorer.UI
Options, Options,
ConsoleLog, ConsoleLog,
AutoCompleter, AutoCompleter,
//MouseInspector,
UIInspectorResults, UIInspectorResults,
HookManager, HookManager,
Clipboard, Clipboard,

View File

@ -79,11 +79,11 @@
<!-- il2cpp nuget --> <!-- il2cpp nuget -->
<ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'"> <ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'">
<PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" IncludeAssets="compile" /> <PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" IncludeAssets="compile" />
<PackageReference Include="UniverseLib.IL2CPP" Version="1.3.9" /> <PackageReference Include="UniverseLib.IL2CPP" Version="1.3.10" />
</ItemGroup> </ItemGroup>
<!-- mono nuget --> <!-- mono nuget -->
<ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'"> <ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'">
<PackageReference Include="UniverseLib.Mono" Version="1.3.9" /> <PackageReference Include="UniverseLib.Mono" Version="1.3.10" />
</ItemGroup> </ItemGroup>
<!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ --> <!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ -->