This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
@@ -10,12 +11,86 @@ using UnityEngine.InputSystem;
using Cysharp.Threading.Tasks;
using System.Text;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using Google.Apis.Http;
using UnityEngine.InputSystem.Interactions;
using Label = UnityEngine.UIElements.Label;
// ReSharper disable PossibleMultipleEnumeration
namespace BITKit.Console
{
public class BITConsole : MonoBehaviour
{
[RuntimeInitializeOnLoadMethod]
private static void Reload()
{
Application.logMessageReceivedThreaded += EnqueueLog;
}
private class CommandSelector
{
public VisualElement Container { get; set; }
public int Index
{
get => _index;
set
{
if (_methods.Length is 0)
{
_index = -1;
return;
}
_index = (value+_methods.Length)%_methods.Length;
Rebuild();
}
}
public event Action<MethodInfo> OnSelected;
private int _index;
private MethodInfo[] _methods=Array.Empty<MethodInfo>();
public void Rebuild()
{
Container.Clear();
for (var i = 0; i < _methods.Length; i++)
{
var method = _methods[i];
var button = Container.Create<Button>();
StringBuilder stringBuilder = new(method.Name);
foreach (var parameterInfo in method.GetParameters())
{
stringBuilder.Append($" {parameterInfo.ParameterType.Name}:{parameterInfo.Name}");
}
button.clicked+= () =>
{
OnSelected?.Invoke(method);
Rebuild();
};
button.text = stringBuilder.ToString();
Container.Add(button);
}
}
public void SetMethods(IEnumerable<MethodInfo> methods)
{
if (methods.IsValid())
{
if (_methods.SequenceEqual(methods)) return;
}
_methods=methods.IsValid()?methods.ToArray():Array.Empty<MethodInfo>();
if (_methods!.Length is 0)
{
_index = -1;
}
Rebuild();
}
}
[BITCommand]
public static async void Clear()
{
@@ -23,75 +98,92 @@ namespace BITKit.Console
singleton.outputString.Clear();
singleton.text.text = string.Empty;
}
static BITConsole singleton;
const string textFieldName = "TextField";
const string commandListViewName = "commands-listview";
const string textName = "Text";
const string scrollViewName = "context-scrollview";
private static BITConsole singleton;
[SerializeField] private UIDocument document;
[SerializeReference] private InputActionReference toggleAction;
[SerializeReference] public InputActionReference nextOrPreviousAction;
private static ConcurrentQueue<(string condition, string stackTrace, LogType type)> logQueue = new();
private static void EnqueueLog(string condition, string stackTrace, LogType type)
{
logQueue.Enqueue((condition, stackTrace, type));
}
private readonly InputActionGroup _inputActionGroup=new()
{
allowGlobalActivation = false
};
public int logLineLimit = 64;
private ListView commandListView;
[UXBindPath("commands-container")]
private VisualElement commandContainer;
[UXBindPath("TextField")]
private TextField textField;
[UXBindPath("Text")]
private Label text;
[UXBindPath( "context-scrollview")]
private ScrollView scrollView;
private bool isActived;
private bool _isRunning;
private List<string> outputString = new();
private void Awake()
{
Application.logMessageReceivedThreaded += LogCallback;
}
private CommandSelector _commandSelector;
private void Start()
{
UXUtils.Inject(this);
_commandSelector = new()
{
Container = commandContainer,
};
_commandSelector.OnSelected += x =>
{
textField.SetValueWithoutNotify(x.Name);
textField.Blur();
textField.Focus();
};
singleton = this;
var visualElement = document.rootVisualElement;
textField = visualElement.Q<TextField>(textFieldName);
commandListView = visualElement.Q<ListView>(commandListViewName);
text = visualElement.Q<Label>(textName);
scrollView = visualElement.Q<ScrollView>(scrollViewName);
textField.RegisterValueChangedCallback(OnTextFieldValieChanged);
textField.RegisterValueChangedCallback(OnTextFieldValueChanged);
textField.RegisterCallback<KeyDownEvent>(OnKeyDown);
commandListView.selectionChanged += OnSelectionChange;
nextOrPreviousAction.action.performed += OnNextCommand;
text.text = string.Empty;
BIT4Log.OnNextLine += () =>
{
if (outputString.Count is not 0 && outputString.Last() != string.Empty)
outputString.Add(string.Empty);
};
commandListView.SetActive(false);
_inputActionGroup.RegisterCallback(toggleAction,Toggle);
_inputActionGroup.RegisterCallback(nextOrPreviousAction, OnNextCommand);
//_inputActionGroup.RegisterCallback(nextOrPreviousAction, OnNextCommand);
_inputActionGroup.allowInput.AddElement(this);
Toggle(false);
BIT4Log.OnNextLine += OnNextLine;
destroyCancellationToken.Register(() =>
{
BIT4Log.OnNextLine -= OnNextLine;
});
}
private void OnNextLine()
{
if (outputString.Count is not 0 && outputString.Last() != string.Empty)
outputString.Add(string.Empty);
}
private void OnDestroy()
{
_inputActionGroup.allowInput.RemoveElement(this);
Application.logMessageReceivedThreaded -= LogCallback;
}
public async void Toggle(bool active)
{
_commandSelector.SetMethods(null);
document.rootVisualElement.SetActive(active);
isActived = active;
_isRunning = active;
BITAppForUnity.AllowCursor.SetElements(this,active);
BITInputSystem.AllowInput.SetDisableElements(this,active);
@@ -110,41 +202,26 @@ namespace BITKit.Console
text.Blur();
}
}
private void OnTextFieldValieChanged(ChangeEvent<string> callback)
private void OnTextFieldValueChanged(ChangeEvent<string> callback)
{
if (callback.newValue.IsValid())
if (string.IsNullOrEmpty(callback.newValue) is false)
{
var commands = BITCommands.GetMethodInfos(callback.newValue).Select(x => x.Name).ToList();
if (commands.Count is 0)
{
commandListView.SetActive(false);
}
else
{
commandListView.itemsSource = commands;
commandListView.SetActive(true);
}
var commands = BITCommands.GetMethodInfos(callback.newValue).ToArray();
_commandSelector.SetMethods(commands);
commandContainer.SetActive(commands.Length is not 0);
}
else
{
commandListView.SetActive(false);
commandContainer.SetActive(false);
_commandSelector.SetMethods(null);
}
}
private void OnDropdownValueChanged(ChangeEvent<string> callback)
{
textField.SetValueWithoutNotify(callback.newValue);
OnTextFieldValieChanged(callback);
textField.Focus();
}
private void OnNextCommand(InputAction.CallbackContext context)
{
if (context.started)
{
var index = context.ReadValue<Vector2>().y;
}
}
private void OnKeyDown(KeyDownEvent keyDownEvent)
private async void OnKeyDown(KeyDownEvent keyDownEvent)
{
var nextStop=true;
switch (keyDownEvent.keyCode)
{
case KeyCode.Return:
@@ -153,13 +230,38 @@ namespace BITKit.Console
LogCallback($">{cmd}", string.Empty, LogType.Log);
textField.SetValueWithoutNotify(string.Empty);
await UniTask.NextFrame();
if (destroyCancellationToken.IsCancellationRequested) return;
textField.Blur();
textField.Focus();
BITCommands.Excute(cmd);
_commandSelector.SetMethods(null);
break;
case KeyCode.Tab:
break;
case KeyCode.DownArrow when string.IsNullOrEmpty(textField.text) is false:
_commandSelector.Index-=1;
break;
case KeyCode.UpArrow when string.IsNullOrEmpty(textField.text) is false:
_commandSelector.Index+=1;
break;
default:
nextStop = false;
break;
}
if (nextStop)
{
keyDownEvent.StopPropagation();
keyDownEvent.PreventDefault();
}
}
@@ -168,7 +270,7 @@ namespace BITKit.Console
switch (context)
{
case { interaction: PressInteraction, performed: true }:
Toggle(!isActived);
Toggle(!_isRunning);
break;
}
}
@@ -205,6 +307,7 @@ namespace BITKit.Console
await BITApp.SwitchToMainThread();
scrollView.ScrollToBottomAutomatic();
text.text = stringBuilder.ToString();
}
catch (OperationCanceledException)
{
@@ -218,24 +321,23 @@ namespace BITKit.Console
private void Update()
{
while (logQueue.TryDequeue(out var log))
{
LogCallback(log.condition, log.stackTrace, log.type);
}
if (_isRunning is false) return;
var pos = textField.worldTransform.GetPosition();
var size = textField.layout.size;
commandListView.style.left = 0;
commandListView.style.top = 0;
commandContainer.style.left = 0;
commandContainer.style.top = 0;
pos.y += size.y;
commandListView.transform.position = pos;
commandContainer.transform.position = pos;
commandListView.style.width = size.x;
}
private void OnSelectionChange(IEnumerable<object> selected)
{
var _selected = selected.First() as string;
textField.SetValueWithoutNotify(_selected);
commandListView.itemsSource?.Clear();
commandListView.SetActive(false);
commandContainer.style.width = size.x;
}
}
}