mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-01 11:12:49 +08:00
Only lexer-highlight what is shown in CS console (fix max vert overflow)
This commit is contained in:
@ -6,6 +6,7 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI;
|
||||
#if CPP
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnhollowerBaseLib;
|
||||
@ -70,6 +71,9 @@ namespace UnityExplorer.Tests
|
||||
|
||||
public static TestValueStruct AATestStruct;
|
||||
|
||||
public static string AAATooLongString = new string('#', UIManager.MAX_INPUTFIELD_CHARS + 2);
|
||||
public static string AAAMaxString = new string('@', UIManager.MAX_INPUTFIELD_CHARS);
|
||||
|
||||
public static TestEnum AATestEnumOne = TestEnum.Neg50;
|
||||
public static TestEnum2 AATestEnumTwo = TestEnum2.Max;
|
||||
public static TestFlags AATestFlags = TestFlags.Thirteen;
|
||||
|
@ -61,7 +61,7 @@ The following helper methods are available:
|
||||
private static HashSet<string> usingDirectives;
|
||||
|
||||
private static CSConsolePanel Panel => UIManager.CSharpConsole;
|
||||
private static InputField InputField => Panel.InputField.InputField;
|
||||
private static InputFieldRef Input => Panel.Input;
|
||||
|
||||
// Todo save as config?
|
||||
public static bool EnableCtrlRShortcut { get; private set; } = true;
|
||||
@ -78,7 +78,8 @@ The following helper methods are available:
|
||||
Evaluator.Compile("0 == 0");
|
||||
|
||||
Panel.OnInputChanged += OnConsoleInputChanged;
|
||||
// TODO other panel listeners
|
||||
Panel.InputScroll.OnScroll += ForceOnContentChange;
|
||||
// TODO other panel listeners (buttons, etc)
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -87,6 +88,123 @@ The following helper methods are available:
|
||||
}
|
||||
}
|
||||
|
||||
// Updating and event listeners
|
||||
|
||||
private static readonly KeyCode[] onFocusKeys =
|
||||
{
|
||||
KeyCode.Return, KeyCode.Backspace, KeyCode.UpArrow,
|
||||
KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow
|
||||
};
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (EnableCtrlRShortcut)
|
||||
{
|
||||
if ((InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
||||
&& InputManager.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
var text = Panel.Input.Text.Trim();
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
Evaluate(text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return))
|
||||
// DoAutoIndent();
|
||||
|
||||
//if (EnableAutocompletes && InputField.isFocused)
|
||||
//{
|
||||
// if (InputManager.GetMouseButton(0) || onFocusKeys.Any(it => InputManager.GetKeyDown(it)))
|
||||
// UpdateAutocompletes();
|
||||
//}
|
||||
}
|
||||
|
||||
private static void ForceOnContentChange()
|
||||
{
|
||||
OnConsoleInputChanged(Input.Text);
|
||||
}
|
||||
|
||||
// Invoked at most once per frame
|
||||
private static void OnConsoleInputChanged(string value)
|
||||
{
|
||||
// todo auto indent? or only on enter?
|
||||
|
||||
// syntax highlight
|
||||
LexerHighlightAndSet(value);
|
||||
|
||||
|
||||
// todo update auto completes
|
||||
// ...
|
||||
}
|
||||
|
||||
private static void LexerHighlightAndSet(string value)
|
||||
{
|
||||
int startLine = 0;
|
||||
int endLine = Input.TextGenerator.lineCount - 1;
|
||||
|
||||
if (Input.Rect.rect.height > Panel.InputScroll.ViewportRect.rect.height)
|
||||
{
|
||||
// Not all text is displayed.
|
||||
// Only syntax highlight what we need to.
|
||||
|
||||
int topLine = -1;
|
||||
int bottomLine = -1;
|
||||
var half = Input.Rect.rect.height * 0.5f;
|
||||
|
||||
var top = Input.Rect.rect.height - Input.Rect.anchoredPosition.y;
|
||||
var bottom = top - Panel.InputScroll.ViewportRect.rect.height;
|
||||
|
||||
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
|
||||
{
|
||||
var line = Input.TextGenerator.lines[i];
|
||||
var pos = line.topY + half;
|
||||
|
||||
if (topLine == -1 && pos <= top)
|
||||
topLine = i;
|
||||
|
||||
if ((pos - line.height) >= bottom)
|
||||
bottomLine = i;
|
||||
}
|
||||
|
||||
startLine = Math.Max(0, topLine - 1);
|
||||
endLine = Math.Min(Input.TextGenerator.lineCount - 1, bottomLine + 1);
|
||||
}
|
||||
|
||||
int startIdx = Input.TextGenerator.lines[startLine].startCharIdx;
|
||||
int endIdx;
|
||||
if (endLine >= Input.TextGenerator.lineCount - 1)
|
||||
endIdx = value.Length - 1;
|
||||
else
|
||||
endIdx = Math.Min(value.Length - 1, Input.TextGenerator.lines[endLine + 1].startCharIdx);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 0; i < startLine; i++)
|
||||
sb.Append('\n');
|
||||
for (int i = startIdx; i <= endIdx; i++)
|
||||
sb.Append(value[i]);
|
||||
|
||||
Panel.HighlightText.text = Lexer.SyntaxHighlight(sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
// TODO indenting
|
||||
|
||||
//private static void DoAutoIndent()
|
||||
//{
|
||||
// int caret = Panel.LastCaretPosition;
|
||||
// Panel.InputField.Text = Lexer.AutoIndentOnEnter(InputField.text, ref caret);
|
||||
// InputField.caretPosition = caret;
|
||||
//
|
||||
// Panel.InputText.Rebuild(CanvasUpdate.Prelayout);
|
||||
// InputField.ForceLabelUpdate();
|
||||
// InputField.Rebuild(CanvasUpdate.Prelayout);
|
||||
//
|
||||
// OnConsoleInputChanged(InputField.text);
|
||||
//}
|
||||
|
||||
#region Evaluating console input
|
||||
|
||||
public static void ResetConsole(bool logSuccess = true)
|
||||
@ -149,65 +267,5 @@ The following helper methods are available:
|
||||
|
||||
#endregion
|
||||
|
||||
// Updating and event listeners
|
||||
|
||||
private static readonly KeyCode[] onFocusKeys =
|
||||
{
|
||||
KeyCode.Return, KeyCode.Backspace, KeyCode.UpArrow,
|
||||
KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow
|
||||
};
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (EnableCtrlRShortcut)
|
||||
{
|
||||
if ((InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
|
||||
&& InputManager.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
var text = Panel.InputField.Text.Trim();
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
Evaluate(text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return))
|
||||
// DoAutoIndent();
|
||||
|
||||
//if (EnableAutocompletes && InputField.isFocused)
|
||||
//{
|
||||
// if (InputManager.GetMouseButton(0) || onFocusKeys.Any(it => InputManager.GetKeyDown(it)))
|
||||
// UpdateAutocompletes();
|
||||
//}
|
||||
}
|
||||
|
||||
// Invoked at most once per frame
|
||||
private static void OnConsoleInputChanged(string input)
|
||||
{
|
||||
// todo update auto completes
|
||||
|
||||
// update syntax highlight
|
||||
Panel.HighlightText.text = Lexer.SyntaxHighlight(input);
|
||||
|
||||
}
|
||||
|
||||
// TODO?
|
||||
//private static void DoAutoIndent()
|
||||
//{
|
||||
// int caret = Panel.LastCaretPosition;
|
||||
// Panel.InputField.Text = Lexer.AutoIndentOnEnter(InputField.text, ref caret);
|
||||
// InputField.caretPosition = caret;
|
||||
//
|
||||
// Panel.InputText.Rebuild(CanvasUpdate.Prelayout);
|
||||
// InputField.ForceLabelUpdate();
|
||||
// InputField.Rebuild(CanvasUpdate.Prelayout);
|
||||
//
|
||||
// OnConsoleInputChanged(InputField.text);
|
||||
//}
|
||||
|
||||
// Autocompletes
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
if (s == null)
|
||||
return false;
|
||||
|
||||
|
||||
return s.Length >= UIManager.MAX_INPUTFIELD_CHARS;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
public InputField InputField;
|
||||
public Text PlaceholderText;
|
||||
private readonly RectTransform Rect;
|
||||
public RectTransform Rect;
|
||||
|
||||
public string Text
|
||||
{
|
||||
@ -30,6 +30,9 @@ namespace UnityExplorer.UI
|
||||
set => InputField.text = value;
|
||||
}
|
||||
|
||||
public bool ReachedMaxVerts => TextGenerator.vertexCount >= UIManager.MAX_TEXT_VERTS;
|
||||
public TextGenerator TextGenerator => InputField.cachedInputTextGenerator;
|
||||
|
||||
private bool updatedWanted;
|
||||
|
||||
private void OnInputChanged(string value)
|
||||
@ -41,7 +44,8 @@ namespace UnityExplorer.UI
|
||||
{
|
||||
if (updatedWanted)
|
||||
{
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Rect);
|
||||
//LayoutRebuilder.ForceRebuildLayoutImmediate(Rect);
|
||||
LayoutRebuilder.MarkLayoutForRebuild(Rect);
|
||||
|
||||
OnValueChanged?.Invoke(InputField.text);
|
||||
updatedWanted = false;
|
||||
|
@ -18,7 +18,8 @@ namespace UnityExplorer.UI.Panels
|
||||
public override int MinWidth => 400;
|
||||
public override int MinHeight => 300;
|
||||
|
||||
public InputFieldRef InputField { get; private set; }
|
||||
public InputFieldScroller InputScroll { get; private set; }
|
||||
public InputFieldRef Input => InputScroll.InputField;
|
||||
public Text InputText { get; private set; }
|
||||
public Text HighlightText { get; private set; }
|
||||
|
||||
@ -37,19 +38,20 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public void UseSuggestion(string suggestion)
|
||||
{
|
||||
string input = InputField.Text;
|
||||
string input = Input.Text;
|
||||
input = input.Insert(LastCaretPosition, suggestion);
|
||||
InputField.Text = input;
|
||||
Input.Text = input;
|
||||
|
||||
m_desiredCaretFix = LastCaretPosition += suggestion.Length;
|
||||
|
||||
var color = InputField.InputField.selectionColor;
|
||||
var color = Input.InputField.selectionColor;
|
||||
color.a = 0f;
|
||||
InputField.InputField.selectionColor = color;
|
||||
Input.InputField.selectionColor = color;
|
||||
}
|
||||
|
||||
private void InvokeOnValueChanged(string value)
|
||||
{
|
||||
// Todo show a label instead of just logging
|
||||
if (value.Length == UIManager.MAX_INPUTFIELD_CHARS)
|
||||
ExplorerCore.LogWarning($"Reached maximum InputField character length! ({UIManager.MAX_INPUTFIELD_CHARS})");
|
||||
|
||||
@ -66,23 +68,23 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
if (!m_fixWaiting)
|
||||
{
|
||||
EventSystem.current.SetSelectedGameObject(InputField.UIRoot, null);
|
||||
EventSystem.current.SetSelectedGameObject(InputScroll.UIRoot, null);
|
||||
m_fixWaiting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputField.InputField.caretPosition = m_desiredCaretFix;
|
||||
InputField.InputField.selectionFocusPosition = m_desiredCaretFix;
|
||||
var color = InputField.InputField.selectionColor;
|
||||
Input.InputField.caretPosition = m_desiredCaretFix;
|
||||
Input.InputField.selectionFocusPosition = m_desiredCaretFix;
|
||||
var color = Input.InputField.selectionColor;
|
||||
color.a = m_defaultInputFieldAlpha;
|
||||
InputField.InputField.selectionColor = color;
|
||||
Input.InputField.selectionColor = color;
|
||||
|
||||
m_fixWaiting = false;
|
||||
m_desiredCaretFix = -1;
|
||||
}
|
||||
}
|
||||
else if (InputField.InputField.caretPosition > 0)
|
||||
LastCaretPosition = InputField.InputField.caretPosition;
|
||||
else if (Input.InputField.caretPosition > 0)
|
||||
LastCaretPosition = Input.InputField.caretPosition;
|
||||
}
|
||||
|
||||
// Saving
|
||||
@ -150,14 +152,14 @@ namespace UnityExplorer.UI.Panels
|
||||
int fontSize = 16;
|
||||
|
||||
var inputObj = UIFactory.CreateSrollInputField(this.content, "ConsoleInput", CSConsole.STARTUP_TEXT, out var inputScroller, fontSize);
|
||||
InputField = inputScroller.InputField;
|
||||
m_defaultInputFieldAlpha = InputField.InputField.selectionColor.a;
|
||||
InputField.OnValueChanged += InvokeOnValueChanged;
|
||||
InputScroll = inputScroller;
|
||||
m_defaultInputFieldAlpha = Input.InputField.selectionColor.a;
|
||||
Input.OnValueChanged += InvokeOnValueChanged;
|
||||
|
||||
var placeHolderText = InputField.PlaceholderText;
|
||||
var placeHolderText = Input.PlaceholderText;
|
||||
placeHolderText.fontSize = fontSize;
|
||||
|
||||
InputText = InputField.InputField.textComponent;
|
||||
InputText = Input.InputField.textComponent;
|
||||
InputText.supportRichText = false;
|
||||
InputText.color = new Color(1, 1, 1, 0.65f);
|
||||
|
||||
|
@ -58,6 +58,7 @@ namespace UnityExplorer.UI
|
||||
internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f);
|
||||
|
||||
public const int MAX_INPUTFIELD_CHARS = 16000;
|
||||
public const int MAX_TEXT_VERTS = 65000;
|
||||
|
||||
public static UIPanel GetPanel(Panels panel)
|
||||
{
|
||||
|
@ -25,6 +25,8 @@ namespace UnityExplorer.UI.Utility
|
||||
}
|
||||
}
|
||||
|
||||
public Action OnScroll;
|
||||
|
||||
internal AutoSliderScrollbar Slider;
|
||||
internal InputFieldRef InputField;
|
||||
|
||||
@ -52,25 +54,40 @@ namespace UnityExplorer.UI.Utility
|
||||
internal bool m_wantJumpToBottom;
|
||||
private float m_desiredContentHeight;
|
||||
|
||||
private float lastContentPosition;
|
||||
private float lastViewportHeight;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (this.ContentRect.localPosition.y != lastContentPosition)
|
||||
{
|
||||
lastContentPosition = ContentRect.localPosition.y;
|
||||
OnScroll?.Invoke();
|
||||
}
|
||||
|
||||
if (ViewportRect.rect.height != lastViewportHeight)
|
||||
{
|
||||
lastViewportHeight = ViewportRect.rect.height;
|
||||
m_updateWanted = true;
|
||||
}
|
||||
|
||||
if (m_updateWanted)
|
||||
{
|
||||
m_updateWanted = false;
|
||||
ProcessInputText();
|
||||
}
|
||||
|
||||
float desiredHeight = Math.Max(m_desiredContentHeight, ViewportRect.rect.height);
|
||||
float desiredHeight = Math.Max(m_desiredContentHeight, ViewportRect.rect.height);
|
||||
|
||||
if (ContentRect.rect.height < desiredHeight)
|
||||
{
|
||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
||||
this.Slider.UpdateSliderHandle();
|
||||
}
|
||||
else if (ContentRect.rect.height > desiredHeight)
|
||||
{
|
||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
||||
this.Slider.UpdateSliderHandle();
|
||||
if (ContentRect.rect.height < desiredHeight)
|
||||
{
|
||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
||||
this.Slider.UpdateSliderHandle();
|
||||
}
|
||||
else if (ContentRect.rect.height > desiredHeight)
|
||||
{
|
||||
ContentRect.sizeDelta = new Vector2(0, desiredHeight);
|
||||
this.Slider.UpdateSliderHandle();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wantJumpToBottom)
|
||||
@ -100,6 +117,9 @@ namespace UnityExplorer.UI.Utility
|
||||
var textGen = InputField.InputField.textComponent.cachedTextGeneratorForLayout;
|
||||
m_desiredContentHeight = textGen.GetPreferredHeight(m_lastText, texGenSettings) + 10;
|
||||
|
||||
// TODO more intelligent jump.
|
||||
// We can detect if the caret is outside the viewport area.
|
||||
|
||||
// jump to bottom
|
||||
if (InputField.InputField.caretPosition == InputField.Text.Length
|
||||
&& InputField.Text.Length > 0
|
||||
|
Reference in New Issue
Block a user