mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-17 16:47:52 +08:00
refactor
This commit is contained in:
@ -1,320 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
#if CPP
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public class AutoCompleter
|
||||
{
|
||||
public static AutoCompleter Instance;
|
||||
|
||||
public const int MAX_LABELS = 500;
|
||||
private const int UPDATES_PER_BATCH = 100;
|
||||
|
||||
public static GameObject m_mainObj;
|
||||
private static RectTransform m_thisRect;
|
||||
|
||||
private static readonly List<GameObject> m_suggestionButtons = new List<GameObject>();
|
||||
private static readonly List<Text> m_suggestionTexts = new List<Text>();
|
||||
private static readonly List<Text> m_hiddenSuggestionTexts = new List<Text>();
|
||||
|
||||
private static bool m_suggestionsDirty;
|
||||
private static Suggestion[] m_suggestions = new Suggestion[0];
|
||||
private static int m_lastBatchIndex;
|
||||
|
||||
private static string m_prevInput = "NULL";
|
||||
private static int m_lastCaretPos;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
ConstructUI();
|
||||
|
||||
m_mainObj.SetActive(false);
|
||||
}
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (!m_mainObj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ConsolePage.EnableSuggestions)
|
||||
{
|
||||
if (m_mainObj.activeSelf)
|
||||
{
|
||||
m_mainObj.SetActive(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshButtons();
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
public static void SetSuggestions(Suggestion[] suggestions)
|
||||
{
|
||||
m_suggestions = suggestions;
|
||||
|
||||
m_suggestionsDirty = true;
|
||||
m_lastBatchIndex = 0;
|
||||
}
|
||||
|
||||
private static void RefreshButtons()
|
||||
{
|
||||
if (!m_suggestionsDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_suggestions.Length < 1)
|
||||
{
|
||||
if (m_mainObj.activeSelf)
|
||||
{
|
||||
m_mainObj?.SetActive(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_mainObj.activeSelf)
|
||||
{
|
||||
m_mainObj.SetActive(true);
|
||||
}
|
||||
|
||||
if (m_suggestions.Length < 1 || m_lastBatchIndex >= MAX_LABELS)
|
||||
{
|
||||
m_suggestionsDirty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int end = m_lastBatchIndex + UPDATES_PER_BATCH;
|
||||
for (int i = m_lastBatchIndex; i < end && i < MAX_LABELS; i++)
|
||||
{
|
||||
if (i >= m_suggestions.Length)
|
||||
{
|
||||
if (m_suggestionButtons[i].activeSelf)
|
||||
{
|
||||
m_suggestionButtons[i].SetActive(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_suggestionButtons[i].activeSelf)
|
||||
{
|
||||
m_suggestionButtons[i].SetActive(true);
|
||||
}
|
||||
|
||||
var suggestion = m_suggestions[i];
|
||||
var label = m_suggestionTexts[i];
|
||||
var hiddenLabel = m_hiddenSuggestionTexts[i];
|
||||
|
||||
label.text = suggestion.Full;
|
||||
hiddenLabel.text = suggestion.Addition;
|
||||
|
||||
label.color = suggestion.TextColor;
|
||||
}
|
||||
|
||||
m_lastBatchIndex = i;
|
||||
}
|
||||
|
||||
m_lastBatchIndex++;
|
||||
}
|
||||
|
||||
private static void UpdatePosition()
|
||||
{
|
||||
var editor = ConsolePage.Instance.m_codeEditor;
|
||||
|
||||
if (editor.InputField.text.Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int caretPos = editor.InputField.caretPosition;
|
||||
while (caretPos >= editor.inputText.textInfo.characterInfo.Length)
|
||||
{
|
||||
caretPos--;
|
||||
}
|
||||
|
||||
if (caretPos == m_lastCaretPos)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_lastCaretPos = caretPos;
|
||||
|
||||
if (caretPos >= 0 && caretPos < editor.inputText.textInfo.characterInfo.Length)
|
||||
{
|
||||
var pos = editor.inputText.textInfo.characterInfo[caretPos].bottomLeft;
|
||||
|
||||
pos = editor.InputField.transform.TransformPoint(pos);
|
||||
|
||||
m_mainObj.transform.position = new Vector3(pos.x, pos.y - 3, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly char[] splitChars = new[] { '{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?' };
|
||||
|
||||
public static void CheckAutocomplete()
|
||||
{
|
||||
var m_codeEditor = ConsolePage.Instance.m_codeEditor;
|
||||
string input = m_codeEditor.InputField.text;
|
||||
int caretIndex = m_codeEditor.InputField.caretPosition;
|
||||
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
{
|
||||
try
|
||||
{
|
||||
int start = caretIndex <= 0 ? 0 : input.LastIndexOfAny(splitChars, caretIndex - 1) + 1;
|
||||
input = input.Substring(start, caretIndex - start).Trim();
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(input) && input != m_prevInput)
|
||||
{
|
||||
GetAutocompletes(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearAutocompletes();
|
||||
}
|
||||
|
||||
m_prevInput = input;
|
||||
}
|
||||
|
||||
public static void ClearAutocompletes()
|
||||
{
|
||||
if (ConsolePage.AutoCompletes.Any())
|
||||
{
|
||||
ConsolePage.AutoCompletes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetAutocompletes(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Credit ManylMarco
|
||||
ConsolePage.AutoCompletes.Clear();
|
||||
string[] completions = ConsolePage.Instance.m_evaluator.GetCompletions(input, out string prefix);
|
||||
if (completions != null)
|
||||
{
|
||||
if (prefix == null)
|
||||
{
|
||||
prefix = input;
|
||||
}
|
||||
|
||||
ConsolePage.AutoCompletes.AddRange(completions
|
||||
.Where(x => !string.IsNullOrEmpty(x))
|
||||
.Select(x => new Suggestion(x, prefix, Suggestion.Contexts.Other))
|
||||
);
|
||||
}
|
||||
|
||||
string trimmed = input.Trim();
|
||||
if (trimmed.StartsWith("using"))
|
||||
{
|
||||
trimmed = trimmed.Remove(0, 5).Trim();
|
||||
}
|
||||
|
||||
IEnumerable<Suggestion> namespaces = Suggestion.Namespaces
|
||||
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
|
||||
.Select(x => new Suggestion(
|
||||
x.Substring(trimmed.Length),
|
||||
x.Substring(0, trimmed.Length),
|
||||
Suggestion.Contexts.Namespace));
|
||||
|
||||
ConsolePage.AutoCompletes.AddRange(namespaces);
|
||||
|
||||
IEnumerable<Suggestion> keywords = Suggestion.Keywords
|
||||
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
|
||||
.Select(x => new Suggestion(
|
||||
x.Substring(trimmed.Length),
|
||||
x.Substring(0, trimmed.Length),
|
||||
Suggestion.Contexts.Keyword));
|
||||
|
||||
ConsolePage.AutoCompletes.AddRange(keywords);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.Log("Autocomplete error:\r\n" + ex.ToString());
|
||||
ClearAutocompletes();
|
||||
}
|
||||
}
|
||||
|
||||
#region UI Construction
|
||||
|
||||
private static void ConstructUI()
|
||||
{
|
||||
var parent = UIManager.CanvasRoot;
|
||||
|
||||
var obj = UIFactory.CreateScrollView(parent, out GameObject content, new Color(0.1f, 0.1f, 0.1f, 0.95f));
|
||||
|
||||
m_mainObj = obj;
|
||||
|
||||
var mainRect = obj.GetComponent<RectTransform>();
|
||||
m_thisRect = mainRect;
|
||||
mainRect.pivot = new Vector2(0f, 1f);
|
||||
mainRect.anchorMin = new Vector2(0.45f, 0.45f);
|
||||
mainRect.anchorMax = new Vector2(0.65f, 0.6f);
|
||||
mainRect.offsetMin = Vector2.zero;
|
||||
mainRect.offsetMax = Vector2.zero;
|
||||
|
||||
var mainGroup = content.GetComponent<VerticalLayoutGroup>();
|
||||
mainGroup.childControlHeight = false;
|
||||
mainGroup.childControlWidth = true;
|
||||
mainGroup.childForceExpandHeight = false;
|
||||
mainGroup.childForceExpandWidth = true;
|
||||
|
||||
for (int i = 0; i < MAX_LABELS; i++)
|
||||
{
|
||||
var buttonObj = UIFactory.CreateButton(content);
|
||||
Button btn = buttonObj.GetComponent<Button>();
|
||||
ColorBlock btnColors = btn.colors;
|
||||
btnColors.normalColor = new Color(0f, 0f, 0f, 0f);
|
||||
btnColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
btn.colors = btnColors;
|
||||
|
||||
var nav = btn.navigation;
|
||||
nav.mode = Navigation.Mode.Vertical;
|
||||
btn.navigation = nav;
|
||||
|
||||
var btnLayout = buttonObj.AddComponent<LayoutElement>();
|
||||
btnLayout.minHeight = 20;
|
||||
|
||||
var text = btn.GetComponentInChildren<Text>();
|
||||
text.alignment = TextAnchor.MiddleLeft;
|
||||
text.color = Color.white;
|
||||
|
||||
var hiddenChild = UIFactory.CreateUIObject("HiddenText", buttonObj);
|
||||
hiddenChild.SetActive(false);
|
||||
var hiddenText = hiddenChild.AddComponent<Text>();
|
||||
m_hiddenSuggestionTexts.Add(hiddenText);
|
||||
|
||||
#if CPP
|
||||
btn.onClick.AddListener(new Action(UseAutocompleteButton));
|
||||
#else
|
||||
btn.onClick.AddListener(UseAutocompleteButton);
|
||||
#endif
|
||||
|
||||
void UseAutocompleteButton()
|
||||
{
|
||||
ConsolePage.Instance.UseAutocomplete(hiddenText.text);
|
||||
EventSystem.current.SetSelectedGameObject(ConsolePage.Instance.m_codeEditor.InputField.gameObject,
|
||||
null);
|
||||
}
|
||||
|
||||
m_suggestionButtons.Add(buttonObj);
|
||||
m_suggestionTexts.Add(text);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Main.Console.Lexer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public static class CSharpLexer
|
||||
{
|
||||
public static char indentIncreaseCharacter = '{';
|
||||
public static char indentDecreaseCharacter = '}';
|
||||
|
||||
public static string delimiterSymbols = "[ ] ( ) { } ; : , .";
|
||||
|
||||
private static readonly StringBuilder indentBuilder = new StringBuilder();
|
||||
|
||||
public static CommentMatch commentMatcher = new CommentMatch();
|
||||
public static SymbolMatch symbolMatcher = new SymbolMatch();
|
||||
public static NumberMatch numberMatcher = new NumberMatch();
|
||||
public static StringMatch stringMatcher = new StringMatch();
|
||||
|
||||
public static KeywordMatch validKeywordMatcher = new KeywordMatch
|
||||
{
|
||||
highlightColor = new Color(0.33f, 0.61f, 0.83f, 1.0f),
|
||||
keywords = @"add as ascending await bool break by byte
|
||||
case catch char checked const continue decimal default descending do dynamic
|
||||
else equals false finally float for foreach from global goto group
|
||||
if in int into is join let lock long new null object on orderby out
|
||||
ref remove return sbyte select short sizeof stackalloc string
|
||||
switch throw true try typeof uint ulong ushort
|
||||
var where while yield"
|
||||
};
|
||||
|
||||
public static KeywordMatch invalidKeywordMatcher = new KeywordMatch()
|
||||
{
|
||||
highlightColor = new Color(0.95f, 0.10f, 0.10f, 1.0f),
|
||||
keywords = @"abstract async base class delegate enum explicit extern fixed get
|
||||
implicit interface internal namespace operator override params private protected public
|
||||
using partial readonly sealed set static struct this unchecked unsafe value virtual volatile void"
|
||||
};
|
||||
|
||||
private static char[] delimiterSymbolCache = null;
|
||||
internal static char[] DelimiterSymbols
|
||||
{
|
||||
get
|
||||
{
|
||||
if (delimiterSymbolCache == null)
|
||||
{
|
||||
string[] symbols = delimiterSymbols.Split(' ');
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < symbols.Length; i++)
|
||||
{
|
||||
if (symbols[i].Length == 1)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
delimiterSymbolCache = new char[count];
|
||||
|
||||
for (int i = 0, index = 0; i < symbols.Length; i++)
|
||||
{
|
||||
if (symbols[i].Length == 1)
|
||||
{
|
||||
delimiterSymbolCache[index] = symbols[i][0];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return delimiterSymbolCache;
|
||||
}
|
||||
}
|
||||
|
||||
private static Matcher[] matchers = null;
|
||||
internal static Matcher[] Matchers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (matchers == null)
|
||||
{
|
||||
List<Matcher> matcherList = new List<Matcher>
|
||||
{
|
||||
commentMatcher,
|
||||
symbolMatcher,
|
||||
numberMatcher,
|
||||
stringMatcher,
|
||||
validKeywordMatcher,
|
||||
invalidKeywordMatcher,
|
||||
};
|
||||
|
||||
matchers = matcherList.ToArray();
|
||||
}
|
||||
return matchers;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetIndentForInput(string input, int indent, out int caretPosition)
|
||||
{
|
||||
indentBuilder.Clear();
|
||||
|
||||
indent += 1;
|
||||
|
||||
bool stringState = false;
|
||||
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (input[i] == '"')
|
||||
{
|
||||
stringState = !stringState;
|
||||
}
|
||||
|
||||
if (input[i] == '\n')
|
||||
{
|
||||
indentBuilder.Append('\n');
|
||||
for (int j = 0; j < indent; j++)
|
||||
{
|
||||
indentBuilder.Append("\t");
|
||||
}
|
||||
}
|
||||
else if (input[i] == '\t')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (!stringState && input[i] == indentIncreaseCharacter)
|
||||
{
|
||||
indentBuilder.Append(indentIncreaseCharacter);
|
||||
indent++;
|
||||
}
|
||||
else if (!stringState && input[i] == indentDecreaseCharacter)
|
||||
{
|
||||
indentBuilder.Append(indentDecreaseCharacter);
|
||||
indent--;
|
||||
}
|
||||
else
|
||||
{
|
||||
indentBuilder.Append(input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
string formattedSection = indentBuilder.ToString();
|
||||
|
||||
caretPosition = formattedSection.Length - 1;
|
||||
|
||||
for (int i = formattedSection.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (formattedSection[i] == '\n')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
caretPosition = i;
|
||||
break;
|
||||
}
|
||||
|
||||
return formattedSection;
|
||||
}
|
||||
|
||||
public static int GetIndentLevel(string inputString, int startIndex, int endIndex)
|
||||
{
|
||||
int indent = 0;
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
if (inputString[i] == '\t')
|
||||
{
|
||||
indent++;
|
||||
}
|
||||
|
||||
// Check for end line or other characters
|
||||
if (inputString[i] == '\n' || inputString[i] != ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,441 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.Input;
|
||||
using UnityExplorer.UI.Main.Console.Lexer;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public class CodeEditor
|
||||
{
|
||||
private readonly InputLexer inputLexer = new InputLexer();
|
||||
|
||||
public TMP_InputField InputField { get; }
|
||||
|
||||
public readonly TextMeshProUGUI inputText;
|
||||
private readonly TextMeshProUGUI inputHighlightText;
|
||||
private readonly TextMeshProUGUI lineText;
|
||||
private readonly Image background;
|
||||
private readonly Image lineHighlight;
|
||||
private readonly Image lineNumberBackground;
|
||||
private readonly Image scrollbar;
|
||||
|
||||
private bool lineHighlightLocked;
|
||||
private readonly RectTransform inputTextTransform;
|
||||
private readonly RectTransform lineHighlightTransform;
|
||||
|
||||
public int LineCount { get; private set; }
|
||||
public int CurrentLine { get; private set; }
|
||||
public int CurrentColumn { get; private set; }
|
||||
public int CurrentIndent { get; private set; }
|
||||
|
||||
private static readonly StringBuilder highlightedBuilder = new StringBuilder(4096);
|
||||
private static readonly StringBuilder lineBuilder = new StringBuilder();
|
||||
|
||||
private static readonly KeyCode[] lineChangeKeys =
|
||||
{
|
||||
KeyCode.Return, KeyCode.Backspace, KeyCode.UpArrow,
|
||||
KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow
|
||||
};
|
||||
|
||||
public string HighlightedText => inputHighlightText.text;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return InputField.text; }
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
InputField.text = value;
|
||||
inputHighlightText.text = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputField.text = string.Empty;
|
||||
inputHighlightText.text = string.Empty;
|
||||
}
|
||||
|
||||
inputText.ForceMeshUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
public CodeEditor(TMP_InputField inputField, TextMeshProUGUI inputText, TextMeshProUGUI inputHighlightText, TextMeshProUGUI lineText,
|
||||
Image background, Image lineHighlight, Image lineNumberBackground, Image scrollbar)
|
||||
{
|
||||
InputField = inputField;
|
||||
this.inputText = inputText;
|
||||
this.inputHighlightText = inputHighlightText;
|
||||
this.lineText = lineText;
|
||||
this.background = background;
|
||||
this.lineHighlight = lineHighlight;
|
||||
this.lineNumberBackground = lineNumberBackground;
|
||||
this.scrollbar = scrollbar;
|
||||
|
||||
if (!AllReferencesAssigned())
|
||||
{
|
||||
throw new Exception("References are missing!");
|
||||
}
|
||||
|
||||
InputField.restoreOriginalTextOnEscape = false;
|
||||
|
||||
inputTextTransform = inputText.GetComponent<RectTransform>();
|
||||
lineHighlightTransform = lineHighlight.GetComponent<RectTransform>();
|
||||
|
||||
ApplyTheme();
|
||||
inputLexer.UseMatchers(CSharpLexer.DelimiterSymbols, CSharpLexer.Matchers);
|
||||
|
||||
// subscribe to text input changing
|
||||
#if CPP
|
||||
InputField.onValueChanged.AddListener(new Action<string>((string s) => { OnInputChanged(); }));
|
||||
#else
|
||||
this.InputField.onValueChanged.AddListener((string s) => { OnInputChanged(); });
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Check for new line
|
||||
if (ConsolePage.EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return))
|
||||
{
|
||||
AutoIndentCaret();
|
||||
}
|
||||
|
||||
if (EventSystem.current?.currentSelectedGameObject?.name == "InputField (TMP)")
|
||||
{
|
||||
bool focusKeyPressed = false;
|
||||
|
||||
// Check for any focus key pressed
|
||||
foreach (KeyCode key in lineChangeKeys)
|
||||
{
|
||||
if (InputManager.GetKeyDown(key))
|
||||
{
|
||||
focusKeyPressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update line highlight
|
||||
if (focusKeyPressed || InputManager.GetMouseButton(0))
|
||||
{
|
||||
UpdateHighlight();
|
||||
ConsolePage.Instance.OnInputChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInputChanged(bool forceUpdate = false)
|
||||
{
|
||||
string newText = InputField.text;
|
||||
|
||||
UpdateIndent();
|
||||
|
||||
if (!forceUpdate && string.IsNullOrEmpty(newText))
|
||||
{
|
||||
inputHighlightText.text = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
inputHighlightText.text = SyntaxHighlightContent(newText);
|
||||
}
|
||||
|
||||
UpdateLineNumbers();
|
||||
UpdateHighlight();
|
||||
|
||||
ConsolePage.Instance.OnInputChanged();
|
||||
}
|
||||
|
||||
public void SetLineHighlight(int lineNumber, bool lockLineHighlight)
|
||||
{
|
||||
if (lineNumber < 1 || lineNumber > LineCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lineHighlightTransform.anchoredPosition = new Vector2(5,
|
||||
(inputText.textInfo.lineInfo[inputText.textInfo.characterInfo[0].lineNumber].lineHeight *
|
||||
-(lineNumber - 1)) - 4f +
|
||||
inputTextTransform.anchoredPosition.y);
|
||||
|
||||
lineHighlightLocked = lockLineHighlight;
|
||||
}
|
||||
|
||||
private void UpdateLineNumbers()
|
||||
{
|
||||
int currentLineCount = inputText.textInfo.lineCount;
|
||||
|
||||
int currentLineNumber = 1;
|
||||
|
||||
if (currentLineCount != LineCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
lineBuilder.Length = 0;
|
||||
|
||||
for (int i = 1; i < currentLineCount + 2; i++)
|
||||
{
|
||||
if (i - 1 > 0 && i - 1 < currentLineCount - 1)
|
||||
{
|
||||
int characterStart = inputText.textInfo.lineInfo[i - 1].firstCharacterIndex;
|
||||
int characterCount = inputText.textInfo.lineInfo[i - 1].characterCount;
|
||||
|
||||
if (characterStart >= 0 && characterStart < inputText.text.Length &&
|
||||
characterCount != 0 && !inputText.text.Substring(characterStart, characterCount).Contains("\n"))
|
||||
{
|
||||
lineBuilder.Append("\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
lineBuilder.Append(currentLineNumber);
|
||||
lineBuilder.Append('\n');
|
||||
|
||||
currentLineNumber++;
|
||||
|
||||
if (i - 1 == 0 && i - 1 < currentLineCount - 1)
|
||||
{
|
||||
int characterStart = inputText.textInfo.lineInfo[i - 1].firstCharacterIndex;
|
||||
int characterCount = inputText.textInfo.lineInfo[i - 1].characterCount;
|
||||
|
||||
if (characterStart >= 0 && characterStart < inputText.text.Length &&
|
||||
characterCount != 0 && !inputText.text.Substring(characterStart, characterCount).Contains("\n"))
|
||||
{
|
||||
lineBuilder.Append("\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lineText.text = lineBuilder.ToString();
|
||||
LineCount = currentLineCount;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateIndent()
|
||||
{
|
||||
int caret = InputField.caretPosition;
|
||||
|
||||
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Length)
|
||||
{
|
||||
while (caret >= 0 && caret >= inputText.textInfo.characterInfo.Length)
|
||||
{
|
||||
caret--;
|
||||
}
|
||||
|
||||
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CurrentLine = inputText.textInfo.characterInfo[caret].lineNumber;
|
||||
|
||||
int charCount = 0;
|
||||
for (int i = 0; i < CurrentLine; i++)
|
||||
{
|
||||
charCount += inputText.textInfo.lineInfo[i].characterCount;
|
||||
}
|
||||
|
||||
CurrentColumn = caret - charCount;
|
||||
CurrentIndent = 0;
|
||||
|
||||
for (int i = 0; i < caret && i < InputField.text.Length; i++)
|
||||
{
|
||||
char character = InputField.text[i];
|
||||
|
||||
if (character == CSharpLexer.indentIncreaseCharacter)
|
||||
{
|
||||
CurrentIndent++;
|
||||
}
|
||||
|
||||
if (character == CSharpLexer.indentDecreaseCharacter)
|
||||
{
|
||||
CurrentIndent--;
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentIndent < 0)
|
||||
{
|
||||
CurrentIndent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHighlight()
|
||||
{
|
||||
if (lineHighlightLocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int caret = InputField.caretPosition - 1;
|
||||
|
||||
float lineHeight = inputText.textInfo.lineInfo[inputText.textInfo.characterInfo[0].lineNumber].lineHeight;
|
||||
int lineNumber = inputText.textInfo.characterInfo[caret].lineNumber;
|
||||
float offset = lineNumber + inputTextTransform.anchoredPosition.y;
|
||||
|
||||
lineHighlightTransform.anchoredPosition = new Vector2(5, -(offset * lineHeight));
|
||||
}
|
||||
catch //(Exception e)
|
||||
{
|
||||
//ExplorerCore.LogWarning("Exception on Update Line Highlight: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private const string CLOSE_COLOR_TAG = "</color>";
|
||||
|
||||
private string SyntaxHighlightContent(string inputText)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
highlightedBuilder.Length = 0;
|
||||
|
||||
foreach (LexerMatchInfo match in inputLexer.LexInputString(inputText))
|
||||
{
|
||||
for (int i = offset; i < match.startIndex; i++)
|
||||
{
|
||||
highlightedBuilder.Append(inputText[i]);
|
||||
}
|
||||
|
||||
highlightedBuilder.Append(match.htmlColor);
|
||||
|
||||
for (int i = match.startIndex; i < match.endIndex; i++)
|
||||
{
|
||||
highlightedBuilder.Append(inputText[i]);
|
||||
}
|
||||
|
||||
highlightedBuilder.Append(CLOSE_COLOR_TAG);
|
||||
|
||||
offset = match.endIndex;
|
||||
}
|
||||
|
||||
for (int i = offset; i < inputText.Length; i++)
|
||||
{
|
||||
highlightedBuilder.Append(inputText[i]);
|
||||
}
|
||||
|
||||
inputText = highlightedBuilder.ToString();
|
||||
|
||||
return inputText;
|
||||
}
|
||||
|
||||
private void AutoIndentCaret()
|
||||
{
|
||||
if (CurrentIndent > 0)
|
||||
{
|
||||
string indent = GetAutoIndentTab(CurrentIndent);
|
||||
|
||||
if (indent.Length > 0)
|
||||
{
|
||||
int caretPos = InputField.caretPosition;
|
||||
|
||||
string indentMinusOne = indent.Substring(0, indent.Length - 1);
|
||||
|
||||
// get last index of {
|
||||
// chuck it on the next line if its not already
|
||||
string text = InputField.text;
|
||||
string sub = InputField.text.Substring(0, InputField.caretPosition);
|
||||
int lastIndex = sub.LastIndexOf("{");
|
||||
int offset = lastIndex - 1;
|
||||
if (offset >= 0 && text[offset] != '\n' && text[offset] != '\t')
|
||||
{
|
||||
string open = "\n" + indentMinusOne;
|
||||
|
||||
InputField.text = text.Insert(offset + 1, open);
|
||||
|
||||
caretPos += open.Length;
|
||||
}
|
||||
|
||||
// check if should add auto-close }
|
||||
int numOpen = InputField.text.Where(x => x == CSharpLexer.indentIncreaseCharacter).Count();
|
||||
int numClose = InputField.text.Where(x => x == CSharpLexer.indentDecreaseCharacter).Count();
|
||||
|
||||
if (numOpen > numClose)
|
||||
{
|
||||
// add auto-indent closing
|
||||
indentMinusOne = $"\n{indentMinusOne}}}";
|
||||
InputField.text = InputField.text.Insert(caretPos, indentMinusOne);
|
||||
}
|
||||
|
||||
// insert the actual auto indent now
|
||||
InputField.text = InputField.text.Insert(caretPos, indent);
|
||||
|
||||
InputField.stringPosition = caretPos + indent.Length;
|
||||
}
|
||||
}
|
||||
|
||||
// Update line column and indent positions
|
||||
UpdateIndent();
|
||||
|
||||
inputText.text = InputField.text;
|
||||
inputText.SetText(InputField.text, true);
|
||||
inputText.Rebuild(CanvasUpdate.Prelayout);
|
||||
InputField.ForceLabelUpdate();
|
||||
InputField.Rebuild(CanvasUpdate.Prelayout);
|
||||
|
||||
OnInputChanged(true);
|
||||
}
|
||||
|
||||
private string GetAutoIndentTab(int amount)
|
||||
{
|
||||
string tab = string.Empty;
|
||||
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
tab += "\t";
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
private static Color caretColor = new Color32(255, 255, 255, 255);
|
||||
private static Color textColor = new Color32(255, 255, 255, 255);
|
||||
private static Color backgroundColor = new Color32(37, 37, 37, 255);
|
||||
private static Color lineHighlightColor = new Color32(50, 50, 50, 255);
|
||||
private static Color lineNumberBackgroundColor = new Color32(25, 25, 25, 255);
|
||||
private static Color lineNumberTextColor = new Color32(180, 180, 180, 255);
|
||||
private static Color scrollbarColor = new Color32(45, 50, 50, 255);
|
||||
|
||||
private void ApplyTheme()
|
||||
{
|
||||
var highlightTextRect = inputHighlightText.GetComponent<RectTransform>();
|
||||
highlightTextRect.anchorMin = Vector2.zero;
|
||||
highlightTextRect.anchorMax = Vector2.one;
|
||||
highlightTextRect.offsetMin = Vector2.zero;
|
||||
highlightTextRect.offsetMax = Vector2.zero;
|
||||
|
||||
InputField.caretColor = caretColor;
|
||||
inputText.color = textColor;
|
||||
inputHighlightText.color = textColor;
|
||||
background.color = backgroundColor;
|
||||
lineHighlight.color = lineHighlightColor;
|
||||
lineNumberBackground.color = lineNumberBackgroundColor;
|
||||
lineText.color = lineNumberTextColor;
|
||||
scrollbar.color = scrollbarColor;
|
||||
}
|
||||
|
||||
private bool AllReferencesAssigned()
|
||||
{
|
||||
if (!InputField ||
|
||||
!inputText ||
|
||||
!inputHighlightText ||
|
||||
!lineText ||
|
||||
!background ||
|
||||
!lineHighlight ||
|
||||
!lineNumberBackground ||
|
||||
!scrollbar)
|
||||
{
|
||||
// One or more references are not assigned
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public sealed class CommentMatch : Matcher
|
||||
{
|
||||
public string lineCommentStart = @"//";
|
||||
public string blockCommentStart = @"/*";
|
||||
public string blockCommentEnd = @"*/";
|
||||
|
||||
public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
||||
public override IEnumerable<char> StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] };
|
||||
public override IEnumerable<char> EndChars => new char[] { blockCommentEnd[0] };
|
||||
public override bool IsImplicitMatch(InputLexer lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart);
|
||||
|
||||
private bool IsMatch(InputLexer lexer, string commentType)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(commentType))
|
||||
{
|
||||
lexer.Rollback();
|
||||
|
||||
bool match = true;
|
||||
for (int i = 0; i < commentType.Length; i++)
|
||||
{
|
||||
if (commentType[i] != lexer.ReadNext())
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
// Read until end
|
||||
while (!IsEndLineOrEndFile(lexer, lexer.ReadNext()))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsEndLineOrEndFile(InputLexer lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r';
|
||||
}
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public struct LexerMatchInfo
|
||||
{
|
||||
public int startIndex;
|
||||
public int endIndex;
|
||||
public string htmlColor;
|
||||
}
|
||||
|
||||
public enum SpecialCharacterPosition
|
||||
{
|
||||
Start,
|
||||
End,
|
||||
};
|
||||
|
||||
public class InputLexer
|
||||
{
|
||||
private string inputString = null;
|
||||
private Matcher[] matchers = null;
|
||||
private readonly HashSet<char> specialStartSymbols = new HashSet<char>();
|
||||
private readonly HashSet<char> specialEndSymbols = new HashSet<char>();
|
||||
private int currentIndex = 0;
|
||||
private int currentLookaheadIndex = 0;
|
||||
|
||||
private char current = ' ';
|
||||
public char Previous { get; private set; } = ' ';
|
||||
|
||||
public bool EndOfStream
|
||||
{
|
||||
get { return currentLookaheadIndex >= inputString.Length; }
|
||||
}
|
||||
|
||||
public void UseMatchers(char[] delimiters, Matcher[] matchers)
|
||||
{
|
||||
this.matchers = matchers;
|
||||
|
||||
specialStartSymbols.Clear();
|
||||
specialEndSymbols.Clear();
|
||||
|
||||
if (delimiters != null)
|
||||
{
|
||||
foreach (char character in delimiters)
|
||||
{
|
||||
if (!specialStartSymbols.Contains(character))
|
||||
{
|
||||
specialStartSymbols.Add(character);
|
||||
}
|
||||
|
||||
if (!specialEndSymbols.Contains(character))
|
||||
{
|
||||
specialEndSymbols.Add(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchers != null)
|
||||
{
|
||||
foreach (Matcher lexer in matchers)
|
||||
{
|
||||
foreach (char special in lexer.StartChars)
|
||||
{
|
||||
if (!specialStartSymbols.Contains(special))
|
||||
{
|
||||
specialStartSymbols.Add(special);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (char special in lexer.EndChars)
|
||||
{
|
||||
if (!specialEndSymbols.Contains(special))
|
||||
{
|
||||
specialEndSymbols.Add(special);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<LexerMatchInfo> LexInputString(string input)
|
||||
{
|
||||
if (input == null || matchers == null || matchers.Length == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
inputString = input;
|
||||
current = ' ';
|
||||
Previous = ' ';
|
||||
currentIndex = 0;
|
||||
currentLookaheadIndex = 0;
|
||||
|
||||
while (!EndOfStream)
|
||||
{
|
||||
bool didMatchLexer = false;
|
||||
|
||||
ReadWhiteSpace();
|
||||
|
||||
foreach (Matcher matcher in matchers)
|
||||
{
|
||||
int startIndex = currentIndex;
|
||||
|
||||
bool isMatched = matcher.IsMatch(this);
|
||||
|
||||
if (isMatched)
|
||||
{
|
||||
int endIndex = currentIndex;
|
||||
|
||||
didMatchLexer = true;
|
||||
|
||||
yield return new LexerMatchInfo
|
||||
{
|
||||
startIndex = startIndex,
|
||||
endIndex = endIndex,
|
||||
htmlColor = matcher.HexColor,
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!didMatchLexer)
|
||||
{
|
||||
ReadNext();
|
||||
Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public char ReadNext()
|
||||
{
|
||||
if (EndOfStream)
|
||||
{
|
||||
return '\0';
|
||||
}
|
||||
|
||||
Previous = current;
|
||||
|
||||
current = inputString[currentLookaheadIndex];
|
||||
currentLookaheadIndex++;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
public void Rollback(int amount = -1)
|
||||
{
|
||||
if (amount == -1)
|
||||
{
|
||||
currentLookaheadIndex = currentIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentLookaheadIndex > currentIndex)
|
||||
{
|
||||
currentLookaheadIndex -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
int previousIndex = currentLookaheadIndex - 1;
|
||||
|
||||
if (previousIndex >= inputString.Length)
|
||||
{
|
||||
Previous = inputString[inputString.Length - 1];
|
||||
}
|
||||
else if (previousIndex >= 0)
|
||||
{
|
||||
Previous = inputString[previousIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
Previous = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
currentIndex = currentLookaheadIndex;
|
||||
}
|
||||
|
||||
public bool IsSpecialSymbol(char character, SpecialCharacterPosition position = SpecialCharacterPosition.Start)
|
||||
{
|
||||
if (position == SpecialCharacterPosition.Start)
|
||||
{
|
||||
return specialStartSymbols.Contains(character);
|
||||
}
|
||||
|
||||
return specialEndSymbols.Contains(character);
|
||||
}
|
||||
|
||||
private void ReadWhiteSpace()
|
||||
{
|
||||
while (char.IsWhiteSpace(ReadNext()) == true)
|
||||
{
|
||||
Commit();
|
||||
}
|
||||
|
||||
Rollback();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public sealed class KeywordMatch : Matcher
|
||||
{
|
||||
public string keywords;
|
||||
|
||||
public override Color HighlightColor => highlightColor;
|
||||
public Color highlightColor;
|
||||
|
||||
private readonly HashSet<string> shortlist = new HashSet<string>();
|
||||
private readonly Stack<string> removeList = new Stack<string>();
|
||||
public string[] keywordCache = null;
|
||||
|
||||
public override bool IsImplicitMatch(InputLexer lexer)
|
||||
{
|
||||
BuildKeywordCache();
|
||||
|
||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
shortlist.Clear();
|
||||
|
||||
int currentIndex = 0;
|
||||
char currentChar = lexer.ReadNext();
|
||||
|
||||
for (int i = 0; i < keywordCache.Length; i++)
|
||||
{
|
||||
if (keywordCache[i][0] == currentChar)
|
||||
{
|
||||
shortlist.Add(keywordCache[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (shortlist.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (lexer.EndOfStream)
|
||||
{
|
||||
RemoveLongStrings(currentIndex + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
currentChar = lexer.ReadNext();
|
||||
currentIndex++;
|
||||
|
||||
if (char.IsWhiteSpace(currentChar) ||
|
||||
lexer.IsSpecialSymbol(currentChar, SpecialCharacterPosition.Start))
|
||||
{
|
||||
RemoveLongStrings(currentIndex);
|
||||
lexer.Rollback(1);
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (string keyword in shortlist)
|
||||
{
|
||||
if (currentIndex >= keyword.Length || keyword[currentIndex] != currentChar)
|
||||
{
|
||||
removeList.Push(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
while (removeList.Count > 0)
|
||||
{
|
||||
shortlist.Remove(removeList.Pop());
|
||||
}
|
||||
}
|
||||
while (shortlist.Count > 0);
|
||||
|
||||
return shortlist.Count > 0;
|
||||
}
|
||||
|
||||
private void RemoveLongStrings(int length)
|
||||
{
|
||||
foreach (string keyword in shortlist)
|
||||
{
|
||||
if (keyword.Length > length)
|
||||
{
|
||||
removeList.Push(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
while (removeList.Count > 0)
|
||||
{
|
||||
shortlist.Remove(removeList.Pop());
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildKeywordCache()
|
||||
{
|
||||
if (keywordCache == null)
|
||||
{
|
||||
string[] kwSplit = keywords.Split(' ');
|
||||
|
||||
List<string> list = new List<string>();
|
||||
foreach (string kw in kwSplit)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(kw) && kw.Length > 0)
|
||||
{
|
||||
list.Add(kw);
|
||||
}
|
||||
}
|
||||
keywordCache = list.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityExplorer.Unstrip.ColorUtility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public abstract class Matcher
|
||||
{
|
||||
public abstract Color HighlightColor { get; }
|
||||
|
||||
public string HexColor => htmlColor ?? (htmlColor = "<#" + HighlightColor.ToHex() + ">");
|
||||
private string htmlColor = null;
|
||||
|
||||
public virtual IEnumerable<char> StartChars { get { yield break; } }
|
||||
public virtual IEnumerable<char> EndChars { get { yield break; } }
|
||||
|
||||
public abstract bool IsImplicitMatch(InputLexer lexer);
|
||||
|
||||
public bool IsMatch(InputLexer lexer)
|
||||
{
|
||||
if (IsImplicitMatch(lexer))
|
||||
{
|
||||
lexer.Commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
lexer.Rollback();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public sealed class NumberMatch : Matcher
|
||||
{
|
||||
public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
||||
|
||||
public override bool IsImplicitMatch(InputLexer lexer)
|
||||
{
|
||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool matchedNumber = false;
|
||||
|
||||
while (!lexer.EndOfStream)
|
||||
{
|
||||
if (IsNumberOrDecimalPoint(lexer.ReadNext()))
|
||||
{
|
||||
matchedNumber = true;
|
||||
lexer.Commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
lexer.Rollback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return matchedNumber;
|
||||
}
|
||||
|
||||
private bool IsNumberOrDecimalPoint(char character) => char.IsNumber(character) || character == '.';
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public sealed class StringMatch : Matcher
|
||||
{
|
||||
public override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f);
|
||||
|
||||
public override IEnumerable<char> StartChars { get { yield return '"'; } }
|
||||
public override IEnumerable<char> EndChars { get { yield return '"'; } }
|
||||
|
||||
public override bool IsImplicitMatch(InputLexer lexer)
|
||||
{
|
||||
if (lexer.ReadNext() == '"')
|
||||
{
|
||||
while (!IsClosingQuoteOrEndFile(lexer, lexer.ReadNext()))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsClosingQuoteOrEndFile(InputLexer lexer, char character)
|
||||
{
|
||||
if (lexer.EndOfStream == true ||
|
||||
character == '"')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console.Lexer
|
||||
{
|
||||
public sealed class SymbolMatch : Matcher
|
||||
{
|
||||
public override Color HighlightColor => new Color(0.58f, 0.47f, 0.37f, 1.0f);
|
||||
|
||||
public string Symbols => @"[ ] ( ) . ? : + - * / % & | ^ ~ = < > ++ -- && || << >> == != <= >=
|
||||
+= -= *= /= %= &= |= ^= <<= >>= -> ?? =>";
|
||||
|
||||
private static readonly List<string> shortlist = new List<string>();
|
||||
private static readonly Stack<string> removeList = new Stack<string>();
|
||||
private string[] symbolCache = null;
|
||||
|
||||
public override IEnumerable<char> StartChars
|
||||
{
|
||||
get
|
||||
{
|
||||
BuildSymbolCache();
|
||||
foreach (string symbol in symbolCache.Where(x => x.Length > 0))
|
||||
{
|
||||
yield return symbol[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<char> EndChars
|
||||
{
|
||||
get
|
||||
{
|
||||
BuildSymbolCache();
|
||||
foreach (string symbol in symbolCache.Where(x => x.Length > 0))
|
||||
{
|
||||
yield return symbol[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsImplicitMatch(InputLexer lexer)
|
||||
{
|
||||
if (lexer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildSymbolCache();
|
||||
|
||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||
!char.IsLetter(lexer.Previous) &&
|
||||
!char.IsDigit(lexer.Previous) &&
|
||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
shortlist.Clear();
|
||||
|
||||
int currentIndex = 0;
|
||||
char currentChar = lexer.ReadNext();
|
||||
|
||||
for (int i = symbolCache.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (symbolCache[i][0] == currentChar)
|
||||
{
|
||||
shortlist.Add(symbolCache[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (shortlist.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (lexer.EndOfStream)
|
||||
{
|
||||
RemoveLongStrings(currentIndex + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
currentChar = lexer.ReadNext();
|
||||
currentIndex++;
|
||||
|
||||
if (char.IsWhiteSpace(currentChar) ||
|
||||
char.IsLetter(currentChar) ||
|
||||
char.IsDigit(currentChar) ||
|
||||
lexer.IsSpecialSymbol(currentChar, SpecialCharacterPosition.Start))
|
||||
{
|
||||
RemoveLongStrings(currentIndex);
|
||||
lexer.Rollback(1);
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (string symbol in shortlist)
|
||||
{
|
||||
if (currentIndex >= symbol.Length || symbol[currentIndex] != currentChar)
|
||||
{
|
||||
removeList.Push(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
while (removeList.Count > 0)
|
||||
{
|
||||
shortlist.Remove(removeList.Pop());
|
||||
}
|
||||
}
|
||||
while (shortlist.Count > 0);
|
||||
|
||||
return shortlist.Count > 0;
|
||||
}
|
||||
|
||||
private void RemoveLongStrings(int length)
|
||||
{
|
||||
foreach (string keyword in shortlist)
|
||||
{
|
||||
if (keyword.Length > length)
|
||||
{
|
||||
removeList.Push(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
while (removeList.Count > 0)
|
||||
{
|
||||
shortlist.Remove(removeList.Pop());
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildSymbolCache()
|
||||
{
|
||||
if (symbolCache != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string[] symSplit = Symbols.Split(' ');
|
||||
List<string> list = new List<string>();
|
||||
foreach (string sym in symSplit)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sym) && sym.Length > 0)
|
||||
{
|
||||
list.Add(sym);
|
||||
}
|
||||
}
|
||||
symbolCache = list.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Mono.CSharp;
|
||||
|
||||
// Thanks to ManlyMarco for this
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public class ScriptEvaluator : Evaluator, IDisposable
|
||||
{
|
||||
private static readonly HashSet<string> StdLib = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
"mscorlib", "System.Core", "System", "System.Xml"
|
||||
};
|
||||
|
||||
private readonly TextWriter _logger;
|
||||
|
||||
public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger))
|
||||
{
|
||||
_logger = logger;
|
||||
|
||||
ImportAppdomainAssemblies(ReferenceAssembly);
|
||||
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
|
||||
_logger.Dispose();
|
||||
}
|
||||
|
||||
private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
|
||||
{
|
||||
string name = args.LoadedAssembly.GetName().Name;
|
||||
if (StdLib.Contains(name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReferenceAssembly(args.LoadedAssembly);
|
||||
}
|
||||
|
||||
private static CompilerContext BuildContext(TextWriter tw)
|
||||
{
|
||||
var reporter = new StreamReportPrinter(tw);
|
||||
|
||||
var settings = new CompilerSettings
|
||||
{
|
||||
Version = LanguageVersion.Experimental,
|
||||
GenerateDebugInfo = false,
|
||||
StdLib = true,
|
||||
Target = Target.Library,
|
||||
WarningLevel = 0,
|
||||
EnhancedWarnings = false
|
||||
};
|
||||
|
||||
return new CompilerContext(settings, reporter);
|
||||
}
|
||||
|
||||
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
||||
{
|
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
string name = assembly.GetName().Name;
|
||||
if (StdLib.Contains(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
import(assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
using System;
|
||||
using Mono.CSharp;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public class ScriptInteraction : InteractiveBase
|
||||
{
|
||||
public static void Log(object message)
|
||||
{
|
||||
ExplorerCore.Log(message);
|
||||
}
|
||||
|
||||
public static void AddUsing(string directive)
|
||||
{
|
||||
ConsolePage.Instance.AddUsing(directive);
|
||||
}
|
||||
|
||||
public static void GetUsing()
|
||||
{
|
||||
ExplorerCore.Log(ConsolePage.Instance.m_evaluator.GetUsing());
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
ConsolePage.Instance.ResetConsole();
|
||||
}
|
||||
|
||||
public static object CurrentTarget()
|
||||
{
|
||||
return InspectorManager.Instance?.m_activeInspector?.Target;
|
||||
}
|
||||
|
||||
public static object[] AllTargets()
|
||||
{
|
||||
int count = InspectorManager.Instance?.m_currentInspectors.Count ?? 0;
|
||||
object[] ret = new object[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ret[i] = InspectorManager.Instance?.m_currentInspectors[i].Target;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Inspect(object obj)
|
||||
{
|
||||
InspectorManager.Instance.Inspect(obj);
|
||||
}
|
||||
|
||||
public static void Inspect(Type type)
|
||||
{
|
||||
InspectorManager.Instance.Inspect(type);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Console
|
||||
{
|
||||
public struct Suggestion
|
||||
{
|
||||
public string Full => Prefix + Addition;
|
||||
|
||||
public readonly string Prefix;
|
||||
public readonly string Addition;
|
||||
public readonly Contexts Context;
|
||||
|
||||
public Color TextColor
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Context)
|
||||
{
|
||||
case Contexts.Namespace: return Color.grey;
|
||||
case Contexts.Keyword: return systemBlue;
|
||||
default: return Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static readonly Color systemBlue = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
||||
|
||||
public Suggestion(string addition, string prefix, Contexts type)
|
||||
{
|
||||
Addition = addition;
|
||||
Prefix = prefix;
|
||||
Context = type;
|
||||
}
|
||||
|
||||
public enum Contexts
|
||||
{
|
||||
Namespace,
|
||||
Keyword,
|
||||
Other
|
||||
}
|
||||
|
||||
public static HashSet<string> Namespaces => m_namspaces ?? GetNamespaces();
|
||||
private static HashSet<string> m_namspaces;
|
||||
|
||||
private static HashSet<string> GetNamespaces()
|
||||
{
|
||||
HashSet<string> set = new HashSet<string>(
|
||||
AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(GetTypes)
|
||||
.Where(x => x.IsPublic && !string.IsNullOrEmpty(x.Namespace))
|
||||
.Select(x => x.Namespace));
|
||||
|
||||
return m_namspaces = set;
|
||||
|
||||
IEnumerable<Type> GetTypes(Assembly asm) => asm.TryGetTypes();
|
||||
}
|
||||
|
||||
public static HashSet<string> Keywords => m_keywords ?? GetKeywords();
|
||||
private static HashSet<string> m_keywords;
|
||||
|
||||
private static HashSet<string> GetKeywords()
|
||||
{
|
||||
if (CSharpLexer.validKeywordMatcher.keywordCache == null)
|
||||
{
|
||||
return new HashSet<string>();
|
||||
}
|
||||
|
||||
HashSet<string> set = new HashSet<string>();
|
||||
|
||||
foreach (string keyword in CSharpLexer.validKeywordMatcher.keywordCache)
|
||||
{
|
||||
set.Add(keyword);
|
||||
}
|
||||
|
||||
return m_keywords = set;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,499 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Main.Console;
|
||||
using UnityExplorer.Unstrip.Resources;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if CPP
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class ConsolePage : MainMenu.Page
|
||||
{
|
||||
public override string Name => "C# Console";
|
||||
|
||||
public static ConsolePage Instance { get; private set; }
|
||||
|
||||
public static bool EnableSuggestions { get; set; } = true;
|
||||
public static bool EnableAutoIndent { get; set; } = true;
|
||||
|
||||
public CodeEditor m_codeEditor;
|
||||
public ScriptEvaluator m_evaluator;
|
||||
|
||||
public static List<Suggestion> AutoCompletes = new List<Suggestion>();
|
||||
public static List<string> UsingDirectives;
|
||||
|
||||
public static readonly string[] DefaultUsing = new string[]
|
||||
{
|
||||
"System",
|
||||
"UnityEngine",
|
||||
"System.Linq",
|
||||
"System.Collections",
|
||||
"System.Collections.Generic",
|
||||
"System.Reflection"
|
||||
};
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
try
|
||||
{
|
||||
ResetConsole();
|
||||
|
||||
foreach (string use in DefaultUsing)
|
||||
{
|
||||
AddUsing(use);
|
||||
}
|
||||
|
||||
ConstructUI();
|
||||
|
||||
AutoCompleter.Init();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Error setting up console!\r\nMessage: {e.Message}");
|
||||
// TODO remove page button from menu
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
m_codeEditor?.Update();
|
||||
|
||||
AutoCompleter.Update();
|
||||
}
|
||||
|
||||
public void AddUsing(string asm)
|
||||
{
|
||||
if (!UsingDirectives.Contains(asm))
|
||||
{
|
||||
UsingDirectives.Add(asm);
|
||||
Evaluate($"using {asm};", true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Evaluate(string str, bool suppressWarning = false)
|
||||
{
|
||||
m_evaluator.Compile(str, out Mono.CSharp.CompiledMethod compiled);
|
||||
|
||||
if (compiled == null)
|
||||
{
|
||||
if (!suppressWarning)
|
||||
{
|
||||
ExplorerCore.LogWarning("Unable to compile the code!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
object ret = VoidType.Value;
|
||||
compiled.Invoke(ref ret);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception executing code: {e.GetType()}, {e.Message}\r\n{e.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetConsole()
|
||||
{
|
||||
if (m_evaluator != null)
|
||||
{
|
||||
m_evaluator.Dispose();
|
||||
}
|
||||
|
||||
m_evaluator = new ScriptEvaluator(new StringWriter(new StringBuilder())) { InteractiveBaseClass = typeof(ScriptInteraction) };
|
||||
|
||||
UsingDirectives = new List<string>();
|
||||
}
|
||||
|
||||
internal void OnInputChanged()
|
||||
{
|
||||
AutoCompleter.CheckAutocomplete();
|
||||
|
||||
AutoCompleter.SetSuggestions(AutoCompletes.ToArray());
|
||||
}
|
||||
|
||||
public void UseAutocomplete(string suggestion)
|
||||
{
|
||||
int cursorIndex = m_codeEditor.InputField.caretPosition;
|
||||
string input = m_codeEditor.InputField.text;
|
||||
input = input.Insert(cursorIndex, suggestion);
|
||||
m_codeEditor.InputField.text = input;
|
||||
m_codeEditor.InputField.caretPosition += suggestion.Length;
|
||||
|
||||
AutoCompleter.ClearAutocompletes();
|
||||
}
|
||||
|
||||
#region UI Construction
|
||||
|
||||
public void ConstructUI()
|
||||
{
|
||||
Content = UIFactory.CreateUIObject("C# Console", MainMenu.Instance.PageViewport);
|
||||
|
||||
var mainLayout = Content.AddComponent<LayoutElement>();
|
||||
mainLayout.preferredHeight = 9900;
|
||||
mainLayout.flexibleHeight = 9000;
|
||||
|
||||
var mainGroup = Content.AddComponent<VerticalLayoutGroup>();
|
||||
mainGroup.childControlHeight = true;
|
||||
mainGroup.childControlWidth = true;
|
||||
mainGroup.childForceExpandHeight = true;
|
||||
mainGroup.childForceExpandWidth = true;
|
||||
|
||||
#region TOP BAR
|
||||
|
||||
// Main group object
|
||||
|
||||
var topBarObj = UIFactory.CreateHorizontalGroup(Content);
|
||||
LayoutElement topBarLayout = topBarObj.AddComponent<LayoutElement>();
|
||||
topBarLayout.minHeight = 50;
|
||||
topBarLayout.flexibleHeight = 0;
|
||||
|
||||
var topBarGroup = topBarObj.GetComponent<HorizontalLayoutGroup>();
|
||||
topBarGroup.padding.left = 30;
|
||||
topBarGroup.padding.right = 30;
|
||||
topBarGroup.padding.top = 8;
|
||||
topBarGroup.padding.bottom = 8;
|
||||
topBarGroup.spacing = 10;
|
||||
topBarGroup.childForceExpandHeight = true;
|
||||
topBarGroup.childForceExpandWidth = true;
|
||||
topBarGroup.childControlWidth = true;
|
||||
topBarGroup.childControlHeight = true;
|
||||
topBarGroup.childAlignment = TextAnchor.LowerCenter;
|
||||
|
||||
var topBarLabel = UIFactory.CreateLabel(topBarObj, TextAnchor.MiddleLeft);
|
||||
var topBarLabelLayout = topBarLabel.AddComponent<LayoutElement>();
|
||||
topBarLabelLayout.preferredWidth = 800;
|
||||
topBarLabelLayout.flexibleWidth = 10;
|
||||
var topBarText = topBarLabel.GetComponent<Text>();
|
||||
topBarText.text = "C# Console";
|
||||
topBarText.fontSize = 20;
|
||||
|
||||
// Enable Suggestions toggle
|
||||
|
||||
var suggestToggleObj = UIFactory.CreateToggle(topBarObj, out Toggle suggestToggle, out Text suggestToggleText);
|
||||
#if CPP
|
||||
suggestToggle.onValueChanged.AddListener(new Action<bool>(SuggestToggleCallback));
|
||||
#else
|
||||
suggestToggle.onValueChanged.AddListener(SuggestToggleCallback);
|
||||
#endif
|
||||
void SuggestToggleCallback(bool val)
|
||||
{
|
||||
EnableSuggestions = val;
|
||||
AutoCompleter.Update();
|
||||
}
|
||||
|
||||
suggestToggleText.text = "Suggestions";
|
||||
suggestToggleText.alignment = TextAnchor.UpperLeft;
|
||||
var suggestTextPos = suggestToggleText.transform.localPosition;
|
||||
suggestTextPos.y = -14;
|
||||
suggestToggleText.transform.localPosition = suggestTextPos;
|
||||
|
||||
var suggestLayout = suggestToggleObj.AddComponent<LayoutElement>();
|
||||
suggestLayout.minWidth = 120;
|
||||
suggestLayout.flexibleWidth = 0;
|
||||
|
||||
var suggestRect = suggestToggleObj.transform.Find("Background");
|
||||
var suggestPos = suggestRect.localPosition;
|
||||
suggestPos.y = -14;
|
||||
suggestRect.localPosition = suggestPos;
|
||||
|
||||
// Enable Auto-indent toggle
|
||||
|
||||
var autoIndentToggleObj = UIFactory.CreateToggle(topBarObj, out Toggle autoIndentToggle, out Text autoIndentToggleText);
|
||||
#if CPP
|
||||
autoIndentToggle.onValueChanged.AddListener(new Action<bool>((bool val) =>
|
||||
{
|
||||
EnableAutoIndent = val;
|
||||
}));
|
||||
#else
|
||||
autoIndentToggle.onValueChanged.AddListener(OnIndentChanged);
|
||||
|
||||
void OnIndentChanged(bool val) => EnableAutoIndent = val;
|
||||
#endif
|
||||
autoIndentToggleText.text = "Auto-indent";
|
||||
autoIndentToggleText.alignment = TextAnchor.UpperLeft;
|
||||
var autoIndentTextPos = autoIndentToggleText.transform.localPosition;
|
||||
autoIndentTextPos.y = -14;
|
||||
autoIndentToggleText.transform.localPosition = autoIndentTextPos;
|
||||
|
||||
var autoIndentLayout = autoIndentToggleObj.AddComponent<LayoutElement>();
|
||||
autoIndentLayout.minWidth = 120;
|
||||
autoIndentLayout.flexibleWidth = 0;
|
||||
|
||||
var autoIndentRect = autoIndentToggleObj.transform.Find("Background");
|
||||
suggestPos = autoIndentRect.localPosition;
|
||||
suggestPos.y = -14;
|
||||
autoIndentRect.localPosition = suggestPos;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CONSOLE INPUT
|
||||
|
||||
var consoleBase = UIFactory.CreateUIObject("CodeEditor", Content);
|
||||
|
||||
var consoleLayout = consoleBase.AddComponent<LayoutElement>();
|
||||
consoleLayout.preferredHeight = 500;
|
||||
consoleLayout.flexibleHeight = 50;
|
||||
|
||||
consoleBase.AddComponent<RectMask2D>();
|
||||
|
||||
var mainRect = consoleBase.GetComponent<RectTransform>();
|
||||
mainRect.pivot = Vector2.one * 0.5f;
|
||||
mainRect.anchorMin = Vector2.zero;
|
||||
mainRect.anchorMax = Vector2.one;
|
||||
mainRect.offsetMin = Vector2.zero;
|
||||
mainRect.offsetMax = Vector2.zero;
|
||||
|
||||
var mainBg = UIFactory.CreateUIObject("MainBackground", consoleBase);
|
||||
|
||||
var mainBgRect = mainBg.GetComponent<RectTransform>();
|
||||
mainBgRect.pivot = new Vector2(0, 1);
|
||||
mainBgRect.anchorMin = Vector2.zero;
|
||||
mainBgRect.anchorMax = Vector2.one;
|
||||
mainBgRect.offsetMin = Vector2.zero;
|
||||
mainBgRect.offsetMax = Vector2.zero;
|
||||
|
||||
var mainBgImage = mainBg.AddComponent<Image>();
|
||||
|
||||
var lineHighlight = UIFactory.CreateUIObject("LineHighlight", consoleBase);
|
||||
|
||||
var lineHighlightRect = lineHighlight.GetComponent<RectTransform>();
|
||||
lineHighlightRect.pivot = new Vector2(0.5f, 1);
|
||||
lineHighlightRect.anchorMin = new Vector2(0, 1);
|
||||
lineHighlightRect.anchorMax = new Vector2(1, 1);
|
||||
lineHighlightRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 21);
|
||||
|
||||
var lineHighlightImage = lineHighlight.GetComponent<Image>();
|
||||
if (!lineHighlightImage)
|
||||
{
|
||||
lineHighlightImage = lineHighlight.AddComponent<Image>();
|
||||
}
|
||||
|
||||
var linesBg = UIFactory.CreateUIObject("LinesBackground", consoleBase);
|
||||
var linesBgRect = linesBg.GetComponent<RectTransform>();
|
||||
linesBgRect.anchorMin = Vector2.zero;
|
||||
linesBgRect.anchorMax = new Vector2(0, 1);
|
||||
linesBgRect.offsetMin = new Vector2(-17.5f, 0);
|
||||
linesBgRect.offsetMax = new Vector2(17.5f, 0);
|
||||
linesBgRect.sizeDelta = new Vector2(65, 0);
|
||||
|
||||
var linesBgImage = linesBg.AddComponent<Image>();
|
||||
|
||||
var inputObj = UIFactory.CreateTMPInput(consoleBase);
|
||||
|
||||
var inputField = inputObj.GetComponent<TMP_InputField>();
|
||||
inputField.richText = false;
|
||||
|
||||
var inputRect = inputObj.GetComponent<RectTransform>();
|
||||
inputRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
inputRect.anchorMin = Vector2.zero;
|
||||
inputRect.anchorMax = new Vector2(0.92f, 1);
|
||||
inputRect.offsetMin = new Vector2(20, 0);
|
||||
inputRect.offsetMax = new Vector2(14, 0);
|
||||
inputRect.anchoredPosition = new Vector2(40, 0);
|
||||
|
||||
var textAreaObj = inputObj.transform.Find("TextArea");
|
||||
var textAreaRect = textAreaObj.GetComponent<RectTransform>();
|
||||
textAreaRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
textAreaRect.anchorMin = Vector2.zero;
|
||||
textAreaRect.anchorMax = Vector2.one;
|
||||
|
||||
var mainTextObj = textAreaObj.transform.Find("Text");
|
||||
var mainTextRect = mainTextObj.GetComponent<RectTransform>();
|
||||
mainTextRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
mainTextRect.anchorMin = Vector2.zero;
|
||||
mainTextRect.anchorMax = Vector2.one;
|
||||
mainTextRect.offsetMin = Vector2.zero;
|
||||
mainTextRect.offsetMax = Vector2.zero;
|
||||
|
||||
var mainTextInput = mainTextObj.GetComponent<TextMeshProUGUI>();
|
||||
mainTextInput.fontSize = 18;
|
||||
|
||||
var placeHolderText = textAreaObj.transform.Find("Placeholder").GetComponent<TextMeshProUGUI>();
|
||||
placeHolderText.text = @"Welcome to the UnityExplorer C# Console.
|
||||
|
||||
The following helper methods are available:
|
||||
|
||||
* <color=#add490>Log(""message"");</color> logs a message to the debug console
|
||||
|
||||
* <color=#add490>CurrentTarget();</color> returns the currently inspected target on the Home page
|
||||
|
||||
* <color=#add490>AllTargets();</color> returns an object[] array containing all inspected instances
|
||||
|
||||
* <color=#add490>Inspect(someObject)</color> to inspect an instance, eg. Inspect(Camera.main);
|
||||
|
||||
* <color=#add490>Inspect(typeof(SomeClass))</color> to inspect a Class with static reflection
|
||||
|
||||
* <color=#add490>AddUsing(""SomeNamespace"");</color> adds a using directive to the C# console
|
||||
|
||||
* <color=#add490>GetUsing();</color> logs the current using directives to the debug console
|
||||
|
||||
* <color=#add490>Reset();</color> resets all using directives and variables
|
||||
";
|
||||
|
||||
var linesTextObj = UIFactory.CreateUIObject("LinesText", mainTextObj.gameObject);
|
||||
var linesTextRect = linesTextObj.GetComponent<RectTransform>();
|
||||
|
||||
var linesTextInput = linesTextObj.AddComponent<TextMeshProUGUI>();
|
||||
linesTextInput.fontSize = 18;
|
||||
|
||||
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", mainTextObj.gameObject);
|
||||
var highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
|
||||
highlightTextRect.anchorMin = Vector2.zero;
|
||||
highlightTextRect.anchorMax = Vector2.one;
|
||||
highlightTextRect.offsetMin = Vector2.zero;
|
||||
highlightTextRect.offsetMax = Vector2.zero;
|
||||
|
||||
var highlightTextInput = highlightTextObj.AddComponent<TextMeshProUGUI>();
|
||||
highlightTextInput.fontSize = 18;
|
||||
|
||||
var scroll = UIFactory.CreateScrollbar(consoleBase);
|
||||
|
||||
var scrollRect = scroll.GetComponent<RectTransform>();
|
||||
scrollRect.anchorMin = new Vector2(1, 0);
|
||||
scrollRect.anchorMax = new Vector2(1, 1);
|
||||
scrollRect.pivot = new Vector2(0.5f, 1);
|
||||
scrollRect.offsetMin = new Vector2(-25f, 0);
|
||||
|
||||
var scroller = scroll.GetComponent<Scrollbar>();
|
||||
scroller.direction = Scrollbar.Direction.TopToBottom;
|
||||
var scrollColors = scroller.colors;
|
||||
scrollColors.normalColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
|
||||
scroller.colors = scrollColors;
|
||||
|
||||
var scrollImage = scroll.GetComponent<Image>();
|
||||
|
||||
var tmpInput = inputObj.GetComponent<TMP_InputField>();
|
||||
tmpInput.scrollSensitivity = 15;
|
||||
tmpInput.verticalScrollbar = scroller;
|
||||
|
||||
// set lines text anchors here after UI is fleshed out
|
||||
linesTextRect.pivot = Vector2.zero;
|
||||
linesTextRect.anchorMin = new Vector2(0, 0);
|
||||
linesTextRect.anchorMax = new Vector2(1, 1);
|
||||
linesTextRect.offsetMin = Vector2.zero;
|
||||
linesTextRect.offsetMax = Vector2.zero;
|
||||
linesTextRect.anchoredPosition = new Vector2(-40, 0);
|
||||
|
||||
tmpInput.GetComponentInChildren<RectMask2D>().enabled = false;
|
||||
inputObj.GetComponent<Image>().enabled = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region COMPILE BUTTON
|
||||
|
||||
var compileBtnObj = UIFactory.CreateButton(Content);
|
||||
var compileBtnLayout = compileBtnObj.AddComponent<LayoutElement>();
|
||||
compileBtnLayout.preferredWidth = 80;
|
||||
compileBtnLayout.flexibleWidth = 0;
|
||||
compileBtnLayout.minHeight = 45;
|
||||
compileBtnLayout.flexibleHeight = 0;
|
||||
var compileButton = compileBtnObj.GetComponent<Button>();
|
||||
var compileBtnColors = compileButton.colors;
|
||||
compileBtnColors.normalColor = new Color(14f / 255f, 80f / 255f, 14f / 255f);
|
||||
compileButton.colors = compileBtnColors;
|
||||
var btnText = compileBtnObj.GetComponentInChildren<Text>();
|
||||
btnText.text = "Run";
|
||||
btnText.fontSize = 18;
|
||||
btnText.color = Color.white;
|
||||
|
||||
// Set compile button callback now that we have the Input Field reference
|
||||
#if CPP
|
||||
compileButton.onClick.AddListener(new Action(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tmpInput.text))
|
||||
{
|
||||
Evaluate(tmpInput.text.Trim());
|
||||
}
|
||||
}));
|
||||
#else
|
||||
compileButton.onClick.AddListener(CompileCallback);
|
||||
|
||||
void CompileCallback()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tmpInput.text))
|
||||
{
|
||||
Evaluate(tmpInput.text.Trim());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region FONT
|
||||
|
||||
TMP_FontAsset fontToUse = null;
|
||||
#if CPP
|
||||
UnityEngine.Object[] fonts = ResourcesUnstrip.FindObjectsOfTypeAll(Il2CppType.Of<TMP_FontAsset>());
|
||||
foreach (UnityEngine.Object font in fonts)
|
||||
{
|
||||
TMP_FontAsset fontCast = font.Il2CppCast(typeof(TMP_FontAsset)) as TMP_FontAsset;
|
||||
|
||||
if (fontCast.name.Contains("LiberationSans"))
|
||||
{
|
||||
fontToUse = fontCast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
var fonts = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
|
||||
foreach (var font in fonts)
|
||||
{
|
||||
if (font.name.Contains("LiberationSans"))
|
||||
{
|
||||
fontToUse = font;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (fontToUse != null)
|
||||
{
|
||||
UnityEngine.TextCore.FaceInfo faceInfo = fontToUse.faceInfo;
|
||||
fontToUse.tabSize = 10;
|
||||
faceInfo.tabWidth = 10;
|
||||
#if CPP
|
||||
fontToUse.faceInfo = faceInfo;
|
||||
#else
|
||||
typeof(TMP_FontAsset)
|
||||
.GetField("m_FaceInfo", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.SetValue(fontToUse, faceInfo);
|
||||
#endif
|
||||
|
||||
tmpInput.fontAsset = fontToUse;
|
||||
mainTextInput.font = fontToUse;
|
||||
highlightTextInput.font = fontToUse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
try
|
||||
{
|
||||
m_codeEditor = new CodeEditor(inputField, mainTextInput, highlightTextInput, linesTextInput,
|
||||
mainBgImage, lineHighlightImage, linesBgImage, scrollImage);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log(e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class VoidType
|
||||
{
|
||||
public static readonly VoidType Value = new VoidType();
|
||||
private VoidType() { }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityExplorer.Unstrip.ColorUtility;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if CPP
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class DebugConsole
|
||||
{
|
||||
public static DebugConsole Instance { get; private set; }
|
||||
|
||||
public static bool LogUnity { get; set; } = true;
|
||||
|
||||
public readonly List<string> AllMessages;
|
||||
public readonly List<Text> MessageHolders;
|
||||
|
||||
private TMP_InputField m_textInput;
|
||||
|
||||
public DebugConsole(GameObject parent)
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
AllMessages = new List<string>();
|
||||
MessageHolders = new List<Text>();
|
||||
|
||||
try
|
||||
{
|
||||
ConstructUI(parent);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log(e);
|
||||
}
|
||||
}
|
||||
public static void Log(string message)
|
||||
{
|
||||
Log(message, null);
|
||||
}
|
||||
|
||||
public static void Log(string message, Color color)
|
||||
{
|
||||
Log(message, color.ToHex());
|
||||
}
|
||||
|
||||
public static void Log(string message, string hexColor)
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Instance.AllMessages.Add(message);
|
||||
|
||||
if (Instance.m_textInput)
|
||||
{
|
||||
if (hexColor != null)
|
||||
{
|
||||
message = $"<color=#{hexColor}>{message}</color>";
|
||||
}
|
||||
|
||||
Instance.m_textInput.text = $"{message}\n{Instance.m_textInput.text}";
|
||||
}
|
||||
}
|
||||
|
||||
// todo: get scrollbar working with inputfield somehow
|
||||
|
||||
public void ConstructUI(GameObject parent)
|
||||
{
|
||||
var mainObj = UIFactory.CreateVerticalGroup(parent, new Color(0.1f, 0.1f, 0.1f, 1.0f));
|
||||
|
||||
var mainGroup = mainObj.GetComponent<VerticalLayoutGroup>();
|
||||
mainGroup.childControlHeight = true;
|
||||
mainGroup.childControlWidth = true;
|
||||
mainGroup.childForceExpandHeight = true;
|
||||
mainGroup.childForceExpandWidth = true;
|
||||
|
||||
var mainImage = mainObj.GetComponent<Image>();
|
||||
mainImage.maskable = true;
|
||||
|
||||
var mask = mainObj.AddComponent<Mask>();
|
||||
mask.showMaskGraphic = true;
|
||||
|
||||
var mainLayout = mainObj.AddComponent<LayoutElement>();
|
||||
mainLayout.minHeight = 190;
|
||||
mainLayout.flexibleHeight = 0;
|
||||
|
||||
#region LOG AREA
|
||||
var logAreaObj = UIFactory.CreateHorizontalGroup(mainObj);
|
||||
var logAreaGroup = logAreaObj.GetComponent<HorizontalLayoutGroup>();
|
||||
logAreaGroup.childControlHeight = true;
|
||||
logAreaGroup.childControlWidth = true;
|
||||
logAreaGroup.childForceExpandHeight = true;
|
||||
logAreaGroup.childForceExpandWidth = true;
|
||||
|
||||
var logAreaLayout = logAreaObj.AddComponent<LayoutElement>();
|
||||
logAreaLayout.preferredHeight = 190;
|
||||
logAreaLayout.flexibleHeight = 0;
|
||||
|
||||
var inputObj = UIFactory.CreateTMPInput(logAreaObj);
|
||||
|
||||
var mainInputGroup = inputObj.GetComponent<VerticalLayoutGroup>();
|
||||
mainInputGroup.padding.left = 8;
|
||||
mainInputGroup.padding.right = 8;
|
||||
mainInputGroup.padding.top = 5;
|
||||
mainInputGroup.padding.bottom = 5;
|
||||
|
||||
var inputLayout = inputObj.AddComponent<LayoutElement>();
|
||||
inputLayout.preferredWidth = 500;
|
||||
inputLayout.flexibleWidth = 9999;
|
||||
|
||||
var inputImage = inputObj.GetComponent<Image>();
|
||||
inputImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
|
||||
|
||||
var scroll = UIFactory.CreateScrollbar(logAreaObj);
|
||||
|
||||
var scrollLayout = scroll.AddComponent<LayoutElement>();
|
||||
scrollLayout.preferredWidth = 25;
|
||||
scrollLayout.flexibleWidth = 0;
|
||||
|
||||
var scroller = scroll.GetComponent<Scrollbar>();
|
||||
scroller.direction = Scrollbar.Direction.TopToBottom;
|
||||
var scrollColors = scroller.colors;
|
||||
scrollColors.normalColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
scroller.colors = scrollColors;
|
||||
|
||||
var tmpInput = inputObj.GetComponent<TMP_InputField>();
|
||||
tmpInput.scrollSensitivity = 15;
|
||||
tmpInput.verticalScrollbar = scroller;
|
||||
|
||||
tmpInput.readOnly = true;
|
||||
|
||||
m_textInput = inputObj.GetComponent<TMP_InputField>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region BOTTOM BAR
|
||||
|
||||
var bottomBarObj = UIFactory.CreateHorizontalGroup(mainObj);
|
||||
LayoutElement topBarLayout = bottomBarObj.AddComponent<LayoutElement>();
|
||||
topBarLayout.minHeight = 40;
|
||||
topBarLayout.flexibleHeight = 0;
|
||||
|
||||
var bottomGroup = bottomBarObj.GetComponent<HorizontalLayoutGroup>();
|
||||
bottomGroup.padding.left = 10;
|
||||
bottomGroup.padding.right = 10;
|
||||
bottomGroup.padding.top = 2;
|
||||
bottomGroup.padding.bottom = 2;
|
||||
bottomGroup.spacing = 10;
|
||||
bottomGroup.childForceExpandHeight = true;
|
||||
bottomGroup.childForceExpandWidth = false;
|
||||
bottomGroup.childControlWidth = true;
|
||||
bottomGroup.childControlHeight = true;
|
||||
bottomGroup.childAlignment = TextAnchor.MiddleLeft;
|
||||
|
||||
// Debug Console label
|
||||
|
||||
var bottomLabel = UIFactory.CreateLabel(bottomBarObj, TextAnchor.MiddleLeft);
|
||||
var topBarLabelLayout = bottomLabel.AddComponent<LayoutElement>();
|
||||
topBarLabelLayout.minWidth = 100;
|
||||
topBarLabelLayout.flexibleWidth = 0;
|
||||
var topBarText = bottomLabel.GetComponent<Text>();
|
||||
topBarText.fontStyle = FontStyle.Bold;
|
||||
topBarText.text = "Debug Console";
|
||||
topBarText.fontSize = 14;
|
||||
|
||||
// Hide button
|
||||
|
||||
var hideButtonObj = UIFactory.CreateButton(bottomBarObj);
|
||||
|
||||
var hideBtnText = hideButtonObj.GetComponentInChildren<Text>();
|
||||
hideBtnText.text = "Hide";
|
||||
|
||||
var hideButton = hideButtonObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
hideButton.onClick.AddListener(new Action(HideCallback));
|
||||
#else
|
||||
hideButton.onClick.AddListener(HideCallback);
|
||||
#endif
|
||||
void HideCallback()
|
||||
{
|
||||
if (logAreaObj.activeSelf)
|
||||
{
|
||||
logAreaObj.SetActive(false);
|
||||
hideBtnText.text = "Show";
|
||||
mainLayout.minHeight = 40;
|
||||
}
|
||||
else
|
||||
{
|
||||
logAreaObj.SetActive(true);
|
||||
hideBtnText.text = "Hide";
|
||||
mainLayout.minHeight = 190;
|
||||
}
|
||||
}
|
||||
|
||||
var hideBtnColors = hideButton.colors;
|
||||
//hideBtnColors.normalColor = new Color(160f / 255f, 140f / 255f, 40f / 255f);
|
||||
hideButton.colors = hideBtnColors;
|
||||
|
||||
var hideBtnLayout = hideButtonObj.AddComponent<LayoutElement>();
|
||||
hideBtnLayout.minWidth = 80;
|
||||
hideBtnLayout.flexibleWidth = 0;
|
||||
|
||||
// Clear button
|
||||
|
||||
var clearButtonObj = UIFactory.CreateButton(bottomBarObj);
|
||||
|
||||
var clearBtnText = clearButtonObj.GetComponentInChildren<Text>();
|
||||
clearBtnText.text = "Clear";
|
||||
|
||||
var clearButton = clearButtonObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
clearButton.onClick.AddListener(new Action(ClearCallback));
|
||||
#else
|
||||
clearButton.onClick.AddListener(ClearCallback);
|
||||
#endif
|
||||
|
||||
void ClearCallback()
|
||||
{
|
||||
m_textInput.text = "";
|
||||
}
|
||||
|
||||
var clearBtnColors = clearButton.colors;
|
||||
//clearBtnColors.normalColor = new Color(160f/255f, 140f/255f, 40f/255f);
|
||||
clearButton.colors = clearBtnColors;
|
||||
|
||||
var clearBtnLayout = clearButtonObj.AddComponent<LayoutElement>();
|
||||
clearBtnLayout.minWidth = 80;
|
||||
clearBtnLayout.flexibleWidth = 0;
|
||||
|
||||
// Unity log toggle
|
||||
|
||||
var unityToggleObj = UIFactory.CreateToggle(bottomBarObj, out Toggle unityToggle, out Text unityToggleText);
|
||||
#if CPP
|
||||
unityToggle.onValueChanged.AddListener(new Action<bool>((bool val) => { LogUnity = val; }));
|
||||
#else
|
||||
unityToggle.onValueChanged.AddListener((bool val) => { LogUnity = val; });
|
||||
#endif
|
||||
unityToggleText.text = "Print Unity Debug?";
|
||||
unityToggleText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
var unityToggleLayout = unityToggleObj.AddComponent<LayoutElement>();
|
||||
unityToggleLayout.minWidth = 200;
|
||||
unityToggleLayout.flexibleWidth = 0;
|
||||
|
||||
var unityToggleRect = unityToggleObj.transform.Find("Background").GetComponent<RectTransform>();
|
||||
var pos = unityToggleRect.localPosition;
|
||||
pos.y = -8;
|
||||
unityToggleRect.localPosition = pos;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class HomePage : MainMenu.Page
|
||||
{
|
||||
public override string Name => "Home";
|
||||
|
||||
public static HomePage Instance { get; internal set; }
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
ConstructMenu();
|
||||
|
||||
new SceneExplorer();
|
||||
|
||||
new InspectorManager();
|
||||
|
||||
SceneExplorer.Instance.Init();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
SceneExplorer.Instance.Update();
|
||||
InspectorManager.Instance.Update();
|
||||
}
|
||||
|
||||
private void ConstructMenu()
|
||||
{
|
||||
GameObject parent = MainMenu.Instance.PageViewport;
|
||||
|
||||
Content = UIFactory.CreateHorizontalGroup(parent);
|
||||
var mainGroup = Content.GetComponent<HorizontalLayoutGroup>();
|
||||
mainGroup.padding.left = 3;
|
||||
mainGroup.padding.right = 3;
|
||||
mainGroup.padding.top = 3;
|
||||
mainGroup.padding.bottom = 3;
|
||||
mainGroup.spacing = 5;
|
||||
mainGroup.childForceExpandHeight = true;
|
||||
mainGroup.childForceExpandWidth = true;
|
||||
mainGroup.childControlHeight = true;
|
||||
mainGroup.childControlWidth = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.Helpers;
|
||||
using UnityExplorer.UI.Main.Inspectors;
|
||||
using UnityExplorer.UI.Shared;
|
||||
using UnityExplorer.Unstrip.Scenes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class InspectorManager
|
||||
{
|
||||
public static InspectorManager Instance { get; private set; }
|
||||
|
||||
public InspectorManager()
|
||||
{
|
||||
Instance = this;
|
||||
ConstructInspectorPane();
|
||||
}
|
||||
|
||||
public InspectorBase m_activeInspector;
|
||||
public readonly List<InspectorBase> m_currentInspectors = new List<InspectorBase>();
|
||||
|
||||
public GameObject m_tabBarContent;
|
||||
public GameObject m_inspectorContent;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
for (int i = 0; i < m_currentInspectors.Count; i++)
|
||||
{
|
||||
if (i >= m_currentInspectors.Count)
|
||||
break;
|
||||
|
||||
m_currentInspectors[i].Update();
|
||||
}
|
||||
}
|
||||
|
||||
public void Inspect(object obj)
|
||||
{
|
||||
#if CPP
|
||||
obj = obj.Il2CppCast(ReflectionHelpers.GetActualType(obj));
|
||||
#endif
|
||||
UnityEngine.Object unityObj = obj as UnityEngine.Object;
|
||||
|
||||
if (InspectorBase.ObjectNullOrDestroyed(obj, unityObj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MainMenu.Instance.SetPage(HomePage.Instance);
|
||||
|
||||
// check if currently inspecting this object
|
||||
foreach (InspectorBase tab in m_currentInspectors)
|
||||
{
|
||||
if (ReferenceEquals(obj, tab.Target))
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
#if CPP
|
||||
else if (unityObj && tab.Target is UnityEngine.Object uTabObj)
|
||||
{
|
||||
if (unityObj.m_CachedPtr == uTabObj.m_CachedPtr)
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
InspectorBase inspector;
|
||||
if (obj is GameObject go)
|
||||
{
|
||||
inspector = new GameObjectInspector(go);
|
||||
}
|
||||
else
|
||||
{
|
||||
inspector = new InstanceInspector(obj);
|
||||
}
|
||||
|
||||
m_currentInspectors.Add(inspector);
|
||||
inspector.Content?.SetActive(false);
|
||||
|
||||
SetInspectorTab(inspector);
|
||||
}
|
||||
|
||||
public void Inspect(Type type)
|
||||
{
|
||||
// TODO static type inspection
|
||||
}
|
||||
|
||||
public void SetInspectorTab(InspectorBase inspector)
|
||||
{
|
||||
UnsetInspectorTab();
|
||||
|
||||
m_activeInspector = inspector;
|
||||
|
||||
m_activeInspector.Content?.SetActive(true);
|
||||
|
||||
Color activeColor = new Color(0, 0.25f, 0, 1);
|
||||
ColorBlock colors = inspector.tabButton.colors;
|
||||
colors.normalColor = activeColor;
|
||||
colors.highlightedColor = activeColor;
|
||||
inspector.tabButton.colors = colors;
|
||||
}
|
||||
|
||||
public void UnsetInspectorTab()
|
||||
{
|
||||
if (m_activeInspector == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_activeInspector.Content?.SetActive(false);
|
||||
|
||||
ColorBlock colors = m_activeInspector.tabButton.colors;
|
||||
colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||
colors.highlightedColor = new Color(0.1f, 0.3f, 0.1f, 1);
|
||||
m_activeInspector.tabButton.colors = colors;
|
||||
|
||||
m_activeInspector = null;
|
||||
}
|
||||
|
||||
#region INSPECTOR PANE
|
||||
|
||||
public void ConstructInspectorPane()
|
||||
{
|
||||
var mainObj = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
|
||||
LayoutElement rightLayout = mainObj.AddComponent<LayoutElement>();
|
||||
rightLayout.flexibleWidth = 999999;
|
||||
|
||||
var rightGroup = mainObj.GetComponent<VerticalLayoutGroup>();
|
||||
rightGroup.childForceExpandHeight = true;
|
||||
rightGroup.childForceExpandWidth = true;
|
||||
rightGroup.childControlHeight = true;
|
||||
rightGroup.childControlWidth = true;
|
||||
rightGroup.spacing = 10;
|
||||
rightGroup.padding.left = 8;
|
||||
rightGroup.padding.right = 8;
|
||||
rightGroup.padding.top = 8;
|
||||
rightGroup.padding.bottom = 8;
|
||||
|
||||
var inspectorTitle = UIFactory.CreateLabel(mainObj, TextAnchor.UpperLeft);
|
||||
Text title = inspectorTitle.GetComponent<Text>();
|
||||
title.text = "Inspector";
|
||||
title.fontSize = 20;
|
||||
var titleLayout = inspectorTitle.AddComponent<LayoutElement>();
|
||||
titleLayout.minHeight = 30;
|
||||
titleLayout.flexibleHeight = 0;
|
||||
|
||||
m_tabBarContent = UIFactory.CreateGridGroup(mainObj, new Vector2(185, 20), new Vector2(5, 2), new Color(0.1f, 0.1f, 0.1f, 1));
|
||||
|
||||
var gridGroup = m_tabBarContent.GetComponent<GridLayoutGroup>();
|
||||
gridGroup.padding.top = 4;
|
||||
gridGroup.padding.left = 4;
|
||||
gridGroup.padding.right = 4;
|
||||
gridGroup.padding.bottom = 4;
|
||||
|
||||
// inspector content area
|
||||
|
||||
m_inspectorContent = UIFactory.CreateVerticalGroup(mainObj, new Color(0.1f, 0.1f, 0.1f, 1.0f));
|
||||
|
||||
var contentGroup = m_inspectorContent.GetComponent<VerticalLayoutGroup>();
|
||||
contentGroup.childForceExpandHeight = true;
|
||||
contentGroup.childForceExpandWidth = true;
|
||||
contentGroup.childControlHeight = true;
|
||||
contentGroup.childControlWidth = true;
|
||||
contentGroup.spacing = 5;
|
||||
contentGroup.padding.top = 5;
|
||||
contentGroup.padding.left = 5;
|
||||
contentGroup.padding.right = 5;
|
||||
contentGroup.padding.bottom = 5;
|
||||
|
||||
var contentLayout = m_inspectorContent.AddComponent<LayoutElement>();
|
||||
contentLayout.preferredHeight = 900;
|
||||
contentLayout.flexibleHeight = 10000;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,847 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.Helpers;
|
||||
using UnityExplorer.UI.Shared;
|
||||
using UnityExplorer.Unstrip.ColorUtility;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Unstrip.LayerMasks;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Inspectors
|
||||
{
|
||||
// TODO:
|
||||
// fix path and name input for very long input (use content size fitter + preffered size + vert layout group)
|
||||
// make back button (inspect parent button)
|
||||
// make controls panel (transform controls, set parent, etc)
|
||||
|
||||
public class GameObjectInspector : InspectorBase
|
||||
{
|
||||
public override string TabLabel => $" [G] {TargetGO?.name}";
|
||||
|
||||
// just to help with casting in il2cpp
|
||||
public GameObject TargetGO;
|
||||
|
||||
// static UI elements (only constructed once)
|
||||
|
||||
private static bool m_UIConstructed;
|
||||
|
||||
private static GameObject m_content;
|
||||
public override GameObject Content
|
||||
{
|
||||
get => m_content;
|
||||
set => m_content = value;
|
||||
}
|
||||
|
||||
// cached ui elements
|
||||
public static TMP_InputField m_nameInput;
|
||||
private static string m_lastName;
|
||||
public static TMP_InputField m_pathInput;
|
||||
private static string m_lastPath;
|
||||
private static GameObject m_pathGroupObj;
|
||||
private static Text m_hiddenPathText;
|
||||
|
||||
private static Toggle m_enabledToggle;
|
||||
private static Text m_enabledText;
|
||||
private static bool? m_lastEnabledState;
|
||||
|
||||
private static Dropdown m_layerDropdown;
|
||||
private static int m_lastLayer = -1;
|
||||
|
||||
private static Text m_sceneText;
|
||||
private static string m_lastScene;
|
||||
|
||||
// children list
|
||||
public static PageHandler s_childListPageHandler;
|
||||
private static GameObject[] s_allChildren = new GameObject[0];
|
||||
private static readonly List<GameObject> s_childrenShortlist = new List<GameObject>();
|
||||
private static GameObject s_childListContent;
|
||||
private static readonly List<Text> s_childListTexts = new List<Text>();
|
||||
private static int s_lastChildCount;
|
||||
|
||||
// comp list
|
||||
public static PageHandler s_compListPageHandler;
|
||||
private static Component[] s_allComps = new Component[0];
|
||||
private static readonly List<Component> s_compShortlist = new List<Component>();
|
||||
private static GameObject s_compListContent;
|
||||
private static readonly List<Text> s_compListTexts = new List<Text>();
|
||||
private static int s_lastCompCount;
|
||||
public static readonly List<Toggle> s_compToggles = new List<Toggle>();
|
||||
|
||||
public GameObjectInspector(GameObject target) : base(target)
|
||||
{
|
||||
TargetGO = target;
|
||||
|
||||
if (!TargetGO)
|
||||
{
|
||||
ExplorerCore.LogWarning("GameObjectInspector cctor: Target GameObject is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
// one UI is used for all gameobject inspectors. no point recreating it.
|
||||
if (!m_UIConstructed)
|
||||
{
|
||||
ConstructUI();
|
||||
m_UIConstructed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (m_pendingDestroy || InspectorManager.Instance.m_activeInspector != this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshTopInfo();
|
||||
|
||||
RefreshChildObjectList();
|
||||
|
||||
RefreshComponentList();
|
||||
}
|
||||
|
||||
private void RefreshTopInfo()
|
||||
{
|
||||
if (m_lastName != TargetGO.name)
|
||||
{
|
||||
m_lastName = TargetGO.name;
|
||||
m_nameInput.text = m_lastName;
|
||||
}
|
||||
|
||||
if (TargetGO.transform.parent)
|
||||
{
|
||||
if (!m_pathGroupObj.activeSelf)
|
||||
m_pathGroupObj.SetActive(true);
|
||||
|
||||
var path = TargetGO.transform.GetTransformPath(true);
|
||||
if (m_lastPath != path)
|
||||
{
|
||||
m_lastPath = path;
|
||||
m_pathInput.text = path;
|
||||
m_hiddenPathText.text = path;
|
||||
}
|
||||
}
|
||||
else if (m_pathGroupObj.activeSelf)
|
||||
m_pathGroupObj.SetActive(false);
|
||||
|
||||
if (m_lastEnabledState != TargetGO.activeSelf)
|
||||
{
|
||||
m_lastEnabledState = TargetGO.activeSelf;
|
||||
|
||||
m_enabledToggle.isOn = TargetGO.activeSelf;
|
||||
m_enabledText.text = TargetGO.activeSelf ? "Enabled" : "Disabled";
|
||||
m_enabledText.color = TargetGO.activeSelf ? Color.green : Color.red;
|
||||
}
|
||||
|
||||
if (m_lastLayer != TargetGO.layer)
|
||||
{
|
||||
m_lastLayer = TargetGO.layer;
|
||||
m_layerDropdown.value = TargetGO.layer;
|
||||
}
|
||||
|
||||
if (m_lastScene != TargetGO.scene.name)
|
||||
{
|
||||
m_lastScene = TargetGO.scene.name;
|
||||
|
||||
if (!string.IsNullOrEmpty(TargetGO.scene.name))
|
||||
m_sceneText.text = m_lastScene;
|
||||
else
|
||||
m_sceneText.text = "None (Asset/Resource)";
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshChildObjectList()
|
||||
{
|
||||
s_allChildren = new GameObject[TargetGO.transform.childCount];
|
||||
for (int i = 0; i < TargetGO.transform.childCount; i++)
|
||||
{
|
||||
var child = TargetGO.transform.GetChild(i);
|
||||
s_allChildren[i] = child.gameObject;
|
||||
}
|
||||
|
||||
var objects = s_allChildren;
|
||||
s_childListPageHandler.ListCount = objects.Length;
|
||||
|
||||
//int startIndex = m_sceneListPageHandler.StartIndex;
|
||||
|
||||
int newCount = 0;
|
||||
|
||||
foreach (var itemIndex in s_childListPageHandler)
|
||||
{
|
||||
newCount++;
|
||||
|
||||
// normalized index starting from 0
|
||||
var i = itemIndex - s_childListPageHandler.StartIndex;
|
||||
|
||||
if (itemIndex >= objects.Length)
|
||||
{
|
||||
if (i > s_lastChildCount || i >= s_childListTexts.Count)
|
||||
break;
|
||||
|
||||
GameObject label = s_childListTexts[i].transform.parent.parent.gameObject;
|
||||
if (label.activeSelf)
|
||||
label.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject obj = objects[itemIndex];
|
||||
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
if (i >= s_childrenShortlist.Count)
|
||||
{
|
||||
s_childrenShortlist.Add(obj);
|
||||
AddChildListButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_childrenShortlist[i] = obj;
|
||||
}
|
||||
|
||||
var text = s_childListTexts[i];
|
||||
|
||||
var name = obj.name;
|
||||
|
||||
if (obj.transform.childCount > 0)
|
||||
name = $"<color=grey>[{obj.transform.childCount}]</color> {name}";
|
||||
|
||||
text.text = name;
|
||||
text.color = obj.activeSelf ? Color.green : Color.red;
|
||||
|
||||
var label = text.transform.parent.parent.gameObject;
|
||||
if (!label.activeSelf)
|
||||
{
|
||||
label.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_lastChildCount = newCount;
|
||||
}
|
||||
|
||||
private void RefreshComponentList()
|
||||
{
|
||||
s_allComps = TargetGO.GetComponents<Component>().ToArray();
|
||||
|
||||
var components = s_allComps;
|
||||
s_compListPageHandler.ListCount = components.Length;
|
||||
|
||||
//int startIndex = m_sceneListPageHandler.StartIndex;
|
||||
|
||||
int newCount = 0;
|
||||
|
||||
foreach (var itemIndex in s_compListPageHandler)
|
||||
{
|
||||
newCount++;
|
||||
|
||||
// normalized index starting from 0
|
||||
var i = itemIndex - s_compListPageHandler.StartIndex;
|
||||
|
||||
if (itemIndex >= components.Length)
|
||||
{
|
||||
if (i > s_lastCompCount || i >= s_compListTexts.Count)
|
||||
break;
|
||||
|
||||
GameObject label = s_compListTexts[i].transform.parent.parent.gameObject;
|
||||
if (label.activeSelf)
|
||||
label.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Component comp = components[itemIndex];
|
||||
|
||||
if (!comp)
|
||||
continue;
|
||||
|
||||
if (i >= s_compShortlist.Count)
|
||||
{
|
||||
s_compShortlist.Add(comp);
|
||||
AddCompListButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_compShortlist[i] = comp;
|
||||
}
|
||||
|
||||
var text = s_compListTexts[i];
|
||||
|
||||
text.text = ReflectionHelpers.GetActualType(comp).FullName;
|
||||
|
||||
var toggle = s_compToggles[i];
|
||||
if (comp is Behaviour behaviour)
|
||||
{
|
||||
if (!toggle.gameObject.activeSelf)
|
||||
toggle.gameObject.SetActive(true);
|
||||
|
||||
toggle.isOn = behaviour.enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (toggle.gameObject.activeSelf)
|
||||
toggle.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
var label = text.transform.parent.parent.gameObject;
|
||||
if (!label.activeSelf)
|
||||
{
|
||||
label.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_lastCompCount = newCount;
|
||||
}
|
||||
|
||||
private void ChangeInspectorTarget(GameObject newTarget)
|
||||
{
|
||||
if (!newTarget)
|
||||
return;
|
||||
|
||||
this.Target = this.TargetGO = newTarget;
|
||||
}
|
||||
|
||||
private static void ApplyNameClicked()
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.TargetGO.name = m_nameInput.text;
|
||||
}
|
||||
|
||||
private static void OnEnableToggled(bool enabled)
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.TargetGO.SetActive(enabled);
|
||||
}
|
||||
|
||||
private static void OnLayerSelected(int layer)
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.TargetGO.layer = layer;
|
||||
}
|
||||
|
||||
private static void OnCompToggleClicked(int index, bool value)
|
||||
{
|
||||
var comp = s_compShortlist[index];
|
||||
|
||||
(comp as Behaviour).enabled = value;
|
||||
}
|
||||
|
||||
#region CHILD LIST
|
||||
|
||||
private static void OnChildListObjectClicked(int index)
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
if (index >= s_childrenShortlist.Count || !s_childrenShortlist[index])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instance.ChangeInspectorTarget(s_childrenShortlist[index]);
|
||||
|
||||
instance.Update();
|
||||
}
|
||||
|
||||
private static void OnBackButtonClicked()
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.ChangeInspectorTarget(instance.TargetGO.transform.parent.gameObject);
|
||||
}
|
||||
|
||||
private static void OnChildListPageTurn()
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.RefreshChildObjectList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region COMPONENT LIST
|
||||
|
||||
private static void OnCompListObjectClicked(int index)
|
||||
{
|
||||
if (index >= s_compShortlist.Count || !s_compShortlist[index])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InspectorManager.Instance.Inspect(s_compShortlist[index]);
|
||||
}
|
||||
|
||||
private static void OnCompListPageTurn()
|
||||
{
|
||||
if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
instance.RefreshComponentList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
private void ConstructUI()
|
||||
{
|
||||
var parent = InspectorManager.Instance.m_inspectorContent;
|
||||
|
||||
m_content = UIFactory.CreateScrollView(parent, out GameObject scrollContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
var scrollGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
|
||||
scrollGroup.childForceExpandHeight = false;
|
||||
scrollGroup.childControlHeight = true;
|
||||
scrollGroup.spacing = 5;
|
||||
|
||||
ConstructTopArea(scrollContent);
|
||||
|
||||
var midGroupObj = UIFactory.CreateHorizontalGroup(scrollContent, new Color(1,1,1,0));
|
||||
var midGroup = midGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
midGroup.spacing = 5;
|
||||
midGroup.childForceExpandWidth = true;
|
||||
midGroup.childControlWidth = true;
|
||||
var midlayout = midGroupObj.AddComponent<LayoutElement>();
|
||||
midlayout.minHeight = 40;
|
||||
midlayout.flexibleHeight = 10000;
|
||||
midlayout.flexibleWidth = 25000;
|
||||
midlayout.minWidth = 200;
|
||||
|
||||
ConstructChildList(midGroupObj);
|
||||
ConstructCompList(midGroupObj);
|
||||
|
||||
ConstructControls(scrollContent);
|
||||
}
|
||||
|
||||
private void ConstructTopArea(GameObject scrollContent)
|
||||
{
|
||||
// path row
|
||||
|
||||
m_pathGroupObj = UIFactory.CreateHorizontalGroup(scrollContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
var pathGroup = m_pathGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
pathGroup.childForceExpandHeight = false;
|
||||
pathGroup.childForceExpandWidth = false;
|
||||
pathGroup.childControlHeight = false;
|
||||
pathGroup.childControlWidth = true;
|
||||
pathGroup.spacing = 5;
|
||||
var pathRect = m_pathGroupObj.GetComponent<RectTransform>();
|
||||
pathRect.sizeDelta = new Vector2(pathRect.sizeDelta.x, 20);
|
||||
var pathLayout = m_pathGroupObj.AddComponent<LayoutElement>();
|
||||
pathLayout.minHeight = 20;
|
||||
pathLayout.flexibleHeight = 75;
|
||||
|
||||
var backButtonObj = UIFactory.CreateButton(m_pathGroupObj);
|
||||
var backButton = backButtonObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
backButton.onClick.AddListener(new Action(OnBackButtonClicked));
|
||||
#else
|
||||
backButton.onClick.AddListener(OnBackButtonClicked());
|
||||
#endif
|
||||
var backText = backButtonObj.GetComponentInChildren<Text>();
|
||||
backText.text = "<";
|
||||
var backLayout = backButtonObj.AddComponent<LayoutElement>();
|
||||
backLayout.minWidth = 55;
|
||||
backLayout.flexibleWidth = 0;
|
||||
backLayout.minHeight = 25;
|
||||
backLayout.flexibleHeight = 0;
|
||||
|
||||
var pathHiddenTextObj = UIFactory.CreateLabel(m_pathGroupObj, TextAnchor.MiddleLeft);
|
||||
m_hiddenPathText = pathHiddenTextObj.GetComponent<Text>();
|
||||
m_hiddenPathText.color = Color.clear;
|
||||
m_hiddenPathText.fontSize = 14;
|
||||
m_hiddenPathText.raycastTarget = false;
|
||||
var hiddenFitter = pathHiddenTextObj.AddComponent<ContentSizeFitter>();
|
||||
hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
var hiddenLayout = pathHiddenTextObj.AddComponent<LayoutElement>();
|
||||
hiddenLayout.minHeight = 25;
|
||||
hiddenLayout.flexibleHeight = 75;
|
||||
hiddenLayout.minWidth = 400;
|
||||
hiddenLayout.flexibleWidth = 9000;
|
||||
var hiddenGroup = pathHiddenTextObj.AddComponent<HorizontalLayoutGroup>();
|
||||
hiddenGroup.childForceExpandWidth = true;
|
||||
hiddenGroup.childControlWidth = true;
|
||||
hiddenGroup.childForceExpandHeight = true;
|
||||
hiddenGroup.childControlHeight = true;
|
||||
|
||||
var pathInputObj = UIFactory.CreateTMPInput(pathHiddenTextObj, 14, 0, (int)TextAlignmentOptions.MidlineLeft);
|
||||
var pathInputRect = pathInputObj.GetComponent<RectTransform>();
|
||||
pathInputRect.sizeDelta = new Vector2(pathInputRect.sizeDelta.x, 25);
|
||||
m_pathInput = pathInputObj.GetComponent<TMP_InputField>();
|
||||
m_pathInput.text = TargetGO.transform.GetTransformPath();
|
||||
m_pathInput.readOnly = true;
|
||||
var pathInputLayout = pathInputObj.AddComponent<LayoutElement>();
|
||||
pathInputLayout.minHeight = 25;
|
||||
pathInputLayout.flexibleHeight = 75;
|
||||
pathInputLayout.preferredWidth = 400;
|
||||
pathInputLayout.flexibleWidth = 9999;
|
||||
|
||||
// name row
|
||||
|
||||
var nameRowObj = UIFactory.CreateHorizontalGroup(scrollContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
var nameGroup = nameRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||
nameGroup.childForceExpandHeight = false;
|
||||
nameGroup.childForceExpandWidth = false;
|
||||
nameGroup.childControlHeight = false;
|
||||
nameGroup.childControlWidth = true;
|
||||
nameGroup.spacing = 5;
|
||||
var nameRect = nameRowObj.GetComponent<RectTransform>();
|
||||
nameRect.sizeDelta = new Vector2(nameRect.sizeDelta.x, 25);
|
||||
var nameLayout = nameRowObj.AddComponent<LayoutElement>();
|
||||
nameLayout.minHeight = 25;
|
||||
nameLayout.flexibleHeight = 0;
|
||||
|
||||
var nameTextObj = UIFactory.CreateTMPLabel(nameRowObj, TextAlignmentOptions.Midline);
|
||||
var nameTextText = nameTextObj.GetComponent<TextMeshProUGUI>();
|
||||
nameTextText.text = "Name:";
|
||||
nameTextText.fontSize = 14;
|
||||
nameTextText.color = Color.grey;
|
||||
var nameTextLayout = nameTextObj.AddComponent<LayoutElement>();
|
||||
nameTextLayout.minHeight = 25;
|
||||
nameTextLayout.flexibleHeight = 0;
|
||||
nameTextLayout.minWidth = 55;
|
||||
nameTextLayout.flexibleWidth = 0;
|
||||
|
||||
var nameInputObj = UIFactory.CreateTMPInput(nameRowObj, 14, 0, (int)TextAlignmentOptions.MidlineLeft);
|
||||
var nameInputRect = nameInputObj.GetComponent<RectTransform>();
|
||||
nameInputRect.sizeDelta = new Vector2(nameInputRect.sizeDelta.x, 25);
|
||||
m_nameInput = nameInputObj.GetComponent<TMP_InputField>();
|
||||
m_nameInput.text = TargetGO.name;
|
||||
m_nameInput.lineType = TMP_InputField.LineType.SingleLine;
|
||||
|
||||
var applyNameBtnObj = UIFactory.CreateButton(nameRowObj);
|
||||
var applyNameBtn = applyNameBtnObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
applyNameBtn.onClick.AddListener(new Action(() => { ApplyNameClicked(); }));
|
||||
#else
|
||||
applyNameBtn.onClick.AddListener(() => { ApplyNameClicked(); });
|
||||
#endif
|
||||
var applyNameText = applyNameBtnObj.GetComponentInChildren<Text>();
|
||||
applyNameText.text = "Apply";
|
||||
applyNameText.fontSize = 14;
|
||||
var applyNameLayout = applyNameBtnObj.AddComponent<LayoutElement>();
|
||||
applyNameLayout.minWidth = 65;
|
||||
applyNameLayout.minHeight = 25;
|
||||
applyNameLayout.flexibleHeight = 0;
|
||||
var applyNameRect = applyNameBtnObj.GetComponent<RectTransform>();
|
||||
applyNameRect.sizeDelta = new Vector2(applyNameRect.sizeDelta.x, 25);
|
||||
|
||||
var activeLabel = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleCenter);
|
||||
var activeLabelLayout = activeLabel.AddComponent<LayoutElement>();
|
||||
activeLabelLayout.minWidth = 55;
|
||||
activeLabelLayout.minHeight = 25;
|
||||
var activeText = activeLabel.GetComponent<Text>();
|
||||
activeText.text = "Active:";
|
||||
activeText.color = Color.grey;
|
||||
activeText.fontSize = 14;
|
||||
|
||||
var enabledToggleObj = UIFactory.CreateToggle(nameRowObj, out m_enabledToggle, out m_enabledText);
|
||||
var toggleLayout = enabledToggleObj.AddComponent<LayoutElement>();
|
||||
toggleLayout.minHeight = 25;
|
||||
toggleLayout.minWidth = 100;
|
||||
toggleLayout.flexibleWidth = 0;
|
||||
m_enabledText.text = "Enabled";
|
||||
m_enabledText.color = Color.green;
|
||||
#if CPP
|
||||
m_enabledToggle.onValueChanged.AddListener(new Action<bool>(OnEnableToggled));
|
||||
#else
|
||||
m_enabledToggle.onValueChanged.AddListener(OnEnableToggled);
|
||||
#endif
|
||||
|
||||
// layer and scene row
|
||||
|
||||
var sceneLayerRow = UIFactory.CreateHorizontalGroup(scrollContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
var sceneLayerGroup = sceneLayerRow.GetComponent<HorizontalLayoutGroup>();
|
||||
sceneLayerGroup.childForceExpandWidth = false;
|
||||
sceneLayerGroup.childControlWidth = true;
|
||||
sceneLayerGroup.spacing = 5;
|
||||
|
||||
var layerLabel = UIFactory.CreateLabel(sceneLayerRow, TextAnchor. MiddleCenter);
|
||||
var layerText = layerLabel.GetComponent<Text>();
|
||||
layerText.text = "Layer:";
|
||||
layerText.fontSize = 14;
|
||||
layerText.color = Color.grey;
|
||||
var layerTextLayout = layerLabel.AddComponent<LayoutElement>();
|
||||
layerTextLayout.minWidth = 55;
|
||||
layerTextLayout.flexibleWidth = 0;
|
||||
|
||||
var layerDropdownObj = UIFactory.CreateDropdown(sceneLayerRow, out m_layerDropdown);
|
||||
m_layerDropdown.options.Clear();
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
var layer = LayerMaskUnstrip.LayerToName(i);
|
||||
m_layerDropdown.options.Add(new Dropdown.OptionData { text = $"{i}: {layer}" });
|
||||
}
|
||||
var itemText = layerDropdownObj.transform.Find("Label").GetComponent<Text>();
|
||||
itemText.resizeTextForBestFit = true;
|
||||
var layerDropdownLayout = layerDropdownObj.AddComponent<LayoutElement>();
|
||||
layerDropdownLayout.minWidth = 120;
|
||||
layerDropdownLayout.flexibleWidth = 2000;
|
||||
layerDropdownLayout.minHeight = 25;
|
||||
#if CPP
|
||||
m_layerDropdown.onValueChanged.AddListener(new Action<int>(OnLayerSelected));
|
||||
#else
|
||||
m_layerDropdown.onValueChanged.AddListener(OnLayerSelected);
|
||||
#endif
|
||||
|
||||
var scenelabelObj = UIFactory.CreateLabel(sceneLayerRow, TextAnchor.MiddleCenter);
|
||||
var sceneLabel = scenelabelObj.GetComponent<Text>();
|
||||
sceneLabel.text = "Scene:";
|
||||
sceneLabel.color = Color.grey;
|
||||
sceneLabel.fontSize = 14;
|
||||
var sceneLabelLayout = scenelabelObj.AddComponent<LayoutElement>();
|
||||
sceneLabelLayout.minWidth = 55;
|
||||
sceneLabelLayout.flexibleWidth = 0;
|
||||
|
||||
var objectSceneText = UIFactory.CreateLabel(sceneLayerRow, TextAnchor.MiddleLeft);
|
||||
m_sceneText = objectSceneText.GetComponent<Text>();
|
||||
m_sceneText.fontSize = 14;
|
||||
m_sceneText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
var sceneTextLayout = objectSceneText.AddComponent<LayoutElement>();
|
||||
sceneTextLayout.minWidth = 120;
|
||||
sceneTextLayout.flexibleWidth = 2000;
|
||||
}
|
||||
|
||||
private void ConstructChildList(GameObject parent)
|
||||
{
|
||||
var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1,1,1,0));
|
||||
var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>();
|
||||
vertGroup.childForceExpandHeight = false;
|
||||
vertGroup.childForceExpandWidth = false;
|
||||
vertGroup.childControlWidth = true;
|
||||
var vertLayout = vertGroupObj.AddComponent<LayoutElement>();
|
||||
vertLayout.minWidth = 120;
|
||||
vertLayout.flexibleWidth = 25000;
|
||||
|
||||
var childTitleObj = UIFactory.CreateLabel(vertGroupObj, TextAnchor.MiddleLeft);
|
||||
var childTitleText = childTitleObj.GetComponent<Text>();
|
||||
childTitleText.text = "Children";
|
||||
childTitleText.color = Color.grey;
|
||||
childTitleText.fontSize = 14;
|
||||
var childTitleLayout = childTitleObj.AddComponent<LayoutElement>();
|
||||
childTitleLayout.minHeight = 30;
|
||||
|
||||
var childrenScrollObj = UIFactory.CreateScrollView(vertGroupObj, out s_childListContent, new Color(0.07f, 0.07f, 0.07f));
|
||||
var contentLayout = childrenScrollObj.AddComponent<LayoutElement>();
|
||||
contentLayout.minHeight = 50;
|
||||
contentLayout.flexibleHeight = 10000;
|
||||
|
||||
var horiScroll = childrenScrollObj.transform.Find("Scrollbar Horizontal");
|
||||
horiScroll.gameObject.SetActive(false);
|
||||
|
||||
var scrollRect = childrenScrollObj.GetComponentInChildren<ScrollRect>();
|
||||
scrollRect.horizontalScrollbar = null;
|
||||
|
||||
var childGroup = s_childListContent.GetComponent<VerticalLayoutGroup>();
|
||||
childGroup.childControlHeight = true;
|
||||
childGroup.spacing = 2;
|
||||
|
||||
s_childListPageHandler = new PageHandler();
|
||||
s_childListPageHandler.ConstructUI(vertGroupObj);
|
||||
s_childListPageHandler.OnPageChanged += OnChildListPageTurn;
|
||||
}
|
||||
|
||||
private void AddChildListButton()
|
||||
{
|
||||
int thisIndex = s_childListTexts.Count;
|
||||
|
||||
GameObject btnGroupObj = UIFactory.CreateHorizontalGroup(s_childListContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
HorizontalLayoutGroup btnGroup = btnGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
btnGroup.childForceExpandWidth = true;
|
||||
btnGroup.childControlWidth = true;
|
||||
btnGroup.childForceExpandHeight = false;
|
||||
btnGroup.childControlHeight = true;
|
||||
LayoutElement btnLayout = btnGroupObj.AddComponent<LayoutElement>();
|
||||
btnLayout.flexibleWidth = 320;
|
||||
btnLayout.minHeight = 25;
|
||||
btnLayout.flexibleHeight = 0;
|
||||
btnGroupObj.AddComponent<Mask>();
|
||||
|
||||
GameObject mainButtonObj = UIFactory.CreateButton(btnGroupObj);
|
||||
LayoutElement mainBtnLayout = mainButtonObj.AddComponent<LayoutElement>();
|
||||
mainBtnLayout.minHeight = 25;
|
||||
mainBtnLayout.flexibleHeight = 0;
|
||||
mainBtnLayout.minWidth = 240;
|
||||
mainBtnLayout.flexibleWidth = 0;
|
||||
Button mainBtn = mainButtonObj.GetComponent<Button>();
|
||||
ColorBlock mainColors = mainBtn.colors;
|
||||
mainColors.normalColor = new Color(0.07f, 0.07f, 0.07f);
|
||||
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||
mainBtn.colors = mainColors;
|
||||
#if CPP
|
||||
mainBtn.onClick.AddListener(new Action(() => { OnChildListObjectClicked(thisIndex); }));
|
||||
#else
|
||||
mainBtn.onClick.AddListener(() => { OnChildListObjectClicked(thisIndex); });
|
||||
#endif
|
||||
|
||||
Text mainText = mainButtonObj.GetComponentInChildren<Text>();
|
||||
mainText.alignment = TextAnchor.MiddleLeft;
|
||||
mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
s_childListTexts.Add(mainText);
|
||||
}
|
||||
|
||||
private void ConstructCompList(GameObject parent)
|
||||
{
|
||||
var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1, 1, 1, 0));
|
||||
var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>();
|
||||
vertGroup.childForceExpandHeight = false;
|
||||
vertGroup.childForceExpandWidth = false;
|
||||
vertGroup.childControlWidth = true;
|
||||
var vertLayout = vertGroupObj.AddComponent<LayoutElement>();
|
||||
vertLayout.minWidth = 120;
|
||||
vertLayout.flexibleWidth = 25000;
|
||||
|
||||
var compTitleObj = UIFactory.CreateLabel(vertGroupObj, TextAnchor.MiddleLeft);
|
||||
var compTitleText = compTitleObj.GetComponent<Text>();
|
||||
compTitleText.text = "Components";
|
||||
compTitleText.color = Color.grey;
|
||||
compTitleText.fontSize = 14;
|
||||
var childTitleLayout = compTitleObj.AddComponent<LayoutElement>();
|
||||
childTitleLayout.minHeight = 30;
|
||||
|
||||
var compScrollObj = UIFactory.CreateScrollView(vertGroupObj, out s_compListContent, new Color(0.07f, 0.07f, 0.07f));
|
||||
var contentLayout = compScrollObj.AddComponent<LayoutElement>();
|
||||
contentLayout.minHeight = 50;
|
||||
contentLayout.flexibleHeight = 10000;
|
||||
|
||||
var contentGroup = s_compListContent.GetComponent<VerticalLayoutGroup>();
|
||||
contentGroup.childControlHeight = true;
|
||||
contentGroup.spacing = 2;
|
||||
|
||||
var horiScroll = compScrollObj.transform.Find("Scrollbar Horizontal");
|
||||
horiScroll.gameObject.SetActive(false);
|
||||
|
||||
var scrollRect = compScrollObj.GetComponentInChildren<ScrollRect>();
|
||||
scrollRect.horizontalScrollbar = null;
|
||||
|
||||
s_compListPageHandler = new PageHandler();
|
||||
s_compListPageHandler.ConstructUI(vertGroupObj);
|
||||
s_compListPageHandler.OnPageChanged += OnCompListPageTurn;
|
||||
}
|
||||
|
||||
private void AddCompListButton()
|
||||
{
|
||||
int thisIndex = s_compListTexts.Count;
|
||||
|
||||
GameObject btnGroupObj = UIFactory.CreateHorizontalGroup(s_compListContent, new Color(0.07f, 0.07f, 0.07f));
|
||||
HorizontalLayoutGroup btnGroup = btnGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
btnGroup.childForceExpandWidth = false;
|
||||
btnGroup.childControlWidth = true;
|
||||
btnGroup.childForceExpandHeight = false;
|
||||
btnGroup.childControlHeight = true;
|
||||
btnGroup.childAlignment = TextAnchor.MiddleLeft;
|
||||
LayoutElement btnLayout = btnGroupObj.AddComponent<LayoutElement>();
|
||||
btnLayout.flexibleWidth = 320;
|
||||
btnLayout.minHeight = 25;
|
||||
btnLayout.flexibleHeight = 0;
|
||||
btnGroupObj.AddComponent<Mask>();
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(btnGroupObj, out Toggle toggle, out Text toggleText);
|
||||
var togBg = toggleObj.transform.Find("Background").GetComponent<Image>();
|
||||
togBg.color = new Color(0.1f, 0.1f, 0.1f, 1);
|
||||
var toggleLayout = toggleObj.AddComponent<LayoutElement>();
|
||||
toggleLayout.minWidth = 25;
|
||||
toggleLayout.flexibleWidth = 0;
|
||||
toggleLayout.minHeight = 25;
|
||||
toggleLayout.flexibleHeight = 0;
|
||||
#if CPP
|
||||
toggle.onValueChanged.AddListener(new Action<bool>((bool val) => { OnCompToggleClicked(thisIndex, val); }));
|
||||
#else
|
||||
toggle.onValueChanged.AddListener((bool val) => { OnCompToggleClicked(thisIndex, val); });
|
||||
#endif
|
||||
toggleText.text = "";
|
||||
s_compToggles.Add(toggle);
|
||||
|
||||
GameObject mainButtonObj = UIFactory.CreateButton(btnGroupObj);
|
||||
LayoutElement mainBtnLayout = mainButtonObj.AddComponent<LayoutElement>();
|
||||
mainBtnLayout.minHeight = 25;
|
||||
mainBtnLayout.flexibleHeight = 0;
|
||||
mainBtnLayout.minWidth = 240;
|
||||
mainBtnLayout.flexibleWidth = 999;
|
||||
Button mainBtn = mainButtonObj.GetComponent<Button>();
|
||||
ColorBlock mainColors = mainBtn.colors;
|
||||
mainColors.normalColor = new Color(0.07f, 0.07f, 0.07f);
|
||||
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||
mainBtn.colors = mainColors;
|
||||
#if CPP
|
||||
mainBtn.onClick.AddListener(new Action(() => { OnCompListObjectClicked(thisIndex); }));
|
||||
#else
|
||||
mainBtn.onClick.AddListener(() => { OnCompListObjectClicked(thisIndex); });
|
||||
#endif
|
||||
|
||||
Text mainText = mainButtonObj.GetComponentInChildren<Text>();
|
||||
mainText.alignment = TextAnchor.MiddleLeft;
|
||||
mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
mainText.color = Syntax.Class_Instance.ToColor();
|
||||
s_compListTexts.Add(mainText);
|
||||
}
|
||||
|
||||
private const int CONTROLS_MAX_HEIGHT = 220;
|
||||
|
||||
private void ConstructControls(GameObject scrollContent)
|
||||
{
|
||||
var controlsObj = UIFactory.CreateVerticalGroup(scrollContent, new Color(0.07f, 0.07f, 0.07f));
|
||||
var controlsGroup = controlsObj.GetComponent<VerticalLayoutGroup>();
|
||||
controlsGroup.childForceExpandWidth = false;
|
||||
controlsGroup.childControlWidth = true;
|
||||
controlsGroup.childForceExpandHeight = false;
|
||||
var controlsLayout = controlsObj.AddComponent<LayoutElement>();
|
||||
controlsLayout.minHeight = CONTROLS_MAX_HEIGHT;
|
||||
controlsLayout.flexibleHeight = 0;
|
||||
controlsLayout.minWidth = 250;
|
||||
controlsLayout.flexibleWidth = 9000;
|
||||
|
||||
// ~~~~~~ Top row ~~~~~~
|
||||
|
||||
var topRow = UIFactory.CreateHorizontalGroup(controlsObj, new Color(1, 1, 1, 0));
|
||||
var topRowGroup = topRow.GetComponent<HorizontalLayoutGroup>();
|
||||
topRowGroup.childForceExpandWidth = false;
|
||||
topRowGroup.childControlWidth = true;
|
||||
topRowGroup.childForceExpandHeight = false;
|
||||
topRowGroup.childControlHeight = true;
|
||||
topRowGroup.spacing = 5;
|
||||
|
||||
var hideButtonObj = UIFactory.CreateButton(topRow);
|
||||
var hideButton = hideButtonObj.GetComponent<Button>();
|
||||
var hideText = hideButtonObj.GetComponentInChildren<Text>();
|
||||
hideText.text = "v";
|
||||
var hideButtonLayout = hideButtonObj.AddComponent<LayoutElement>();
|
||||
hideButtonLayout.minWidth = 40;
|
||||
hideButtonLayout.flexibleWidth = 0;
|
||||
hideButtonLayout.minHeight = 25;
|
||||
hideButtonLayout.flexibleHeight = 0;
|
||||
#if CPP
|
||||
hideButton.onClick.AddListener(new Action(OnHideClicked));
|
||||
#else
|
||||
hideButton.onClick.AddListener(OnHideClicked);
|
||||
#endif
|
||||
void OnHideClicked()
|
||||
{
|
||||
if (controlsLayout.minHeight > 25)
|
||||
{
|
||||
hideText.text = "^";
|
||||
controlsLayout.minHeight = 25;
|
||||
}
|
||||
else
|
||||
{
|
||||
hideText.text = "v";
|
||||
controlsLayout.minHeight = CONTROLS_MAX_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
var topTitle = UIFactory.CreateLabel(topRow, TextAnchor.MiddleLeft);
|
||||
var topText = topTitle.GetComponent<Text>();
|
||||
topText.text = "GameObject Controls";
|
||||
var titleLayout = topTitle.AddComponent<LayoutElement>();
|
||||
titleLayout.minWidth = 100;
|
||||
titleLayout.flexibleWidth = 9500;
|
||||
titleLayout.minHeight = 25;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Inspectors
|
||||
{
|
||||
public abstract class InspectorBase
|
||||
{
|
||||
public object Target;
|
||||
// just to cache a cast
|
||||
public UnityEngine.Object UnityTarget;
|
||||
|
||||
public abstract string TabLabel { get; }
|
||||
|
||||
public abstract GameObject Content { get; set; }
|
||||
public Button tabButton;
|
||||
public Text tabText;
|
||||
|
||||
internal bool m_pendingDestroy;
|
||||
|
||||
public InspectorBase(object target)
|
||||
{
|
||||
Target = target;
|
||||
UnityTarget = target as UnityEngine.Object;
|
||||
|
||||
if (ObjectNullOrDestroyed(Target, UnityTarget))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
AddInspectorTab();
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (ObjectNullOrDestroyed(Target, UnityTarget))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
tabText.text = TabLabel;
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
m_pendingDestroy = true;
|
||||
|
||||
GameObject tabGroup = tabButton?.transform.parent.gameObject;
|
||||
|
||||
if (tabGroup)
|
||||
{
|
||||
GameObject.Destroy(tabGroup);
|
||||
}
|
||||
|
||||
//if (Content)
|
||||
//{
|
||||
// GameObject.Destroy(Content);
|
||||
//}
|
||||
|
||||
int thisIndex = -1;
|
||||
if (InspectorManager.Instance.m_currentInspectors.Contains(this))
|
||||
{
|
||||
thisIndex = InspectorManager.Instance.m_currentInspectors.IndexOf(this);
|
||||
InspectorManager.Instance.m_currentInspectors.Remove(this);
|
||||
}
|
||||
|
||||
if (ReferenceEquals(InspectorManager.Instance.m_activeInspector, this))
|
||||
{
|
||||
InspectorManager.Instance.UnsetInspectorTab();
|
||||
|
||||
if (InspectorManager.Instance.m_currentInspectors.Count > 0)
|
||||
{
|
||||
var prevTab = InspectorManager.Instance.m_currentInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
|
||||
InspectorManager.Instance.SetInspectorTab(prevTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ObjectNullOrDestroyed(object obj, UnityEngine.Object unityObj, bool suppressWarning = false)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
if (!suppressWarning)
|
||||
{
|
||||
ExplorerCore.LogWarning("The target instance is null!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (obj is UnityEngine.Object)
|
||||
{
|
||||
if (!unityObj)
|
||||
{
|
||||
if (!suppressWarning)
|
||||
{
|
||||
ExplorerCore.LogWarning("The target UnityEngine.Object was destroyed!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
public void AddInspectorTab()
|
||||
{
|
||||
var tabContent = InspectorManager.Instance.m_tabBarContent;
|
||||
|
||||
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent);
|
||||
var tabGroup = tabGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
tabGroup.childForceExpandWidth = true;
|
||||
tabGroup.childControlWidth = true;
|
||||
var tabLayout = tabGroupObj.AddComponent<LayoutElement>();
|
||||
tabLayout.minWidth = 185;
|
||||
tabLayout.flexibleWidth = 0;
|
||||
tabGroupObj.AddComponent<Mask>();
|
||||
|
||||
var targetButtonObj = UIFactory.CreateButton(tabGroupObj);
|
||||
var targetButtonLayout = targetButtonObj.AddComponent<LayoutElement>();
|
||||
targetButtonLayout.minWidth = 165;
|
||||
targetButtonLayout.flexibleWidth = 0;
|
||||
|
||||
tabText = targetButtonObj.GetComponentInChildren<Text>();
|
||||
tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
tabText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
tabButton = targetButtonObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
tabButton.onClick.AddListener(new Action(() => { InspectorManager.Instance.SetInspectorTab(this); }));
|
||||
#else
|
||||
tabButton.onClick.AddListener(() => { InspectorManager.Instance.SetInspectorTab(this); });
|
||||
#endif
|
||||
var closeBtnObj = UIFactory.CreateButton(tabGroupObj);
|
||||
var closeBtnLayout = closeBtnObj.AddComponent<LayoutElement>();
|
||||
closeBtnLayout.minWidth = 20;
|
||||
closeBtnLayout.flexibleWidth = 0;
|
||||
var closeBtnText = closeBtnObj.GetComponentInChildren<Text>();
|
||||
closeBtnText.text = "X";
|
||||
closeBtnText.color = new Color(1, 0, 0, 1);
|
||||
|
||||
var closeBtn = closeBtnObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
closeBtn.onClick.AddListener(new Action(() => { Destroy(); }));
|
||||
#else
|
||||
closeBtn.onClick.AddListener(() => { Destroy(); });
|
||||
#endif
|
||||
|
||||
var closeColors = closeBtn.colors;
|
||||
closeColors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||
closeBtn.colors = closeColors;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using UnityExplorer.Helpers;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Inspectors
|
||||
{
|
||||
public class InstanceInspector : ReflectionInspector
|
||||
{
|
||||
// todo
|
||||
public override string TabLabel => $" [R] {base.TabLabel}";
|
||||
|
||||
public InstanceInspector(object target) : base(target)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (m_pendingDestroy || InspectorManager.Instance.m_activeInspector != this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// todo
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.Helpers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Inspectors
|
||||
{
|
||||
public class ReflectionInspector : InspectorBase
|
||||
{
|
||||
public override string TabLabel => m_targetTypeShortName;
|
||||
|
||||
private GameObject m_content;
|
||||
public override GameObject Content
|
||||
{
|
||||
get => m_content;
|
||||
set => m_content = value;
|
||||
}
|
||||
|
||||
private readonly string m_targetTypeShortName;
|
||||
|
||||
public ReflectionInspector(object target) : base(target)
|
||||
{
|
||||
Type type = ReflectionHelpers.GetActualType(target);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
m_targetTypeShortName = type.Name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace UnityExplorer.UI.Main.Inspectors
|
||||
{
|
||||
public class StaticInspector : ReflectionInspector
|
||||
{
|
||||
public override string TabLabel => $" [S] {base.TabLabel}";
|
||||
|
||||
public StaticInspector(Type type) : base(type)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (m_pendingDestroy || InspectorManager.Instance.m_activeInspector != this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// todo
|
||||
}
|
||||
}
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityExplorer.UI.Main.Console;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class MainMenu
|
||||
{
|
||||
public abstract class Page
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
|
||||
public GameObject Content;
|
||||
public Button RefNavbarButton { get; set; }
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => Content?.activeSelf ?? false;
|
||||
set => Content?.SetActive(true);
|
||||
}
|
||||
|
||||
|
||||
public abstract void Init();
|
||||
public abstract void Update();
|
||||
}
|
||||
|
||||
public static MainMenu Instance { get; set; }
|
||||
|
||||
public PanelDragger Dragger { get; private set; }
|
||||
|
||||
public GameObject MainPanel { get; private set; }
|
||||
public GameObject PageViewport { get; private set; }
|
||||
|
||||
public readonly List<Page> Pages = new List<Page>();
|
||||
private Page m_activePage;
|
||||
|
||||
// Navbar buttons
|
||||
private Button m_lastNavButtonPressed;
|
||||
private readonly Color m_navButtonNormal = new Color(0.3f, 0.3f, 0.3f, 1);
|
||||
private readonly Color m_navButtonHighlight = new Color(0.3f, 0.6f, 0.3f);
|
||||
private readonly Color m_navButtonSelected = new Color(0.2f, 0.5f, 0.2f, 1);
|
||||
|
||||
public MainMenu()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
ExplorerCore.LogWarning("An instance of MainMenu already exists, cannot create another!");
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
|
||||
Pages.Add(new HomePage());
|
||||
Pages.Add(new SearchPage());
|
||||
// TODO remove page on games where it failed to init?
|
||||
Pages.Add(new ConsolePage());
|
||||
Pages.Add(new OptionsPage());
|
||||
|
||||
ConstructMenu();
|
||||
|
||||
foreach (Page page in Pages)
|
||||
{
|
||||
page.Init();
|
||||
page.Content?.SetActive(false);
|
||||
}
|
||||
|
||||
SetPage(Pages[0]);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
m_activePage?.Update();
|
||||
}
|
||||
|
||||
public void SetPage(Page page)
|
||||
{
|
||||
if (m_activePage == page || page == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_activePage?.Content?.SetActive(false);
|
||||
if (m_activePage is ConsolePage)
|
||||
{
|
||||
AutoCompleter.m_mainObj?.SetActive(false);
|
||||
}
|
||||
|
||||
m_activePage = page;
|
||||
|
||||
m_activePage.Content?.SetActive(true);
|
||||
|
||||
Button button = page.RefNavbarButton;
|
||||
|
||||
ColorBlock colors = button.colors;
|
||||
colors.normalColor = m_navButtonSelected;
|
||||
//try { colors.selectedColor = m_navButtonSelected; } catch { }
|
||||
button.colors = colors;
|
||||
|
||||
if (m_lastNavButtonPressed && m_lastNavButtonPressed != button)
|
||||
{
|
||||
ColorBlock oldColors = m_lastNavButtonPressed.colors;
|
||||
oldColors.normalColor = m_navButtonNormal;
|
||||
//try { oldColors.selectedColor = m_navButtonNormal; } catch { }
|
||||
m_lastNavButtonPressed.colors = oldColors;
|
||||
}
|
||||
|
||||
m_lastNavButtonPressed = button;
|
||||
}
|
||||
|
||||
#region UI Construction
|
||||
|
||||
private void ConstructMenu()
|
||||
{
|
||||
MainPanel = UIFactory.CreatePanel(UIManager.CanvasRoot, "MainMenu", out GameObject content);
|
||||
|
||||
RectTransform panelRect = MainPanel.GetComponent<RectTransform>();
|
||||
panelRect.anchorMin = new Vector2(0.25f, 0.1f);
|
||||
panelRect.anchorMax = new Vector2(0.78f, 0.95f);
|
||||
|
||||
ConstructTitleBar(content);
|
||||
|
||||
ConstructNavbar(content);
|
||||
|
||||
ConstructMainViewport(content);
|
||||
|
||||
new DebugConsole(content);
|
||||
}
|
||||
|
||||
private void ConstructTitleBar(GameObject content)
|
||||
{
|
||||
// Core title bar holder
|
||||
|
||||
GameObject titleBar = UIFactory.CreateHorizontalGroup(content);
|
||||
|
||||
HorizontalLayoutGroup titleGroup = titleBar.GetComponent<HorizontalLayoutGroup>();
|
||||
titleGroup.childControlHeight = true;
|
||||
titleGroup.childControlWidth = true;
|
||||
titleGroup.childForceExpandHeight = true;
|
||||
titleGroup.childForceExpandWidth = true;
|
||||
titleGroup.padding.left = 15;
|
||||
titleGroup.padding.right = 3;
|
||||
titleGroup.padding.top = 3;
|
||||
titleGroup.padding.bottom = 3;
|
||||
|
||||
LayoutElement titleLayout = titleBar.AddComponent<LayoutElement>();
|
||||
titleLayout.minHeight = 35;
|
||||
titleLayout.flexibleHeight = 0;
|
||||
|
||||
// Explorer label
|
||||
|
||||
GameObject textObj = UIFactory.CreateLabel(titleBar, TextAnchor.MiddleLeft);
|
||||
|
||||
Text text = textObj.GetComponent<Text>();
|
||||
text.text = $"<b>UnityExplorer</b> <i>v{ExplorerCore.VERSION}</i>";
|
||||
text.resizeTextForBestFit = true;
|
||||
text.resizeTextMinSize = 12;
|
||||
text.resizeTextMaxSize = 20;
|
||||
|
||||
LayoutElement textLayout = textObj.AddComponent<LayoutElement>();
|
||||
textLayout.flexibleWidth = 50;
|
||||
|
||||
// Add PanelDragger using the label object
|
||||
|
||||
Dragger = new PanelDragger(titleBar.GetComponent<RectTransform>(), MainPanel.GetComponent<RectTransform>());
|
||||
|
||||
// Hide button
|
||||
|
||||
GameObject hideBtnObj = UIFactory.CreateButton(titleBar);
|
||||
|
||||
Button hideBtn = hideBtnObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
hideBtn.onClick.AddListener(new Action(() => { ExplorerCore.ShowMenu = false; }));
|
||||
#else
|
||||
hideBtn.onClick.AddListener(() => { ExplorerCore.ShowMenu = false; });
|
||||
#endif
|
||||
ColorBlock colorBlock = hideBtn.colors;
|
||||
colorBlock.normalColor = new Color(65f / 255f, 23f / 255f, 23f / 255f);
|
||||
colorBlock.pressedColor = new Color(35f / 255f, 10f / 255f, 10f / 255f);
|
||||
colorBlock.highlightedColor = new Color(156f / 255f, 0f, 0f);
|
||||
hideBtn.colors = colorBlock;
|
||||
|
||||
LayoutElement btnLayout = hideBtnObj.AddComponent<LayoutElement>();
|
||||
btnLayout.minWidth = 90;
|
||||
btnLayout.flexibleWidth = 2;
|
||||
|
||||
Text hideText = hideBtnObj.GetComponentInChildren<Text>();
|
||||
// Todo use actual keycode from mod config, update on OnSettingsChanged or whatever
|
||||
hideText.text = "Hide (F7)";
|
||||
hideText.color = Color.white;
|
||||
hideText.resizeTextForBestFit = true;
|
||||
hideText.resizeTextMinSize = 8;
|
||||
hideText.resizeTextMaxSize = 16;
|
||||
}
|
||||
|
||||
private void ConstructNavbar(GameObject content)
|
||||
{
|
||||
GameObject navbarObj = UIFactory.CreateHorizontalGroup(content);
|
||||
|
||||
HorizontalLayoutGroup navGroup = navbarObj.GetComponent<HorizontalLayoutGroup>();
|
||||
navGroup.padding.left = 3;
|
||||
navGroup.padding.right = 3;
|
||||
navGroup.padding.top = 3;
|
||||
navGroup.padding.bottom = 3;
|
||||
navGroup.spacing = 5;
|
||||
navGroup.childControlHeight = true;
|
||||
navGroup.childControlWidth = true;
|
||||
navGroup.childForceExpandHeight = true;
|
||||
navGroup.childForceExpandWidth = true;
|
||||
|
||||
LayoutElement navLayout = navbarObj.AddComponent<LayoutElement>();
|
||||
navLayout.minHeight = 35;
|
||||
navLayout.flexibleHeight = 0;
|
||||
|
||||
foreach (Page page in Pages)
|
||||
{
|
||||
GameObject btnObj = UIFactory.CreateButton(navbarObj);
|
||||
Button btn = btnObj.GetComponent<Button>();
|
||||
|
||||
page.RefNavbarButton = btn;
|
||||
|
||||
#if CPP
|
||||
btn.onClick.AddListener(new Action(() => { SetPage(page); }));
|
||||
#else
|
||||
btn.onClick.AddListener(() => { SetPage(page); });
|
||||
#endif
|
||||
|
||||
Text text = btnObj.GetComponentInChildren<Text>();
|
||||
text.text = page.Name;
|
||||
|
||||
// Set button colors
|
||||
ColorBlock colorBlock = btn.colors;
|
||||
colorBlock.normalColor = m_navButtonNormal;
|
||||
//try { colorBlock.selectedColor = colorBlock.normalColor; } catch { }
|
||||
colorBlock.highlightedColor = m_navButtonHighlight;
|
||||
colorBlock.pressedColor = m_navButtonSelected;
|
||||
btn.colors = colorBlock;
|
||||
}
|
||||
}
|
||||
|
||||
private void ConstructMainViewport(GameObject content)
|
||||
{
|
||||
GameObject mainObj = UIFactory.CreateHorizontalGroup(content);
|
||||
HorizontalLayoutGroup mainGroup = mainObj.GetComponent<HorizontalLayoutGroup>();
|
||||
mainGroup.childControlHeight = true;
|
||||
mainGroup.childControlWidth = true;
|
||||
mainGroup.childForceExpandHeight = true;
|
||||
mainGroup.childForceExpandWidth = true;
|
||||
|
||||
PageViewport = mainObj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class OptionsPage : MainMenu.Page
|
||||
{
|
||||
public override string Name => "Options / Misc";
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,363 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Input;
|
||||
using System.IO;
|
||||
#if CPP
|
||||
using UnityExplorer.Unstrip.ImageConversion;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
// Handles dragging and resizing for the main explorer window.
|
||||
|
||||
public class PanelDragger
|
||||
{
|
||||
public static PanelDragger Instance { get; private set; }
|
||||
|
||||
public RectTransform Panel { get; set; }
|
||||
|
||||
private static bool s_loadedCursorImage;
|
||||
|
||||
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag)
|
||||
{
|
||||
Instance = this;
|
||||
DragableArea = dragArea;
|
||||
Panel = panelToDrag;
|
||||
|
||||
UpdateResizeCache();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Vector3 rawMousePos = InputManager.MousePosition;
|
||||
|
||||
ResizeTypes type;
|
||||
Vector3 resizePos = Panel.InverseTransformPoint(rawMousePos);
|
||||
Vector3 dragPos = DragableArea.InverseTransformPoint(rawMousePos);
|
||||
|
||||
if (WasHoveringResize && m_resizeCursorImage)
|
||||
{
|
||||
UpdateHoverImagePos();
|
||||
}
|
||||
|
||||
// If Mouse pressed this frame
|
||||
if (InputManager.GetMouseButtonDown(0))
|
||||
{
|
||||
if (DragableArea.rect.Contains(dragPos))
|
||||
{
|
||||
OnBeginDrag();
|
||||
return;
|
||||
}
|
||||
else if (MouseInResizeArea(resizePos))
|
||||
{
|
||||
type = GetResizeType(resizePos);
|
||||
if (type != ResizeTypes.NONE)
|
||||
{
|
||||
OnBeginResize(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If mouse still pressed from last frame
|
||||
else if (InputManager.GetMouseButton(0))
|
||||
{
|
||||
if (WasDragging)
|
||||
{
|
||||
OnDrag();
|
||||
}
|
||||
else if (WasResizing)
|
||||
{
|
||||
OnResize();
|
||||
}
|
||||
}
|
||||
// If mouse not pressed
|
||||
else
|
||||
{
|
||||
if (WasDragging)
|
||||
{
|
||||
OnEndDrag();
|
||||
}
|
||||
else if (WasResizing)
|
||||
{
|
||||
OnEndResize();
|
||||
}
|
||||
else if (MouseInResizeArea(resizePos) && (type = GetResizeType(resizePos)) != ResizeTypes.NONE)
|
||||
{
|
||||
OnHoverResize(type);
|
||||
}
|
||||
else if (WasHoveringResize)
|
||||
{
|
||||
OnHoverResizeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#region DRAGGING
|
||||
|
||||
public RectTransform DragableArea { get; set; }
|
||||
public bool WasDragging { get; set; }
|
||||
private Vector3 m_lastDragPosition;
|
||||
|
||||
public void OnBeginDrag()
|
||||
{
|
||||
WasDragging = true;
|
||||
m_lastDragPosition = InputManager.MousePosition;
|
||||
}
|
||||
|
||||
public void OnDrag()
|
||||
{
|
||||
Vector3 diff = InputManager.MousePosition - m_lastDragPosition;
|
||||
m_lastDragPosition = InputManager.MousePosition;
|
||||
|
||||
Vector3 pos = Panel.localPosition;
|
||||
float z = pos.z;
|
||||
pos += diff;
|
||||
pos.z = z;
|
||||
Panel.localPosition = pos;
|
||||
}
|
||||
|
||||
public void OnEndDrag()
|
||||
{
|
||||
WasDragging = false;
|
||||
UpdateResizeCache();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RESIZE
|
||||
|
||||
private const int RESIZE_THICKNESS = 10;
|
||||
|
||||
private bool WasResizing { get; set; }
|
||||
private ResizeTypes m_currentResizeType = ResizeTypes.NONE;
|
||||
private Vector2 m_lastResizePos;
|
||||
|
||||
private bool WasHoveringResize { get; set; }
|
||||
private ResizeTypes m_lastResizeHoverType;
|
||||
public GameObject m_resizeCursorImage;
|
||||
|
||||
private Rect m_resizeRect;
|
||||
|
||||
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new Dictionary<ResizeTypes, Rect>
|
||||
{
|
||||
{ ResizeTypes.Top, Rect.zero },
|
||||
{ ResizeTypes.Left, Rect.zero },
|
||||
{ ResizeTypes.Right, Rect.zero },
|
||||
{ ResizeTypes.Bottom, Rect.zero },
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum ResizeTypes
|
||||
{
|
||||
NONE = 0,
|
||||
Top = 1,
|
||||
Left = 2,
|
||||
Right = 4,
|
||||
Bottom = 8,
|
||||
TopLeft = Top | Left,
|
||||
TopRight = Top | Right,
|
||||
BottomLeft = Bottom | Left,
|
||||
BottomRight = Bottom | Right,
|
||||
}
|
||||
|
||||
private void UpdateResizeCache()
|
||||
{
|
||||
int halfThick = RESIZE_THICKNESS / 2;
|
||||
int dblThick = RESIZE_THICKNESS * 2;
|
||||
|
||||
// calculate main outer rect
|
||||
// the resize area is both outside and inside the panel,
|
||||
// to give a bit of buffer and make it easier to use.
|
||||
|
||||
// outer rect is the outer-most bounds of our resize area
|
||||
Rect outer = new Rect(Panel.rect.x - halfThick,
|
||||
Panel.rect.y - halfThick,
|
||||
Panel.rect.width + dblThick,
|
||||
Panel.rect.height + dblThick);
|
||||
m_resizeRect = outer;
|
||||
|
||||
// calculate the four cross sections to use as flags
|
||||
|
||||
m_resizeMask[ResizeTypes.Bottom] = new Rect(outer.x, outer.y, outer.width, RESIZE_THICKNESS);
|
||||
|
||||
m_resizeMask[ResizeTypes.Left] = new Rect(outer.x, outer.y, RESIZE_THICKNESS, outer.height);
|
||||
|
||||
m_resizeMask[ResizeTypes.Top] = new Rect(outer.x, outer.y + Panel.rect.height, outer.width, RESIZE_THICKNESS);
|
||||
|
||||
m_resizeMask[ResizeTypes.Right] = new Rect(outer.x + Panel.rect.width, outer.y, RESIZE_THICKNESS, outer.height);
|
||||
}
|
||||
|
||||
private bool MouseInResizeArea(Vector2 mousePos)
|
||||
{
|
||||
return m_resizeRect.Contains(mousePos);
|
||||
}
|
||||
|
||||
private ResizeTypes GetResizeType(Vector2 mousePos)
|
||||
{
|
||||
// Calculate which part of the resize area we're in, if any.
|
||||
// We do this via a bitmask with the ResizeTypes enum.
|
||||
// We can return Top/Right/Bottom/Left, or a corner like TopLeft.
|
||||
|
||||
int mask = 0;
|
||||
|
||||
if (m_resizeMask[ResizeTypes.Top].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Top;
|
||||
}
|
||||
else if (m_resizeMask[ResizeTypes.Bottom].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Bottom;
|
||||
}
|
||||
|
||||
if (m_resizeMask[ResizeTypes.Left].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Left;
|
||||
}
|
||||
else if (m_resizeMask[ResizeTypes.Right].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Right;
|
||||
}
|
||||
|
||||
return (ResizeTypes)mask;
|
||||
}
|
||||
|
||||
public void OnHoverResize(ResizeTypes resizeType)
|
||||
{
|
||||
if (WasHoveringResize && m_lastResizeHoverType == resizeType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_loadedCursorImage)
|
||||
LoadCursorImage();
|
||||
|
||||
// we are entering resize, or the resize type has changed.
|
||||
|
||||
WasHoveringResize = true;
|
||||
m_lastResizeHoverType = resizeType;
|
||||
|
||||
m_resizeCursorImage.SetActive(true);
|
||||
|
||||
// set the rotation for the resize icon
|
||||
float iconRotation = 0f;
|
||||
switch (resizeType)
|
||||
{
|
||||
case ResizeTypes.TopRight:
|
||||
case ResizeTypes.BottomLeft:
|
||||
iconRotation = 45f; break;
|
||||
case ResizeTypes.Top:
|
||||
case ResizeTypes.Bottom:
|
||||
iconRotation = 90f; break;
|
||||
case ResizeTypes.TopLeft:
|
||||
case ResizeTypes.BottomRight:
|
||||
iconRotation = 135f; break;
|
||||
}
|
||||
|
||||
Quaternion rot = m_resizeCursorImage.transform.rotation;
|
||||
rot.eulerAngles = new Vector3(0, 0, iconRotation);
|
||||
m_resizeCursorImage.transform.rotation = rot;
|
||||
|
||||
UpdateHoverImagePos();
|
||||
}
|
||||
|
||||
// update the resize icon position to be above the mouse
|
||||
private void UpdateHoverImagePos()
|
||||
{
|
||||
RectTransform t = UIManager.CanvasRoot.GetComponent<RectTransform>();
|
||||
m_resizeCursorImage.transform.localPosition = t.InverseTransformPoint(InputManager.MousePosition);
|
||||
}
|
||||
|
||||
public void OnHoverResizeEnd()
|
||||
{
|
||||
WasHoveringResize = false;
|
||||
m_resizeCursorImage.SetActive(false);
|
||||
}
|
||||
|
||||
public void OnBeginResize(ResizeTypes resizeType)
|
||||
{
|
||||
m_currentResizeType = resizeType;
|
||||
m_lastResizePos = InputManager.MousePosition;
|
||||
WasResizing = true;
|
||||
}
|
||||
|
||||
public void OnResize()
|
||||
{
|
||||
Vector3 mousePos = InputManager.MousePosition;
|
||||
Vector2 diff = m_lastResizePos - (Vector2)mousePos;
|
||||
m_lastResizePos = mousePos;
|
||||
|
||||
float diffX = (float)((decimal)diff.x / Screen.width);
|
||||
float diffY = (float)((decimal)diff.y / Screen.height);
|
||||
|
||||
if (m_currentResizeType.HasFlag(ResizeTypes.Left))
|
||||
{
|
||||
Vector2 anch = Panel.anchorMin;
|
||||
anch.x -= diffX;
|
||||
Panel.anchorMin = anch;
|
||||
}
|
||||
else if (m_currentResizeType.HasFlag(ResizeTypes.Right))
|
||||
{
|
||||
Vector2 anch = Panel.anchorMax;
|
||||
anch.x -= diffX;
|
||||
Panel.anchorMax = anch;
|
||||
}
|
||||
|
||||
if (m_currentResizeType.HasFlag(ResizeTypes.Top))
|
||||
{
|
||||
Vector2 anch = Panel.anchorMax;
|
||||
anch.y -= diffY;
|
||||
Panel.anchorMax = anch;
|
||||
}
|
||||
else if (m_currentResizeType.HasFlag(ResizeTypes.Bottom))
|
||||
{
|
||||
Vector2 anch = Panel.anchorMin;
|
||||
anch.y -= diffY;
|
||||
Panel.anchorMin = anch;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEndResize()
|
||||
{
|
||||
WasResizing = false;
|
||||
UpdateResizeCache();
|
||||
}
|
||||
|
||||
private void LoadCursorImage()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = @"Mods\Explorer\cursor.png";
|
||||
byte[] data = File.ReadAllBytes(path);
|
||||
|
||||
Texture2D tex = new Texture2D(32, 32);
|
||||
tex.LoadImage(data, false);
|
||||
UnityEngine.Object.DontDestroyOnLoad(tex);
|
||||
|
||||
Sprite sprite = UIManager.CreateSprite(tex, new Rect(0, 0, 32, 32));
|
||||
UnityEngine.Object.DontDestroyOnLoad(sprite);
|
||||
|
||||
m_resizeCursorImage = new GameObject("ResizeCursorImage");
|
||||
m_resizeCursorImage.transform.SetParent(UIManager.CanvasRoot.transform);
|
||||
|
||||
Image image = m_resizeCursorImage.AddComponent<Image>();
|
||||
image.sprite = sprite;
|
||||
RectTransform rect = image.transform.GetComponent<RectTransform>();
|
||||
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 32);
|
||||
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 32);
|
||||
|
||||
//m_resizeCursorImage.SetActive(false);
|
||||
|
||||
s_loadedCursorImage = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning("Exception loading cursor image!\r\n" + e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,488 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.Helpers;
|
||||
using UnityExplorer.UI.Main.Inspectors;
|
||||
using UnityExplorer.UI.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Unstrip.Scenes;
|
||||
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class SceneExplorer
|
||||
{
|
||||
public static SceneExplorer Instance;
|
||||
|
||||
public SceneExplorer()
|
||||
{
|
||||
Instance = this;
|
||||
ConstructScenePane();
|
||||
}
|
||||
|
||||
private const float UPDATE_INTERVAL = 1f;
|
||||
private float m_timeOfLastSceneUpdate;
|
||||
|
||||
private GameObject m_selectedSceneObject;
|
||||
private int m_currentSceneHandle = -1;
|
||||
private int m_lastCount;
|
||||
|
||||
private Dropdown m_sceneDropdown;
|
||||
private Text m_scenePathText;
|
||||
private GameObject m_mainInspectBtn;
|
||||
private GameObject m_backButtonObj;
|
||||
|
||||
public PageHandler m_sceneListPageHandler;
|
||||
|
||||
private GameObject[] m_allSceneListObjects = new GameObject[0];
|
||||
private readonly List<GameObject> m_sceneShortList = new List<GameObject>();
|
||||
private GameObject m_sceneListContent;
|
||||
private readonly List<Text> m_sceneListTexts = new List<Text>();
|
||||
|
||||
public static int DontDestroyHandle => DontDestroyObject.scene.handle;
|
||||
|
||||
internal static GameObject DontDestroyObject
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!m_dontDestroyObject)
|
||||
{
|
||||
m_dontDestroyObject = new GameObject("DontDestroyMe");
|
||||
GameObject.DontDestroyOnLoad(m_dontDestroyObject);
|
||||
}
|
||||
return m_dontDestroyObject;
|
||||
}
|
||||
}
|
||||
internal static GameObject m_dontDestroyObject;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
RefreshActiveScenes();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Time.realtimeSinceStartup - m_timeOfLastSceneUpdate < UPDATE_INTERVAL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshActiveScenes();
|
||||
|
||||
if (!m_selectedSceneObject)
|
||||
{
|
||||
if (m_currentSceneHandle != -1)
|
||||
{
|
||||
SetSceneObjectList(SceneUnstrip.GetRootGameObjects(m_currentSceneHandle));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshSelectedSceneObject();
|
||||
}
|
||||
}
|
||||
|
||||
public int GetSceneHandle(string sceneName)
|
||||
{
|
||||
if (sceneName == "DontDestroyOnLoad")
|
||||
return DontDestroyHandle;
|
||||
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
var scene = SceneManager.GetSceneAt(i);
|
||||
if (scene.name == sceneName)
|
||||
return scene.handle;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal void OnSceneChange()
|
||||
{
|
||||
m_sceneDropdown.OnCancel(null);
|
||||
RefreshActiveScenes();
|
||||
}
|
||||
|
||||
private void RefreshActiveScenes()
|
||||
{
|
||||
var names = new List<string>();
|
||||
var handles = new List<int>();
|
||||
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneAt(i);
|
||||
|
||||
int handle = scene.handle;
|
||||
|
||||
if (scene == null || handle == -1 || string.IsNullOrEmpty(scene.name))
|
||||
continue;
|
||||
|
||||
handles.Add(handle);
|
||||
names.Add(scene.name);
|
||||
}
|
||||
|
||||
names.Add("DontDestroyOnLoad");
|
||||
handles.Add(DontDestroyHandle);
|
||||
|
||||
m_sceneDropdown.options.Clear();
|
||||
|
||||
foreach (string scene in names)
|
||||
{
|
||||
m_sceneDropdown.options.Add(new Dropdown.OptionData
|
||||
{
|
||||
text = scene
|
||||
});
|
||||
}
|
||||
|
||||
if (!handles.Contains(m_currentSceneHandle))
|
||||
{
|
||||
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = names[0];
|
||||
SetTargetScene(handles[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTargetScene(string name) => SetTargetScene(GetSceneHandle(name));
|
||||
|
||||
public void SetTargetScene(int handle)
|
||||
{
|
||||
if (handle == -1)
|
||||
return;
|
||||
|
||||
m_currentSceneHandle = handle;
|
||||
|
||||
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(handle);
|
||||
SetSceneObjectList(rootObjs);
|
||||
|
||||
m_selectedSceneObject = null;
|
||||
|
||||
if (m_backButtonObj.activeSelf)
|
||||
{
|
||||
m_backButtonObj.SetActive(false);
|
||||
m_mainInspectBtn.SetActive(false);
|
||||
}
|
||||
|
||||
m_scenePathText.text = "Scene root:";
|
||||
//m_scenePathText.ForceMeshUpdate();
|
||||
}
|
||||
|
||||
public void SetTargetObject(GameObject obj)
|
||||
{
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
m_scenePathText.text = obj.name;
|
||||
//m_scenePathText.ForceMeshUpdate();
|
||||
|
||||
m_selectedSceneObject = obj;
|
||||
|
||||
RefreshSelectedSceneObject();
|
||||
|
||||
if (!m_backButtonObj.activeSelf)
|
||||
{
|
||||
m_backButtonObj.SetActive(true);
|
||||
m_mainInspectBtn.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshSelectedSceneObject()
|
||||
{
|
||||
GameObject[] list = new GameObject[m_selectedSceneObject.transform.childCount];
|
||||
for (int i = 0; i < m_selectedSceneObject.transform.childCount; i++)
|
||||
{
|
||||
list[i] = m_selectedSceneObject.transform.GetChild(i).gameObject;
|
||||
}
|
||||
|
||||
SetSceneObjectList(list);
|
||||
}
|
||||
|
||||
private void SetSceneObjectList(GameObject[] objects)
|
||||
{
|
||||
m_allSceneListObjects = objects;
|
||||
RefreshSceneObjectList();
|
||||
}
|
||||
|
||||
private void SceneListObjectClicked(int index)
|
||||
{
|
||||
if (index >= m_sceneShortList.Count || !m_sceneShortList[index])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetTargetObject(m_sceneShortList[index]);
|
||||
}
|
||||
|
||||
private void OnSceneListPageTurn()
|
||||
{
|
||||
RefreshSceneObjectList();
|
||||
}
|
||||
|
||||
private void RefreshSceneObjectList()
|
||||
{
|
||||
m_timeOfLastSceneUpdate = Time.realtimeSinceStartup;
|
||||
|
||||
var objects = m_allSceneListObjects;
|
||||
m_sceneListPageHandler.ListCount = objects.Length;
|
||||
|
||||
//int startIndex = m_sceneListPageHandler.StartIndex;
|
||||
|
||||
int newCount = 0;
|
||||
|
||||
foreach (var itemIndex in m_sceneListPageHandler)
|
||||
{
|
||||
newCount++;
|
||||
|
||||
// normalized index starting from 0
|
||||
var i = itemIndex - m_sceneListPageHandler.StartIndex;
|
||||
|
||||
if (itemIndex >= objects.Length)
|
||||
{
|
||||
if (i > m_lastCount || i >= m_sceneListTexts.Count)
|
||||
break;
|
||||
|
||||
GameObject label = m_sceneListTexts[i].transform.parent.parent.gameObject;
|
||||
if (label.activeSelf)
|
||||
label.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject obj = objects[itemIndex];
|
||||
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
if (i >= m_sceneShortList.Count)
|
||||
{
|
||||
m_sceneShortList.Add(obj);
|
||||
AddObjectListButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sceneShortList[i] = obj;
|
||||
}
|
||||
|
||||
var text = m_sceneListTexts[i];
|
||||
|
||||
var name = obj.name;
|
||||
|
||||
if (obj.transform.childCount > 0)
|
||||
name = $"<color=grey>[{obj.transform.childCount}]</color> {name}";
|
||||
|
||||
text.text = name;
|
||||
text.color = obj.activeSelf ? Color.green : Color.red;
|
||||
|
||||
var label = text.transform.parent.parent.gameObject;
|
||||
if (!label.activeSelf)
|
||||
{
|
||||
label.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lastCount = newCount;
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
public void ConstructScenePane()
|
||||
{
|
||||
GameObject leftPane = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
|
||||
LayoutElement leftLayout = leftPane.AddComponent<LayoutElement>();
|
||||
leftLayout.minWidth = 350;
|
||||
leftLayout.flexibleWidth = 0;
|
||||
|
||||
VerticalLayoutGroup leftGroup = leftPane.GetComponent<VerticalLayoutGroup>();
|
||||
leftGroup.padding.left = 8;
|
||||
leftGroup.padding.right = 8;
|
||||
leftGroup.padding.top = 8;
|
||||
leftGroup.padding.bottom = 8;
|
||||
leftGroup.spacing = 5;
|
||||
leftGroup.childControlWidth = true;
|
||||
leftGroup.childControlHeight = true;
|
||||
leftGroup.childForceExpandWidth = true;
|
||||
leftGroup.childForceExpandHeight = true;
|
||||
|
||||
GameObject titleObj = UIFactory.CreateLabel(leftPane, TextAnchor.UpperLeft);
|
||||
Text titleLabel = titleObj.GetComponent<Text>();
|
||||
titleLabel.text = "Scene Explorer";
|
||||
titleLabel.fontSize = 20;
|
||||
LayoutElement titleLayout = titleObj.AddComponent<LayoutElement>();
|
||||
titleLayout.minHeight = 30;
|
||||
titleLayout.flexibleHeight = 0;
|
||||
|
||||
GameObject sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown);
|
||||
LayoutElement dropdownLayout = sceneDropdownObj.AddComponent<LayoutElement>();
|
||||
dropdownLayout.minHeight = 40;
|
||||
dropdownLayout.flexibleHeight = 0;
|
||||
dropdownLayout.minWidth = 320;
|
||||
dropdownLayout.flexibleWidth = 2;
|
||||
|
||||
#if CPP
|
||||
m_sceneDropdown.onValueChanged.AddListener(new Action<int>((int val) => { SetSceneFromDropdown(val); }));
|
||||
#else
|
||||
m_sceneDropdown.onValueChanged.AddListener((int val) => { SetSceneFromDropdown(val); });
|
||||
#endif
|
||||
void SetSceneFromDropdown(int val)
|
||||
{
|
||||
string scene = m_sceneDropdown.options[val].text;
|
||||
SetTargetScene(scene);
|
||||
}
|
||||
|
||||
GameObject scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, new Color(1, 1, 1, 0f));
|
||||
HorizontalLayoutGroup scenePathGroup = scenePathGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
scenePathGroup.childControlHeight = true;
|
||||
scenePathGroup.childControlWidth = true;
|
||||
scenePathGroup.childForceExpandHeight = true;
|
||||
scenePathGroup.childForceExpandWidth = true;
|
||||
scenePathGroup.spacing = 5;
|
||||
LayoutElement scenePathLayout = scenePathGroupObj.AddComponent<LayoutElement>();
|
||||
scenePathLayout.minHeight = 20;
|
||||
scenePathLayout.minWidth = 335;
|
||||
scenePathLayout.flexibleWidth = 0;
|
||||
|
||||
m_backButtonObj = UIFactory.CreateButton(scenePathGroupObj);
|
||||
Text backButtonText = m_backButtonObj.GetComponentInChildren<Text>();
|
||||
backButtonText.text = "<";
|
||||
LayoutElement backButtonLayout = m_backButtonObj.AddComponent<LayoutElement>();
|
||||
backButtonLayout.minWidth = 40;
|
||||
backButtonLayout.flexibleWidth = 0;
|
||||
Button backButton = m_backButtonObj.GetComponent<Button>();
|
||||
#if CPP
|
||||
backButton.onClick.AddListener(new Action(() => { SetSceneObjectParent(); }));
|
||||
#else
|
||||
backButton.onClick.AddListener(() => { SetSceneObjectParent(); });
|
||||
#endif
|
||||
|
||||
void SetSceneObjectParent()
|
||||
{
|
||||
if (!m_selectedSceneObject || !m_selectedSceneObject.transform.parent?.gameObject)
|
||||
{
|
||||
m_selectedSceneObject = null;
|
||||
SetTargetScene(m_currentSceneHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTargetObject(m_selectedSceneObject.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
GameObject scenePathLabel = UIFactory.CreateHorizontalGroup(scenePathGroupObj);
|
||||
Image image = scenePathLabel.GetComponent<Image>();
|
||||
image.color = Color.white;
|
||||
|
||||
LayoutElement scenePathLabelLayout = scenePathLabel.AddComponent<LayoutElement>();
|
||||
scenePathLabelLayout.minWidth = 210;
|
||||
scenePathLabelLayout.minHeight = 20;
|
||||
scenePathLabelLayout.flexibleHeight = 0;
|
||||
scenePathLabelLayout.flexibleWidth = 120;
|
||||
|
||||
scenePathLabel.AddComponent<Mask>().showMaskGraphic = false;
|
||||
|
||||
GameObject scenePathLabelText = UIFactory.CreateLabel(scenePathLabel, TextAnchor.MiddleLeft);
|
||||
m_scenePathText = scenePathLabelText.GetComponent<Text>();
|
||||
m_scenePathText.text = "Scene root:";
|
||||
m_scenePathText.fontSize = 15;
|
||||
m_scenePathText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
|
||||
LayoutElement textLayout = scenePathLabelText.gameObject.AddComponent<LayoutElement>();
|
||||
textLayout.minWidth = 210;
|
||||
textLayout.flexibleWidth = 120;
|
||||
textLayout.minHeight = 20;
|
||||
textLayout.flexibleHeight = 0;
|
||||
|
||||
m_mainInspectBtn = UIFactory.CreateButton(scenePathGroupObj);
|
||||
Text inspectButtonText = m_mainInspectBtn.GetComponentInChildren<Text>();
|
||||
inspectButtonText.text = "Inspect";
|
||||
LayoutElement inspectButtonLayout = m_mainInspectBtn.AddComponent<LayoutElement>();
|
||||
inspectButtonLayout.minWidth = 65;
|
||||
inspectButtonLayout.flexibleWidth = 0;
|
||||
Button inspectButton = m_mainInspectBtn.GetComponent<Button>();
|
||||
#if CPP
|
||||
inspectButton.onClick.AddListener(new Action(() => { InspectorManager.Instance.Inspect(m_selectedSceneObject); }));
|
||||
|
||||
#else
|
||||
inspectButton.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_selectedSceneObject); });
|
||||
#endif
|
||||
GameObject scrollObj = UIFactory.CreateScrollView(leftPane, out m_sceneListContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
Scrollbar scroll = scrollObj.transform.Find("Scrollbar Vertical").GetComponent<Scrollbar>();
|
||||
ColorBlock colors = scroll.colors;
|
||||
colors.normalColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
|
||||
scroll.colors = colors;
|
||||
|
||||
var horiScroll = scrollObj.transform.Find("Scrollbar Horizontal");
|
||||
horiScroll.gameObject.SetActive(false);
|
||||
|
||||
var scrollRect = scrollObj.GetComponentInChildren<ScrollRect>();
|
||||
scrollRect.horizontalScrollbar = null;
|
||||
|
||||
var sceneGroup = m_sceneListContent.GetComponent<VerticalLayoutGroup>();
|
||||
sceneGroup.childControlHeight = true;
|
||||
sceneGroup.spacing = 2;
|
||||
|
||||
m_sceneListPageHandler = new PageHandler();
|
||||
m_sceneListPageHandler.ConstructUI(leftPane);
|
||||
m_sceneListPageHandler.OnPageChanged += OnSceneListPageTurn;
|
||||
}
|
||||
|
||||
private void AddObjectListButton()
|
||||
{
|
||||
int thisIndex = m_sceneListTexts.Count();
|
||||
|
||||
GameObject btnGroupObj = UIFactory.CreateHorizontalGroup(m_sceneListContent, new Color(0.1f, 0.1f, 0.1f));
|
||||
HorizontalLayoutGroup btnGroup = btnGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||
btnGroup.childForceExpandWidth = true;
|
||||
btnGroup.childControlWidth = true;
|
||||
btnGroup.childForceExpandHeight = false;
|
||||
btnGroup.childControlHeight = true;
|
||||
LayoutElement btnLayout = btnGroupObj.AddComponent<LayoutElement>();
|
||||
btnLayout.flexibleWidth = 320;
|
||||
btnLayout.minHeight = 25;
|
||||
btnLayout.flexibleHeight = 0;
|
||||
btnGroupObj.AddComponent<Mask>();
|
||||
|
||||
GameObject mainButtonObj = UIFactory.CreateButton(btnGroupObj);
|
||||
LayoutElement mainBtnLayout = mainButtonObj.AddComponent<LayoutElement>();
|
||||
mainBtnLayout.minHeight = 25;
|
||||
mainBtnLayout.flexibleHeight = 0;
|
||||
mainBtnLayout.minWidth = 240;
|
||||
mainBtnLayout.flexibleWidth = 0;
|
||||
Button mainBtn = mainButtonObj.GetComponent<Button>();
|
||||
ColorBlock mainColors = mainBtn.colors;
|
||||
mainColors.normalColor = new Color(0.1f, 0.1f, 0.1f);
|
||||
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||
mainBtn.colors = mainColors;
|
||||
#if CPP
|
||||
mainBtn.onClick.AddListener(new Action(() => { SceneListObjectClicked(thisIndex); }));
|
||||
#else
|
||||
mainBtn.onClick.AddListener(() => { SceneListObjectClicked(thisIndex); });
|
||||
#endif
|
||||
|
||||
Text mainText = mainButtonObj.GetComponentInChildren<Text>();
|
||||
mainText.alignment = TextAnchor.MiddleLeft;
|
||||
mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
m_sceneListTexts.Add(mainText);
|
||||
|
||||
GameObject inspectBtnObj = UIFactory.CreateButton(btnGroupObj);
|
||||
LayoutElement inspectBtnLayout = inspectBtnObj.AddComponent<LayoutElement>();
|
||||
inspectBtnLayout.minWidth = 60;
|
||||
inspectBtnLayout.flexibleWidth = 0;
|
||||
inspectBtnLayout.minHeight = 25;
|
||||
inspectBtnLayout.flexibleHeight = 0;
|
||||
Text inspectText = inspectBtnObj.GetComponentInChildren<Text>();
|
||||
inspectText.text = "Inspect";
|
||||
inspectText.color = Color.white;
|
||||
|
||||
Button inspectBtn = inspectBtnObj.GetComponent<Button>();
|
||||
ColorBlock inspectColors = inspectBtn.colors;
|
||||
inspectColors.normalColor = new Color(0.15f, 0.15f, 0.15f);
|
||||
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
|
||||
inspectBtn.colors = inspectColors;
|
||||
#if CPP
|
||||
inspectBtn.onClick.AddListener(new Action(() => { InspectorManager.Instance.Inspect(m_sceneShortList[thisIndex]); }));
|
||||
#else
|
||||
inspectBtn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_sceneShortList[thisIndex]); });
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
namespace UnityExplorer.UI.Main
|
||||
{
|
||||
public class SearchPage : MainMenu.Page
|
||||
{
|
||||
public override string Name => "Search";
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user