Net.Like.Xue.Tokyo/Assets/Plugins/MonKey Commander/Editor/MonKey/Commands/Parameters/ParametricCommandExecution.cs

630 lines
21 KiB
C#
Raw Normal View History

2024-11-03 16:42:23 +08:00
#if UNITY_EDITOR
using MonKey.Editor.Console;
using MonKey.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace MonKey.Editor.Internal
{
internal class ParametricCommandExecution
{
public CommandInfo Info;
private int currentArrayIDEdited = -1;
private readonly List<object> valuesParsed;
private readonly List<List<string>> arrayTextEntered;
private readonly List<List<object>> arrayValuesParsed;
public int LastParameterCompleted { get; private set; } = -1;
public bool HasNextVariable => CurrentParameterID + 1 < Info.CommandParameterInfo.Count;
private CommandParameterInterpreter currentInterpreter;
public object GetValueParsed(int index)
{
if (valuesParsed.Count > index && index >= 0)
{
return valuesParsed[index];
}
return null;
}
public string GetFormattedCurrentlyChosen()
{
if (!IsArray)
{
return CurrentTextEntered;
}
string[] split = CurrentTextEntered.Split(',');
if (split.Length > 0)
{
return split.Last();
}
return "";
}
public List<string> TextEntered { get; }
public CommandParameterInfo CurrentParameterInfo => (CurrentParameterID == -1) ? null :
Info.CommandParameterInfo[CurrentParameterID];
public string CurrentTextEntered { get; private set; }
public int CurrentParameterID { get; private set; } = -1;
public GenericCommandParameterAutoComplete CurrentAutoComplete { get; private set; }
internal ParametricCommandExecution(CommandInfo info, CommandConsoleWindow window)
{
Info = info;
TextEntered = new List<string>(info.CommandParameterInfo.Count);
valuesParsed = new List<object>(info.CommandParameterInfo.Count);
arrayValuesParsed = new List<List<object>>();
arrayTextEntered = new List<List<string>>();
foreach (var t in info.CommandParameterInfo)
{
TextEntered.Add("");
valuesParsed.Add(null);
arrayValuesParsed.Add(t.IsArray ?
new List<object>() : null);
arrayTextEntered.Add(t.IsArray ?
new List<string>() : null);
}
}
public bool IsParameterArray(int id)
{
return Info.CommandParameterInfo[id].IsArray;
}
public bool IsParameterEdited(int id)
{
return CurrentParameterID == id;
}
public bool IsParameterEntered(int id)
{
return id <= LastParameterCompleted;
}
public bool IsParameterDefault(int id)
{
return IsParameterEntered(id) && TextEntered[id] == "";
}
public bool IsParameterError(int id)
{
if (!IsParameterEntered(id))
{
return false;
}
if (Info.CommandParameterInfo[id].IsArray)
{
return arrayTextEntered[id].Count > 0
&& arrayValuesParsed[id].Contains(null);
}
return (TextEntered[id] != "" ||
Info.CommandParameterInfo[id].PreventDefaultValueUsage)
&& valuesParsed[id] == null;
}
public bool IsAutoCompleteSuggestions => CurrentAutoComplete != null
&& CurrentAutoComplete.Count > 0;
public List<string> CurrentArrayTextEntered { get; private set; }
public int CurrentArrayIDEdited => currentArrayIDEdited;
public bool IsArray => CurrentParameterID != -1 && CurrentParameterInfo.IsArray;
public List<object> CurrentArrayValuesParsed { get; private set; }
public int CurrentAutoCompleteID { get; private set; } = -1;
internal bool ExecuteCommand(CommandConsoleWindow window)
{
ComputeCurrentParameterValue(window);
CurrentParameterID = -1;
window.SearchTerms = "";
CurrentTextEntered = "";
List<object> finalObjects = new List<object>(valuesParsed.Count);
for (int i = 0; i < valuesParsed.Count; i++)
{
if (IsParameterError(i))
{
CurrentParameterID = i;
PrepareParameterEdition();
return false;
}
if (!IsParameterEntered(i))
{
CurrentTextEntered = "";
CurrentParameterID = i;
CurrentAutoCompleteID = -1;
ComputeCurrentParameterValue(window);
}
finalObjects.Add(valuesParsed[i]);
}
Info.ExecuteCommand(finalObjects.ToArray());
return true;
}
public void NotifyFewInputs(string[] inputs, CommandConsoleWindow window)
{
for (var i = 0; i < inputs.Length; i++)
{
var input = inputs[i];
NotifyNewInput(input, window);
if (IsArray || i < inputs.Length - 1)
{
NotifyNextVariable(window);
}
if (!IsArray)
{
window.SearchTerms = inputs[i];
}
}
}
public void NotifyNewInput(string newInput, CommandConsoleWindow window)
{
if (newInput.IsNullOrEmpty())
{
CurrentTextEntered = "";
CurrentAutoComplete?.InitializeAutoComplete();
}
else
{
AddNewArraySlotIfNeeded();
}
CurrentTextEntered = newInput;
CurrentAutoCompleteID = -1;
RegenerateAutoComplete();
if (CurrentAutoComplete != null
&& (CurrentAutoCompleteID > CurrentAutoComplete.Count ||
CurrentAutoCompleteID == -1))
{
if (!newInput.IsNullOrEmpty() && CurrentAutoComplete.Count > 0
&& Info.CommandParameterInfo[CurrentParameterID].ForceAutoCompleteUsage)
{
CurrentAutoCompleteID = 0;
window.SelectedIndex = CurrentAutoCompleteID;
}
else
{
CurrentAutoCompleteID = -1;
window.SelectedIndex = CurrentAutoCompleteID;
}
}
window.Repaint();
}
private void AddNewArraySlotIfNeeded()
{
if (IsArray && (CurrentArrayIDEdited == -1
|| CurrentArrayIDEdited >= CurrentArrayTextEntered.Count))
{
if (CurrentArrayIDEdited == -1)
{
currentArrayIDEdited = 0;
}
CurrentArrayTextEntered.Add("");
CurrentArrayValuesParsed.Add(null);
}
}
public void NotifyInputFromAutoComplete(int newInputID)
{
if (CurrentAutoComplete == null
|| newInputID >= CurrentAutoComplete.Count)
{
return;
}
CurrentAutoCompleteID = newInputID;
CurrentTextEntered = "";
}
public void NotifyNextVariable(CommandConsoleWindow window)
{
if (IsArray)
{
if (!CurrentTextEntered.IsNullOrEmpty() || CurrentAutoCompleteID != -1)
{
AddNewArraySlotIfNeeded();
JumpToArrayID(window, currentArrayIDEdited + 1);
return;
}
}
if (CurrentParameterID != -1)
{
ComputeCurrentParameterValue(window);
}
if (HasNextVariable)
{
CurrentParameterID++;
}
else
{
window.TryExecuteCurrentParametricCommand();
return;
}
PrepareParameterEdition();
window.SelectedIndex = CurrentAutoCompleteID;
window.TabFrames = 10;
window.Repaint();
}
public void JumpToArrayID(CommandConsoleWindow window, int id)
{
if (IsArray)
{
ComputeCurrentArrayVariable(window);
currentArrayIDEdited = id;
CurrentTextEntered = CurrentArrayTextEntered.Count > CurrentArrayIDEdited ?
CurrentArrayTextEntered[CurrentArrayIDEdited] : "";
//TODO add this as a option (has pros and cons)
// currentAutoComplete.InitializeAutoComplete();
window.SelectedIndex = -1;
window.SearchTerms = CurrentTextEntered;
NotifyNewInput(CurrentTextEntered, window);
window.Repaint();
window.Focus();
window.TabFrames = 10;
}
}
public void NotifyPreviousVariable(CommandConsoleWindow window)
{
if (IsArray && CurrentArrayIDEdited > 0)
{
JumpToArrayID(window, CurrentArrayIDEdited - 1);
return;
}
if (CurrentParameterID <= 0)
{
return;
}
ComputeCurrentParameterValue(window);
LastParameterCompleted = Mathf.Max(CurrentParameterID, LastParameterCompleted);
CurrentParameterID--;
PrepareParameterEdition();
window.SelectedIndex = CurrentAutoCompleteID;
window.TabFrames = 10;
window.Repaint();
}
public void JumpToFirstError(CommandConsoleWindow window)
{
for (int i = 0; i < valuesParsed.Count; i++)
{
if (IsParameterError(i))
{
CurrentParameterID = i;
PrepareParameterEdition();
window.Focus();
window.TabFrames = 10;
window.Repaint();
break;
}
}
}
public void JumpToID(int id)
{
ComputeCurrentParameterValue(CommandConsoleWindow.CurrentPanel);
CurrentParameterID = id;
PrepareParameterEdition();
}
private void PrepareParameterEdition()
{
CommandParameterInfo paramInfo = Info.CommandParameterInfo[CurrentParameterID];
currentInterpreter = CommandParameterInterpreter.
GetInterpreter(paramInfo.ParameterType);
CurrentTextEntered = TextEntered[CurrentParameterID];
CurrentAutoComplete = paramInfo.HasAutoComplete
? paramInfo.AutoComplete
: AutoCompleteManager.GetDefaultAutoComplete(IsArray ?
paramInfo.ParameterType.GetElementType() :
paramInfo.ParameterType);
CurrentAutoComplete?.InitializeAutoComplete();
CurrentAutoCompleteID = -1;
if (!CurrentParameterInfo.PreventDefaultValueUsage && CurrentParameterInfo.HadDefaultValue && CurrentAutoComplete != null)
{
if (CurrentAutoComplete.Count == 0)
{
CurrentAutoComplete.GenerateAndSortAutoComplete("");
}
for (int i = 0; i < CurrentAutoComplete.Count; i++)
{
if (CurrentAutoComplete.GetValue(i).Equals(CurrentParameterInfo.DefaultValue))
// if (CurrentAutoComplete.GetValue(i).ToString() == CurrentParameterInfo.DefaultValue.ToString())
{
CurrentAutoCompleteID = i;
break;
}
}
}
if (IsArray)
{
CurrentArrayTextEntered = arrayTextEntered[CurrentParameterID];
CurrentArrayValuesParsed = arrayValuesParsed[CurrentParameterID];
currentArrayIDEdited = CurrentArrayTextEntered.Count - 1;
if (CurrentArrayIDEdited >= 0)
{
CurrentTextEntered = CurrentArrayTextEntered[CurrentArrayIDEdited];
}
}
else
{
CurrentTextEntered = TextEntered[CurrentParameterID];
}
if (!CurrentTextEntered.IsNullOrEmpty())
{
RegenerateAutoComplete();
}
else
{
CurrentAutoComplete?.InitializeAutoComplete();
}
CommandConsoleWindow.CurrentPanel.SearchTerms = CurrentTextEntered;
CommandConsoleWindow.CurrentPanel.PreviousSearchTerms = CurrentTextEntered;
}
private void RegenerateAutoComplete()
{
CurrentAutoComplete?.GenerateAndSortAutoComplete(CurrentTextEntered);
}
private void ComputeCurrentParameterValue(CommandConsoleWindow window)
{
if (CurrentParameterID == -1)
{
return;
}
LastParameterCompleted = CurrentParameterID;
if (!IsArray)
{
TextEntered[CurrentParameterID] = CurrentTextEntered;
object parsedObject = null;
if (!CurrentParameterInfo.PreventDefaultValueUsage
&& CurrentTextEntered.IsNullOrEmpty())
{
parsedObject = CurrentParameterInfo.DefaultValue;
if (CurrentAutoComplete != null)
{
if ((CurrentAutoCompleteID == -1 || CurrentAutoCompleteID >= CurrentAutoComplete.Count)&& CurrentParameterInfo.ForceAutoCompleteUsage)
{
for (int i = 0; i < CurrentAutoComplete.Count; i++)
{
if (CurrentAutoComplete.GetValue(i) != null
&& CurrentAutoComplete.GetValue(i).ToString() == parsedObject.ToString())
{
CurrentAutoCompleteID = i;
break;
}
}
}
if (CurrentAutoCompleteID != -1 && CurrentAutoCompleteID < CurrentAutoComplete.Count)
parsedObject = CurrentAutoComplete.GetValue(CurrentAutoCompleteID);
}
}
else
{
if (!Info.CommandParameterInfo[CurrentParameterID].ForceAutoCompleteUsage)
{
currentInterpreter.TryParse(CurrentTextEntered, out parsedObject);
}
if (IsAutoCompleteSuggestions
&& parsedObject == null
&& (Info.CommandParameterInfo[CurrentParameterID].ForceAutoCompleteUsage
|| CurrentAutoCompleteID != -1))
{
if (CurrentAutoCompleteID == -1)
{
CurrentAutoCompleteID = 0;
}
if (CurrentAutoComplete != null)
{
if (CurrentAutoComplete.Count <= CurrentAutoCompleteID)
CurrentAutoComplete.GenerateAndSortAutoComplete(CurrentTextEntered);
parsedObject = CurrentAutoComplete.GetValue(CurrentAutoCompleteID);
TextEntered[CurrentParameterID] =
CurrentAutoComplete.GetStringValue(CurrentAutoCompleteID);
}
else
{
parsedObject = CurrentParameterInfo.DefaultValue;
}
}
}
if (parsedObject == null)
{
valuesParsed[CurrentParameterID] = TextEntered[CurrentParameterID]
.IsNullOrEmpty() && !CurrentParameterInfo.PreventDefaultValueUsage
? Info.CommandParameterInfo[CurrentParameterID].DefaultValue
: null;
}
else
{
valuesParsed[CurrentParameterID] = parsedObject;
}
}
else
{
ComputeCurrentArrayVariable(window);
if (CurrentArrayValuesParsed != null && CurrentArrayValuesParsed.Count > 0)
{
if (!CurrentArrayValuesParsed.Contains(null))
{
Type elemType = CurrentParameterInfo.ParameterType.GetElementType();
if (elemType != null)
{
var obj = Array.CreateInstance(elemType,
CurrentArrayValuesParsed.Count);
for (int i = 0; i < CurrentArrayValuesParsed.Count; i++)
{
obj.SetValue(CurrentArrayValuesParsed[i], i);
}
valuesParsed[CurrentParameterID] = obj;
}
else
{
valuesParsed[CurrentParameterID] = null;
}
}
else
{
valuesParsed[CurrentParameterID] = null;
}
arrayValuesParsed[CurrentParameterID] = CurrentArrayValuesParsed;
}
else if (!CurrentParameterInfo.PreventDefaultValueUsage
&& CurrentParameterInfo.DefaultValue != null)
{
valuesParsed[CurrentParameterID] = CurrentParameterInfo.DefaultValue;
Array ar = (Array)
CurrentParameterInfo.DefaultValue;
if (ar != null)
{
List<object> list = new List<object>();
foreach (object o in ar)
{
list.Add(o);
}
arrayValuesParsed[CurrentParameterID] = list;
}
}
else
{
valuesParsed[CurrentParameterID] = null;
arrayValuesParsed[CurrentParameterID] = CurrentArrayValuesParsed;
}
}
}
private void ComputeCurrentArrayVariable(CommandConsoleWindow window)
{
if (currentArrayIDEdited < 0 || currentArrayIDEdited >= CurrentArrayTextEntered.Count)
{
return;
}
//TODO refactor this condition mess
CurrentArrayTextEntered[CurrentArrayIDEdited] = CurrentTextEntered;
object outputObj = null;
if (!Info.CommandParameterInfo[CurrentParameterID].ForceAutoCompleteUsage
&& !CurrentTextEntered.IsNullOrEmpty())
{
currentInterpreter.TryParse(CurrentTextEntered, out outputObj);
}
if ((!CurrentTextEntered.IsNullOrEmpty() || CurrentAutoCompleteID != -1)
&& IsAutoCompleteSuggestions && outputObj == null
&& (Info.CommandParameterInfo[CurrentParameterID].ForceAutoCompleteUsage || CurrentAutoCompleteID != -1))
{
if (CurrentAutoCompleteID == -1)
{
CurrentAutoCompleteID = 0;
}
CurrentArrayValuesParsed[CurrentArrayIDEdited] =
(CurrentAutoComplete.GetValue(CurrentAutoCompleteID));
CurrentArrayTextEntered[CurrentArrayIDEdited] =
CurrentAutoComplete.GetStringValue(CurrentAutoCompleteID);
CurrentAutoComplete.InitializeAutoComplete();
}
else
{
CurrentArrayValuesParsed[CurrentArrayIDEdited] = outputObj;
}
CurrentAutoCompleteID = -1;
CurrentAutoComplete?.InitializeAutoComplete();
window.SelectedIndex = -1;
window.SearchTerms = "";
window.PreviousSearchTerms = "";
window.Repaint();
window.Focus();
}
}
}
#endif