2024-01-23 02:56:26 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
using BITKit;
|
|
|
|
using BITKit.UX;
|
|
|
|
using System.Linq;
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
using System.Text;
|
|
|
|
using System.IO;
|
|
|
|
using System.Reflection;
|
|
|
|
using Google.Apis.Http;
|
|
|
|
using UnityEngine.InputSystem.Interactions;
|
|
|
|
|
|
|
|
namespace BITKit.Console
|
|
|
|
{
|
|
|
|
public class BITConsole : MonoBehaviour
|
|
|
|
{
|
|
|
|
[BITCommand]
|
|
|
|
public static async void Clear()
|
|
|
|
{
|
|
|
|
await BITApp.SwitchToMainThread();
|
|
|
|
singleton.outputString.Clear();
|
|
|
|
singleton.text.text = string.Empty;
|
|
|
|
}
|
|
|
|
private static BITConsole singleton;
|
|
|
|
[SerializeField] private UIDocument document;
|
|
|
|
[SerializeReference] private InputActionReference toggleAction;
|
|
|
|
[SerializeReference] public InputActionReference nextOrPreviousAction;
|
|
|
|
|
|
|
|
private readonly InputActionGroup _inputActionGroup=new()
|
|
|
|
{
|
|
|
|
allowGlobalActivation = false
|
|
|
|
};
|
|
|
|
public int logLineLimit = 64;
|
|
|
|
[UXBindPath("commands-listview")]
|
|
|
|
private ListView commandListView;
|
|
|
|
[UXBindPath("TextField")]
|
|
|
|
private TextField textField;
|
|
|
|
[UXBindPath("Text")]
|
|
|
|
private Label text;
|
|
|
|
[UXBindPath( "context-scrollview")]
|
|
|
|
private ScrollView scrollView;
|
|
|
|
private bool isActived;
|
|
|
|
private List<string> outputString = new();
|
|
|
|
|
|
|
|
private (MethodInfo[] methods,int currentIndex) _currentCommands;
|
|
|
|
|
|
|
|
private void Start()
|
|
|
|
{
|
|
|
|
singleton = this;
|
|
|
|
|
|
|
|
UXUtils.Inject(this);
|
|
|
|
|
|
|
|
textField.RegisterValueChangedCallback(OnTextFieldValieChanged);
|
|
|
|
textField.RegisterCallback<KeyDownEvent>(OnKeyDown);
|
|
|
|
|
|
|
|
commandListView.selectionChanged += OnSelectionChange;
|
|
|
|
|
|
|
|
nextOrPreviousAction.action.performed += OnNextCommand;
|
|
|
|
|
|
|
|
text.text = string.Empty;
|
|
|
|
|
|
|
|
commandListView.SetActive(false);
|
|
|
|
|
|
|
|
_inputActionGroup.RegisterCallback(toggleAction,Toggle);
|
|
|
|
//_inputActionGroup.RegisterCallback(nextOrPreviousAction, OnNextCommand);
|
|
|
|
|
|
|
|
_inputActionGroup.allowInput.AddElement(this);
|
|
|
|
|
|
|
|
Toggle(false);
|
|
|
|
|
|
|
|
BIT4Log.OnNextLine += OnNextLine;
|
|
|
|
|
|
|
|
destroyCancellationToken.Register(() =>
|
|
|
|
{
|
|
|
|
BIT4Log.OnNextLine -= OnNextLine;
|
|
|
|
});
|
2024-01-23 04:14:54 +08:00
|
|
|
|
|
|
|
Application.logMessageReceivedThreaded += LogCallback;
|
|
|
|
destroyCancellationToken.Register(() =>
|
|
|
|
{
|
|
|
|
Application.logMessageReceivedThreaded -= LogCallback;
|
|
|
|
});
|
2024-01-23 02:56:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void OnNextLine()
|
|
|
|
{
|
|
|
|
if (outputString.Count is not 0 && outputString.Last() != string.Empty)
|
|
|
|
outputString.Add(string.Empty);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
{
|
|
|
|
_inputActionGroup.allowInput.RemoveElement(this);
|
|
|
|
}
|
|
|
|
public async void Toggle(bool active)
|
|
|
|
{
|
|
|
|
document.rootVisualElement.SetActive(active);
|
|
|
|
isActived = active;
|
|
|
|
|
|
|
|
BITAppForUnity.AllowCursor.SetElements(this,active);
|
|
|
|
BITInputSystem.AllowInput.SetDisableElements(this,active);
|
|
|
|
|
|
|
|
await UniTask.WaitForEndOfFrame(this);
|
|
|
|
if (active)
|
|
|
|
{
|
|
|
|
textField.SetValueWithoutNotify(string.Empty);
|
|
|
|
|
|
|
|
textField.Focus();
|
|
|
|
|
|
|
|
scrollView.ScrollToBottom();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
text.Blur();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void OnTextFieldValieChanged(ChangeEvent<string> callback)
|
|
|
|
{
|
|
|
|
if (callback.newValue.IsValid())
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commandListView.SetActive(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void OnDropdownValueChanged(ChangeEvent<string> callback)
|
|
|
|
{
|
|
|
|
textField.SetValueWithoutNotify(callback.newValue);
|
|
|
|
OnTextFieldValieChanged(callback);
|
|
|
|
textField.Blur();
|
|
|
|
textField.Focus();
|
|
|
|
}
|
|
|
|
private void OnNextCommand(InputAction.CallbackContext context)
|
|
|
|
{
|
|
|
|
switch (context)
|
|
|
|
{
|
|
|
|
case { interaction: PressInteraction, performed: true }:
|
|
|
|
//var index = context.ReadValue<float>();
|
|
|
|
if (int.TryParse(context.ReadValue<float>().ToString(), out var index) is false) return;
|
|
|
|
|
|
|
|
_currentCommands = (BITCommands.GetMethodInfos(textField.text).ToArray(),index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private async void OnKeyDown(KeyDownEvent keyDownEvent)
|
|
|
|
{
|
|
|
|
switch (keyDownEvent.keyCode)
|
|
|
|
{
|
|
|
|
case KeyCode.Return:
|
|
|
|
var cmd = textField.text;
|
|
|
|
|
|
|
|
LogCallback($">{cmd}", string.Empty, LogType.Log);
|
|
|
|
|
|
|
|
textField.SetValueWithoutNotify(string.Empty);
|
|
|
|
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
|
|
|
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
|
|
|
|
|
|
|
|
|
|
|
textField.Blur();
|
|
|
|
|
|
|
|
textField.Focus();
|
|
|
|
|
|
|
|
BITCommands.Excute(cmd);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case KeyCode.Tab:
|
|
|
|
break;
|
|
|
|
case KeyCode.DownArrow when string.IsNullOrEmpty(textField.text) is false:
|
|
|
|
textField.cursorIndex -= 1;
|
|
|
|
break;
|
|
|
|
case KeyCode.UpArrow when string.IsNullOrEmpty(textField.text) is false:
|
|
|
|
textField.cursorIndex += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Toggle(InputAction.CallbackContext context)
|
|
|
|
{
|
|
|
|
switch (context)
|
|
|
|
{
|
|
|
|
case { interaction: PressInteraction, performed: true }:
|
|
|
|
Toggle(!isActived);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private async void LogCallback(string condition, string stackTrace, LogType type)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case LogType.Error:
|
|
|
|
outputString.Add($"<color=red>{condition}</color>");
|
|
|
|
break;
|
|
|
|
case LogType.Warning:
|
|
|
|
outputString.Add($"<color=yellow>{condition}</color>");
|
|
|
|
break;
|
|
|
|
case LogType.Exception:
|
|
|
|
outputString.Add($"<color=red>{condition}</color>");
|
|
|
|
outputString.Add($"<color=red>{stackTrace}</color>");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
outputString.Add(condition);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
var length = outputString.Count;
|
|
|
|
if (length > logLineLimit)
|
|
|
|
{
|
|
|
|
outputString = outputString.GetRange(length - logLineLimit, logLineLimit);
|
|
|
|
}
|
|
|
|
StringBuilder stringBuilder = new();
|
|
|
|
outputString.ForEach(x => stringBuilder.AppendLine(x));
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await BITApp.SwitchToMainThread();
|
|
|
|
scrollView.ScrollToBottomAutomatic();
|
|
|
|
text.text = stringBuilder.ToString();
|
|
|
|
|
|
|
|
}
|
|
|
|
catch (OperationCanceledException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
Debug.LogException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
{
|
|
|
|
var pos = textField.worldTransform.GetPosition();
|
|
|
|
var size = textField.layout.size;
|
|
|
|
|
|
|
|
commandListView.style.left = 0;
|
|
|
|
commandListView.style.top = 0;
|
|
|
|
|
|
|
|
pos.y += size.y;
|
|
|
|
commandListView.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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|