finished C# Console and Debug Console, starting work on Scene Explorer

This commit is contained in:
sinaioutlander 2020-10-27 00:54:08 +11:00
parent 2256828384
commit fd950e2aef
20 changed files with 1167 additions and 368 deletions

Binary file not shown.

View File

@ -12,7 +12,7 @@
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<OutputPath>..\Release\Explorer.MelonLoader.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<DefineConstants></DefineConstants>
<IsCpp>true</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<DebugSymbols>false</DebugSymbols>
@ -25,18 +25,22 @@
<RootNamespace>Explorer</RootNamespace>
<AssemblyName>ExplorerBeta</AssemblyName>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
<MLCppGameFolder>D:\Steam\steamapps\common\VRChat</MLCppGameFolder>
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
<!-- Set this to the Mono Managed folder, without the ending '\' character. -->
<MLMonoManagedFolder>D:\Steam\steamapps\common\Outward\Outward_Data\Managed</MLMonoManagedFolder>
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
<BIECppGameFolder>D:\Steam\steamapps\common\Outward_Il2Cpp</BIECppGameFolder>
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
<BIEMonoGameFolder>D:\Steam\steamapps\common\Outward</BIEMonoGameFolder>
<!-- Set this to the BepInEx Managed folder, without the ending '\' character. -->
<BIEMonoManagedFolder>D:\Steam\steamapps\common\Outward\Outward_Data\Managed</BIEMonoManagedFolder>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<!-- <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> -->
<OutputPath>..\Release\Explorer.MelonLoader.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<IsCpp>true</IsCpp>
@ -44,7 +48,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<!-- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> -->
<OutputPath>..\Release\Explorer.MelonLoader.Mono\</OutputPath>
<DefineConstants>MONO,ML</DefineConstants>
<Prefer32Bit>false</Prefer32Bit>
@ -53,7 +57,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<!-- <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> -->
<OutputPath>..\Release\Explorer.BepInEx.Il2Cpp\</OutputPath>
<DefineConstants>CPP,BIE</DefineConstants>
<IsCpp>true</IsCpp>
@ -61,7 +65,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<!-- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> -->
<OutputPath>..\Release\Explorer.BepInEx.Mono\</OutputPath>
<DefineConstants>MONO,BIE</DefineConstants>
<IsCpp>false</IsCpp>
@ -81,24 +85,71 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
<!-- Universal Mono UnityEngine.dll ref (v5.3) --><!--
<ItemGroup Condition="'$(IsCpp)'=='false'">
<Reference Include="UnityEngine">
<HintPath>..\lib\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\lib\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>..\lib\Unity.TextMeshPro.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- MelonLoader Mono ref -->
</ItemGroup>-->
<!-- MelonLoader Mono refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|false'">
<Reference Include="MelonLoader.ModHandler">
<HintPath>$(MLMonoGameFolder)\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>$(MLMonoManagedFolder)\Unity.TextMeshPro.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextCoreModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.TextCoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.TextRenderingModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.UIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.ImageConversionModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- BepInEx Mono refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|false'">
<Reference Include="BepInEx">
@ -109,7 +160,48 @@
<HintPath>$(BIEMonoGameFolder)\BepInEx\core\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>$(BIEMonoManagedFolder)\Unity.TextMeshPro.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextCoreModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.TextCoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.TextRenderingModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.UIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.ImageConversionModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- MelonLoader Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|true'">
<Reference Include="MelonLoader.ModHandler">
@ -165,6 +257,7 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- BepInEx Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
<Reference Include="BepInEx">
@ -247,7 +340,7 @@
<Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" />
<Compile Include="Input\IAbstractInput.cs" />
<Compile Include="Tests\TestClass.cs" />
<Compile Include="CacheObject\Tests\TestClass.cs" />
<Compile Include="Input\InputManager.cs" />
<Compile Include="Input\InputSystem.cs" />
<Compile Include="Input\LegacyInput.cs" />
@ -256,6 +349,7 @@
<Compile Include="UI\Main\MainMenu.cs" />
<Compile Include="UI\Main\Pages\BaseMenuPage.cs" />
<Compile Include="UI\Main\Pages\ConsolePage.cs" />
<Compile Include="UI\Main\Pages\Console\AutoCompleter.cs" />
<Compile Include="UI\Main\Pages\Console\Editor\CodeEditor.cs" />
<Compile Include="UI\Main\Pages\Console\Editor\CSharpLexer.cs" />
<Compile Include="UI\Main\Pages\Console\Editor\Lexer\CommentMatch.cs" />

View File

@ -5,6 +5,7 @@ using ExplorerBeta.Config;
using ExplorerBeta.Input;
using ExplorerBeta.UI;
using ExplorerBeta.UI.Main;
using System.Reflection;
using UnityEngine;
namespace ExplorerBeta
@ -56,6 +57,12 @@ namespace ExplorerBeta
InputManager.Init();
ForceUnlockCursor.Init();
#if CPP
Application.add_logMessageReceived(new Action<string, string, LogType>(LogCallback));
#else
Application.logMessageReceived += LogCallback;
#endif
ShowMenu = true;
Log($"{NAME} initialized.");
@ -89,7 +96,7 @@ namespace ExplorerBeta
{
m_timeSinceStartup += Time.deltaTime;
if (m_timeSinceStartup > 1f)
if (m_timeSinceStartup > 0.1f)
{
UIManager.Init();
@ -115,9 +122,36 @@ namespace ExplorerBeta
UIManager.OnSceneChange();
}
public static void Log(object message)
private void LogCallback(string message, string stackTrace, LogType type)
{
if (!DebugConsole.LogUnity)
return;
message = $"[UNITY] {message}";
switch (type)
{
case LogType.Assert:
case LogType.Log:
Log(message);
break;
case LogType.Warning:
LogWarning(message);
break;
case LogType.Exception:
case LogType.Error:
LogError(message);
break;
}
}
public static void Log(object message, bool unity = false)
{
DebugConsole.Log(message?.ToString());
if (unity)
return;
#if ML
MelonLoader.MelonLogger.Log(message?.ToString());
#else
@ -125,23 +159,31 @@ namespace ExplorerBeta
#endif
}
public static void LogWarning(object message)
public static void LogWarning(object message, bool unity = false)
{
DebugConsole.Log(message?.ToString(), "FFFF00");
if (unity)
return;
#if ML
MelonLoader.MelonLogger.LogWarning(message?.ToString());
#else
ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
#endif
}
public static void LogError(object message)
public static void LogError(object message, bool unity = false)
{
DebugConsole.Log(message?.ToString(), "FF0000");
if (unity)
return;
#if ML
MelonLoader.MelonLogger.LogError(message?.ToString());
#else
ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
#endif
}
}

View File

@ -6,32 +6,28 @@ using Explorer.Unstrip.ColorUtility;
using ExplorerBeta.Input;
using ExplorerBeta.Unstrip.Resources;
using TMPro;
using UnhollowerRuntimeLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace ExplorerBeta.UI.Main
{
// TODO:
// - Maybe hook into Unity's debug logs
// - Buttons for clear, save to file, etc..?
public class DebugConsole
{
public static DebugConsole Instance { get; private set; }
public static bool LogUnity { get; set; } = true;
public static GameObject CanvasRoot;
//private static GameObject Panel;
public readonly List<string> AllMessages;
public readonly List<Text> MessageHolders;
private TMP_InputField m_textInput;
// todo probably put this in UImanager, use for C# console too
//internal static Font m_consoleFont;
//private const int MAX_MESSAGES = 100;
public DebugConsole(GameObject parent)
{
Instance = this;
@ -53,30 +49,52 @@ namespace ExplorerBeta.UI.Main
public void ConstructUI(GameObject parent)
{
var obj = UIFactory.CreateHorizontalGroup(parent, new Color(0.1f, 0.1f, 0.1f, 1.0f));
var mainGroup = obj.GetComponent<HorizontalLayoutGroup>();
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 = obj.GetComponent<Image>();
var mainImage = mainObj.GetComponent<Image>();
mainImage.maskable = true;
var mask = obj.AddComponent<Mask>();
var mask = mainObj.AddComponent<Mask>();
mask.showMaskGraphic = true;
var mainLayout = obj.AddComponent<LayoutElement>();
var mainLayout = mainObj.AddComponent<LayoutElement>();
mainLayout.minHeight = 40;
mainLayout.preferredHeight = 230;
mainLayout.flexibleHeight = 0;
var input = UIFactory.CreateTMPInput(obj);
#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 inputLayout = input.AddComponent<LayoutElement>();
var logAreaLayout = logAreaObj.AddComponent<LayoutElement>();
logAreaLayout.preferredHeight = 300;
logAreaLayout.flexibleHeight = 50;
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 scroll = UIFactory.CreateScrollbar(obj);
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;
@ -86,14 +104,139 @@ namespace ExplorerBeta.UI.Main
scroller.direction = Scrollbar.Direction.TopToBottom;
var scrollColors = scroller.colors;
scrollColors.normalColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
//try { scrollColors.selectedColor = scrollColors.normalColor; } catch { }
scroller.colors = scrollColors;
var tmpInput = input.GetComponent<TMP_InputField>();
var tmpInput = inputObj.GetComponent<TMP_InputField>();
tmpInput.scrollSensitivity = 15;
tmpInput.verticalScrollbar = scroller;
m_textInput = input.GetComponent<TMP_InputField>();
tmpInput.readOnly = true;
m_textInput = inputObj.GetComponent<TMP_InputField>();
#endregion
#region BOTTOM BAR
var bottomBarObj = UIFactory.CreateHorizontalGroup(mainObj);
var 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.preferredHeight = 40;
}
else
{
logAreaObj.SetActive(true);
hideBtnText.text = "Hide";
mainLayout.preferredHeight = 230;
}
}
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>(ToggleCallback));
#else
unityToggle.onValueChanged.AddListener(ToggleCallback);
#endif
void ToggleCallback(bool val)
{
LogUnity = val;
}
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
}
public static void Log(string message)

View File

@ -8,6 +8,7 @@ using UnityEngine.UI;
using UnityEngine.EventSystems;
using ExplorerBeta.UI.Shared;
using Explorer.UI.Main.Pages;
using Explorer.UI.Main.Pages.Console;
namespace ExplorerBeta.UI.Main
{
@ -41,6 +42,7 @@ namespace ExplorerBeta.UI.Main
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());
@ -60,13 +62,16 @@ namespace ExplorerBeta.UI.Main
m_activePage?.Update();
}
// todo
private void SetPage(BaseMenuPage 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;
@ -162,7 +167,11 @@ namespace ExplorerBeta.UI.Main
var hideBtnObj = UIFactory.CreateButton(titleBar);
var hideBtn = hideBtnObj.GetComponent<Button>();
#if CPP
hideBtn.onClick.AddListener(new Action(() => { ExplorerCore.ShowMenu = false; }));
#else
hideBtn.onClick.AddListener(() => { ExplorerCore.ShowMenu = false; });
#endif
var colorBlock = hideBtn.colors;
colorBlock.normalColor = new Color(65f/255f, 23f/255f, 23f/255f);
colorBlock.pressedColor = new Color(35f/255f, 10f/255f, 10f/255f);
@ -208,7 +217,11 @@ namespace ExplorerBeta.UI.Main
page.RefNavbarButton = btn;
#if CPP
btn.onClick.AddListener(new Action(() => { SetPage(page); }));
#else
btn.onClick.AddListener(() => { SetPage(page); });
#endif
var text = btnObj.GetComponentInChildren<Text>();
text.text = page.Name;
@ -235,6 +248,6 @@ namespace ExplorerBeta.UI.Main
PageViewport = mainObj;
}
#endregion
#endregion
}
}

View File

@ -0,0 +1,303 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExplorerBeta;
using ExplorerBeta.Input;
using ExplorerBeta.UI;
using ExplorerBeta.UI.Main;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace Explorer.UI.Main.Pages.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 AutoComplete[] m_suggestions = new AutoComplete[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(AutoComplete[] 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;
if (suggestion.Context == AutoComplete.Contexts.Namespace)
{
label.color = new Color(0.75f, 0.75f, 0.75f, 1.0f);
}
else
{
label.color = Color.white;
}
}
m_lastBatchIndex = i;
}
m_lastBatchIndex++;
}
private static void UpdatePosition()
{
var editor = ConsolePage.Instance.m_codeEditor;
if (editor.InputField.text.Length < 1)
return;
var 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 = MainMenu.Instance.MainPanel.transform.TransformPoint(pos);
m_mainObj.transform.position = new Vector3(pos.x + m_thisRect.rect.width / 2, pos.y - 12, 0);
}
}
private static readonly char[] splitChars = new[] { '{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&' };
public static void CheckAutocomplete()
{
var m_codeEditor = ConsolePage.Instance.m_codeEditor;
var input = m_codeEditor.InputField.text;
var caretIndex = m_codeEditor.InputField.caretPosition;
if (!string.IsNullOrEmpty(input))
{
try
{
var 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();
var 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 AutoComplete(x, prefix, AutoComplete.Contexts.Other))
);
}
var trimmed = input.Trim();
if (trimmed.StartsWith("using"))
trimmed = trimmed.Remove(0, 5).Trim();
var namespaces = AutoCompleteHelpers.Namespaces
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
.Select(x => new AutoComplete(
x.Substring(trimmed.Length),
x.Substring(0, trimmed.Length),
AutoComplete.Contexts.Namespace));
ConsolePage.AutoCompletes.AddRange(namespaces);
}
catch (Exception ex)
{
ExplorerCore.Log("C# Console error:\r\n" + ex);
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(0.5f, 0.5f);
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);
var btn = buttonObj.GetComponent<Button>();
var btnColors = btn.colors;
btnColors.normalColor = new Color(0f, 0f, 0f, 0f);
btnColors.highlightedColor = new Color(0.5f, 0.5f, 0.5f, 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
}
}

View File

@ -9,8 +9,6 @@ namespace Explorer.UI.Main.Pages.Console
{
public static class CSharpLexer
{
// todo option to disable auto-indent
public static bool allowAutoIndent = true;
public static char indentIncreaseCharacter = '{';
public static char indentDecreaseCharacter = '}';

View File

@ -8,6 +8,7 @@ using ExplorerBeta.Input;
using Explorer.UI.Main.Pages.Console.Lexer;
using ExplorerBeta;
using System.Linq;
using UnityEngine.EventSystems;
namespace Explorer.UI.Main.Pages.Console
{
@ -17,7 +18,7 @@ namespace Explorer.UI.Main.Pages.Console
public TMP_InputField InputField { get; }
private readonly TextMeshProUGUI inputText;
public readonly TextMeshProUGUI inputText;
private readonly TextMeshProUGUI inputHighlightText;
private readonly TextMeshProUGUI lineText;
private readonly Image background;
@ -25,7 +26,6 @@ namespace Explorer.UI.Main.Pages.Console
private readonly Image lineNumberBackground;
private readonly Image scrollbar;
private string lastText;
private bool lineHighlightLocked;
private readonly RectTransform inputTextTransform;
private readonly RectTransform lineHighlightTransform;
@ -90,33 +90,41 @@ namespace Explorer.UI.Main.Pages.Console
inputLexer.UseMatchers(CSharpLexer.DelimiterSymbols, CSharpLexer.Matchers);
// subscribe to text input changing
#if CPP
this.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 (InputManager.GetKeyDown(KeyCode.Return))
if (ConsolePage.EnableAutoIndent && InputManager.GetKeyDown(KeyCode.Return))
{
AutoIndentCaret();
}
bool focusKeyPressed = false;
// Check for any focus key pressed
foreach (KeyCode key in lineChangeKeys)
if (EventSystem.current?.currentSelectedGameObject?.name == "InputField (TMP)")
{
if (InputManager.GetKeyDown(key))
bool focusKeyPressed = false;
// Check for any focus key pressed
foreach (KeyCode key in lineChangeKeys)
{
focusKeyPressed = true;
break;
if (InputManager.GetKeyDown(key))
{
focusKeyPressed = true;
break;
}
}
}
// Update line highlight
if (focusKeyPressed || InputManager.GetMouseButton(0))
{
UpdateHighlight();
// Update line highlight
if (focusKeyPressed || InputManager.GetMouseButton(0))
{
UpdateHighlight();
ConsolePage.Instance.OnInputChanged();
}
}
}
@ -126,25 +134,19 @@ namespace Explorer.UI.Main.Pages.Console
UpdateIndent();
if ((!forceUpdate && lastText == newText) || string.IsNullOrEmpty(newText))
if (!forceUpdate && string.IsNullOrEmpty(newText))
{
if (string.IsNullOrEmpty(newText))
{
inputHighlightText.text = string.Empty;
}
UpdateLineNumbers();
UpdateHighlight();
return;
inputHighlightText.text = string.Empty;
}
else
{
inputHighlightText.text = SyntaxHighlightContent(newText);
}
inputHighlightText.text = SyntaxHighlightContent(newText);
// Sync line numbers and update the line highlight
UpdateLineNumbers();
UpdateHighlight();
this.lastText = newText;
ConsolePage.Instance.OnInputChanged();
}
public void SetLineHighlight(int lineNumber, bool lockLineHighlight)
@ -217,12 +219,12 @@ namespace Explorer.UI.Main.Pages.Console
{
int caret = InputField.caretPosition;
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Count)
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Length)
{
while (caret >= 0 && caret >= inputText.textInfo.characterInfo.Count)
while (caret >= 0 && caret >= inputText.textInfo.characterInfo.Length)
caret--;
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Count)
if (caret < 0 || caret >= inputText.textInfo.characterInfo.Length)
{
return;
}
@ -357,6 +359,7 @@ namespace Explorer.UI.Main.Pages.Console
inputText.Rebuild(CanvasUpdate.Prelayout);
InputField.ForceLabelUpdate();
InputField.Rebuild(CanvasUpdate.Prelayout);
OnInputChanged(true);
}
@ -396,10 +399,6 @@ namespace Explorer.UI.Main.Pages.Console
scrollbar.color = scrollbarColor;
}
private void ApplyLanguage()
{
}
private bool AllReferencesAssigned()
{
if (!InputField ||

View File

@ -19,21 +19,17 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
private MatchLexer[] matchers = null;
private readonly HashSet<char> specialStartSymbols = new HashSet<char>();
private readonly HashSet<char> specialEndSymbols = new HashSet<char>();
private char current = ' ';
private char previous = ' ';
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 char Previous
{
get { return previous; }
}
public void UseMatchers(char[] delimiters, MatchLexer[] matchers)
{
this.matchers = matchers;
@ -45,10 +41,10 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
{
foreach (char character in delimiters)
{
if (specialStartSymbols.Contains(character) == false)
if (!specialStartSymbols.Contains(character))
specialStartSymbols.Add(character);
if (specialEndSymbols.Contains(character) == false)
if (!specialEndSymbols.Contains(character))
specialEndSymbols.Add(character);
}
}
@ -58,11 +54,11 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
foreach (MatchLexer lexer in matchers)
{
foreach (char special in lexer.StartChars)
if (specialStartSymbols.Contains(special) == false)
if (!specialStartSymbols.Contains(special))
specialStartSymbols.Add(special);
foreach (char special in lexer.EndChars)
if (specialEndSymbols.Contains(special) == false)
if (!specialEndSymbols.Contains(special))
specialEndSymbols.Add(special);
}
}
@ -75,11 +71,11 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
this.inputString = input;
this.current = ' ';
this.previous = ' ';
this.Previous = ' ';
this.currentIndex = 0;
this.currentLookaheadIndex = 0;
while (EndOfStream == false)
while (!EndOfStream)
{
bool didMatchLexer = false;
@ -91,7 +87,7 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
bool isMatched = matcher.IsMatch(this);
if (isMatched == true)
if (isMatched)
{
int endIndex = currentIndex;
@ -108,7 +104,7 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
}
}
if (didMatchLexer == false)
if (!didMatchLexer)
{
ReadNext();
Commit();
@ -118,10 +114,10 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
public char ReadNext()
{
if (EndOfStream == true)
if (EndOfStream)
return '\0';
previous = current;
Previous = current;
current = inputString[currentLookaheadIndex];
currentLookaheadIndex++;
@ -144,11 +140,11 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
int previousIndex = currentLookaheadIndex - 1;
if (previousIndex >= inputString.Length)
previous = inputString[inputString.Length - 1];
Previous = inputString[inputString.Length - 1];
else if (previousIndex >= 0)
previous = inputString[previousIndex];
Previous = inputString[previousIndex];
else
previous = ' ';
Previous = ' ';
}
public void Commit()

View File

@ -18,7 +18,7 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
private readonly HashSet<string> shortlist = new HashSet<string>();
private readonly Stack<string> removeList = new Stack<string>();
private string[] keywordCache = null;
public string[] keywordCache = null;
public override bool IsImplicitMatch(ILexer lexer)
{
@ -34,7 +34,7 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
char currentChar = lexer.ReadNext();
for (int i = 0; i < keywordCache.Length; i++)
if (CompareChar(keywordCache[i][0], currentChar))
if (keywordCache[i][0] == currentChar)
shortlist.Add(keywordCache[i]);
if (shortlist.Count == 0)
@ -61,8 +61,7 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
foreach (string keyword in shortlist)
{
if (currentIndex >= keyword.Length ||
!CompareChar(keyword[currentIndex], currentChar))
if (currentIndex >= keyword.Length || keyword[currentIndex] != currentChar)
{
removeList.Push(keyword);
}
@ -103,8 +102,5 @@ namespace Explorer.UI.Main.Pages.Console.Lexer
keywordCache = list.ToArray();
}
}
private bool CompareChar(char a, char b) =>
(a == b) || (char.ToUpper(a, CultureInfo.CurrentCulture) == char.ToUpper(b, CultureInfo.CurrentCulture));
}
}

View File

@ -8,7 +8,7 @@ using Mono.CSharp;
namespace Explorer.UI.Main.Pages.Console
{
internal class ScriptEvaluator : Evaluator, IDisposable
public class ScriptEvaluator : Evaluator, IDisposable
{
private static readonly HashSet<string> StdLib = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
{

View File

@ -36,30 +36,33 @@ namespace Explorer.UI.Main
public static void Help()
{
ExplorerCore.Log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
ExplorerCore.Log(" C# Console Help ");
ExplorerCore.Log("");
ExplorerCore.Log("The following helper methods are available:");
ExplorerCore.Log("");
ExplorerCore.Log("void Log(object message)");
ExplorerCore.Log(" prints a message to the console window and debug log");
ExplorerCore.Log(" usage: Log(\"hello world\");");
ExplorerCore.Log("");
ExplorerCore.Log("object CurrentTarget()");
ExplorerCore.Log(" returns the target object of the current tab (in tab view mode only)");
ExplorerCore.Log(" usage: var target = CurrentTarget();");
ExplorerCore.Log("");
ExplorerCore.Log("object[] AllTargets()");
ExplorerCore.Log(" returns an object[] array containing all currently inspected objects");
ExplorerCore.Log(" usage: var targets = AllTargets();");
ExplorerCore.Log("");
ExplorerCore.Log("void Inspect(object obj)");
ExplorerCore.Log(" inspects the provided object in a new window.");
ExplorerCore.Log(" usage: Inspect(Camera.main);");
ExplorerCore.Log("");
ExplorerCore.Log("void Inspect(Type type)");
ExplorerCore.Log(" attempts to inspect the provided type with static-only reflection.");
ExplorerCore.Log(" usage: Inspect(typeof(Camera));");
var msg = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n";
msg += " C# Console Help \r\n";
msg += "\r\n";
msg += "The following helper methods are available:\r\n";
msg += "\r\n";
msg += "void Log(object message)\r\n";
msg += " prints a message to the console window and debug log\r\n";
msg += " usage: Log(\"hello world\");\r\n";
msg += "\r\n";
ExplorerCore.Log(msg);
//ExplorerCore.Log("object CurrentTarget()");
//ExplorerCore.Log(" returns the target object of the current tab (in tab view mode only)");
//ExplorerCore.Log(" usage: var target = CurrentTarget();");
//ExplorerCore.Log("");
//ExplorerCore.Log("object[] AllTargets()");
//ExplorerCore.Log(" returns an object[] array containing all currently inspected objects");
//ExplorerCore.Log(" usage: var targets = AllTargets();");
//ExplorerCore.Log("");
//ExplorerCore.Log("void Inspect(object obj)");
//ExplorerCore.Log(" inspects the provided object in a new window.");
//ExplorerCore.Log(" usage: Inspect(Camera.main);");
//ExplorerCore.Log("");
//ExplorerCore.Log("void Inspect(Type type)");
//ExplorerCore.Log(" attempts to inspect the provided type with static-only reflection.");
//ExplorerCore.Log(" usage: Inspect(typeof(Camera));");
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Explorer.UI.Main.Pages.Console;
using ExplorerBeta;
@ -9,21 +10,28 @@ using ExplorerBeta.UI;
using ExplorerBeta.UI.Main;
using ExplorerBeta.Unstrip.Resources;
using TMPro;
using UnhollowerRuntimeLib;
using UnityEngine;
using UnityEngine.UI;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace Explorer.UI.Main.Pages
{
// TODO: Maybe add interface for managing the Using directives of the console.
// Otherwise it's pretty much done.
public class ConsolePage : BaseMenuPage
{
public override string Name => "C# Console";
public static ConsolePage Instance { get; private set; }
private CodeEditor m_codeEditor;
public static bool EnableSuggestions { get; set; } = true;
public static bool EnableAutoIndent { get; set; } = true;
private ScriptEvaluator m_evaluator;
public CodeEditor m_codeEditor;
public ScriptEvaluator m_evaluator;
public static List<AutoComplete> AutoCompletes = new List<AutoComplete>();
public static List<string> UsingDirectives;
@ -52,6 +60,8 @@ namespace Explorer.UI.Main.Pages
}
ConstructUI();
AutoCompleter.Init();
}
catch (Exception e)
{
@ -63,16 +73,11 @@ namespace Explorer.UI.Main.Pages
public override void Update()
{
m_codeEditor?.Update();
AutoCompleter.Update();
}
internal string AsmToUsing(string asm, bool richText = false)
{
if (richText)
{
return $"<color=#569cd6>using</color> {asm};";
}
return $"using {asm};";
}
internal string AsmToUsing(string asm) => $"using {asm};";
public void AddUsing(string asm)
{
@ -121,111 +126,26 @@ namespace Explorer.UI.Main.Pages
UsingDirectives = new List<string>();
}
private static string m_prevInput = "NULL";
// TODO call from OnInputChanged
private void CheckAutocomplete()
internal void OnInputChanged()
{
var input = m_codeEditor.InputField.text;
var caretIndex = m_codeEditor.InputField.caretPosition;
AutoCompleter.CheckAutocomplete();
if (!string.IsNullOrEmpty(input))
{
try
{
var splitChars = new[] { ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&' };
// Credit ManlyMarco
// Separate input into parts, grab only the part with cursor in it
var start = caretIndex <= 0 ? 0 : input.LastIndexOfAny(splitChars, (int)(caretIndex - 1)) + 1;
var end = caretIndex <= 0 ? input.Length : input.IndexOfAny(splitChars, (int)(caretIndex - 1));
if (end < 0 || end < start) end = input.Length;
input = input.Substring(start, end - start);
}
catch (ArgumentException) { }
if (!string.IsNullOrEmpty(input) && input != m_prevInput)
{
GetAutocompletes(input);
}
}
else
{
ClearAutocompletes();
}
m_prevInput = input;
AutoCompleter.SetSuggestions(AutoCompletes.ToArray());
}
private void ClearAutocompletes()
{
if (AutoCompletes.Any())
{
AutoCompletes.Clear();
}
}
private void UseAutocomplete(string suggestion)
public void UseAutocomplete(string suggestion)
{
int cursorIndex = m_codeEditor.InputField.caretPosition;
var input = m_codeEditor.InputField.text;
input = input.Insert(cursorIndex, suggestion);
m_codeEditor.InputField.text = input;
m_codeEditor.InputField.caretPosition += suggestion.Length;
ClearAutocompletes();
AutoCompleter.ClearAutocompletes();
}
private void GetAutocompletes(string input)
{
try
{
//ExplorerCore.Log("Fetching suggestions for input " + input);
// Credit ManylMarco
AutoCompletes.Clear();
var completions = m_evaluator.GetCompletions(input, out string prefix);
if (completions != null)
{
if (prefix == null)
prefix = input;
AutoCompletes.AddRange(completions
.Where(x => !string.IsNullOrEmpty(x))
.Select(x => new AutoComplete(x, prefix, AutoComplete.Contexts.Other))
);
}
var trimmed = input.Trim();
if (trimmed.StartsWith("using"))
trimmed = trimmed.Remove(0, 5).Trim();
var namespaces = AutoCompleteHelpers.Namespaces
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
.Select(x => new AutoComplete(
x.Substring(trimmed.Length),
x.Substring(0, trimmed.Length),
AutoComplete.Contexts.Namespace));
AutoCompletes.AddRange(namespaces);
}
catch (Exception ex)
{
ExplorerCore.Log("C# Console error:\r\n" + ex);
ClearAutocompletes();
}
}
// Call on OnInputChanged, or maybe limit frequency if its too laggy
// update autocomplete buttons
private void RefreshAutocompleteButtons()
{
throw new NotImplementedException("TODO");
}
#region UI Construction
#region UI Construction
public void ConstructUI()
{
@ -241,6 +161,10 @@ namespace Explorer.UI.Main.Pages
mainGroup.childForceExpandHeight = true;
mainGroup.childForceExpandWidth = true;
#region TOP BAR
// Main group object
var topBarObj = UIFactory.CreateHorizontalGroup(Content);
var topBarLayout = topBarObj.AddComponent<LayoutElement>();
topBarLayout.minHeight = 50;
@ -256,6 +180,7 @@ namespace Explorer.UI.Main.Pages
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>();
@ -265,24 +190,72 @@ namespace Explorer.UI.Main.Pages
topBarText.text = "C# Console";
topBarText.fontSize = 20;
var compileBtnObj = UIFactory.CreateButton(topBarObj);
var compileBtnLayout = compileBtnObj.AddComponent<LayoutElement>();
compileBtnLayout.preferredWidth = 80;
compileBtnLayout.flexibleWidth = 0;
var compileButton = compileBtnObj.GetComponent<Button>();
var compileBtnColors = compileButton.colors;
compileBtnColors.normalColor = new Color(14f/255f, 106f/255f, 14f/255f);
compileButton.colors = compileBtnColors;
var btnText = compileBtnObj.GetComponentInChildren<Text>();
btnText.text = ">";
btnText.fontSize = 25;
btnText.color = Color.white;
// 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 = 5;
consoleLayout.flexibleHeight = 50;
consoleBase.AddComponent<RectMask2D>();
@ -356,6 +329,11 @@ namespace Explorer.UI.Main.Pages
var mainTextInput = mainTextObj.GetComponent<TextMeshProUGUI>();
mainTextInput.fontSize = 18;
var placeHolderText = textAreaObj.transform.Find("Placeholder").GetComponent<TextMeshProUGUI>();
placeHolderText.text = @"Welcome to the Explorer C# Console!
Use the <color=#c74e26>Help();</color> command for a list of available helper methods, or <color=#c74e26>Log(""[message]"");</color> to print something to console.";
var linesTextObj = UIFactory.CreateUIObject("LinesText", mainTextObj.gameObject);
var linesTextRect = linesTextObj.GetComponent<RectTransform>();
@ -403,15 +381,49 @@ namespace Explorer.UI.Main.Pages
tmpInput.GetComponentInChildren<RectMask2D>().enabled = false;
inputObj.GetComponent<Image>().enabled = false;
// setup button callbacks
#endregion
compileButton.onClick.AddListener(new Action(() =>
#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
@ -439,17 +451,24 @@ namespace Explorer.UI.Main.Pages
#endif
if (fontToUse != null)
{
fontToUse.faceInfo.tabWidth = 10;
fontToUse.tabSize = 10;
var 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,

View File

@ -6,7 +6,9 @@ using ExplorerBeta;
using ExplorerBeta.UI;
using ExplorerBeta.UI.Main;
using ExplorerBeta.UI.Shared;
using ExplorerBeta.Unstrip.Scenes;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Explorer.UI.Main.Pages
@ -15,16 +17,153 @@ namespace Explorer.UI.Main.Pages
{
public override string Name => "Home";
private PageHandler m_sceneListPages;
// private PageHandler m_sceneListPages;
private Dropdown m_sceneDropdown;
private Dictionary<string, int> m_sceneHandles = new Dictionary<string, int>();
// is tihs needed?
private int m_currentSceneHandle;
private List<GameObject> m_currentObjectList = new List<GameObject>();
private GameObject m_sceneListContent;
private readonly List<Text> m_sceneListTexts = new List<Text>();
// todo
private GameObject m_currentSceneObject;
private int m_lastMaxIndex;
public override void Init()
{
ConstructMenu();
// get DontDestroyScene handle
var test = new GameObject();
GameObject.DontDestroyOnLoad(test);
GetSceneHandle(test.scene);
GameObject.Destroy(test);
RefreshActiveScenes();
}
public override void Update()
{
// refresh active scenes? maybe on a timer to limit frequency
// refresh scene objects on limited frequency
}
private int GetSceneHandle(Scene scene)
{
if (!m_sceneHandles.ContainsKey(scene.name))
{
m_sceneHandles.Add(scene.name, scene.handle);
}
return scene.handle;
}
private int GetSceneHandle(string sceneName)
{
if (!m_sceneHandles.ContainsKey(sceneName))
return -1;
else
return m_sceneHandles[sceneName];
}
public void SetScene(string name)
{
var handle = GetSceneHandle(name);
if (handle == -1)
{
ExplorerCore.LogWarning($"Error: Could not get handle for scene '{name}'");
return;
}
m_currentSceneHandle = handle;
var rootObjs = SceneUnstrip.GetRootGameObjects(handle);
SetSceneObjectList(rootObjs);
}
private void RefreshActiveScenes(bool firstTime = false)
{
var activeScene = SceneManager.GetActiveScene().name;
var otherScenes = new List<string>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
GetSceneHandle(scene);
if (!firstTime || scene.name != activeScene)
otherScenes.Add(scene.name);
}
otherScenes.Add("DontDestroyOnLoad");
m_sceneDropdown.options.Clear();
if (firstTime)
{
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = activeScene
});
}
foreach (var scene in otherScenes)
{
m_sceneDropdown.options.Add(new Dropdown.OptionData
{
text = scene
});
}
SetScene(activeScene);
}
private void SceneButtonClicked(int index)
{
var obj = m_currentObjectList[index];
ExplorerCore.Log("Clicked " + obj.name);
}
private void SetSceneObjectList(IEnumerable<GameObject> objects)
{
m_currentObjectList.Clear();
int index = 0;
foreach (var obj in objects)
{
m_currentObjectList.Add(obj);
if (index >= m_sceneListTexts.Count)
{
AddSceneButton();
}
m_sceneListTexts[index].text = obj.name;
var parent = m_sceneListTexts[index].transform.parent.gameObject;
if (!parent.activeSelf)
parent.SetActive(true);
index++;
}
var origIndex = index;
while (index < m_sceneListTexts.Count && index < m_lastMaxIndex)
{
var obj = m_sceneListTexts[index].transform.parent.gameObject;
if (obj.activeSelf)
obj.SetActive(false);
index++;
}
m_lastMaxIndex = origIndex;
}
#region UI Construction
@ -76,24 +215,70 @@ namespace Explorer.UI.Main.Pages
private void ConstructScenePane(GameObject leftPane)
{
m_sceneListPages = new PageHandler(100);
m_sceneListPages.ConstructUI(leftPane);
m_sceneListPages.OnPageChanged += RefreshSceneObjectList;
var activeSceneLabelObj = UIFactory.CreateLabel(leftPane, TextAnchor.UpperLeft);
var activeSceneLabel = activeSceneLabelObj.GetComponent<Text>();
activeSceneLabel.text = "Scene Explorer";
activeSceneLabel.fontSize = 25;
var activeSceneLayout = activeSceneLabelObj.AddComponent<LayoutElement>();
activeSceneLayout.minHeight = 30;
activeSceneLayout.flexibleHeight = 0;
var scrollTest = UIFactory.CreateScrollView(leftPane, out GameObject content);
var sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown);
var 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)
{
var scene = m_sceneDropdown.options[val].text;
SetScene(scene);
}
// Scene list(TODO)
//m_sceneListPages = new PageHandler(100);
//m_sceneListPages.ConstructUI(leftPane);
//m_sceneListPages.OnPageChanged += RefreshSceneObjectList;
var scrollTest = UIFactory.CreateScrollView(leftPane, out m_sceneListContent, new Color(0.15f, 0.15f, 0.15f, 1));
for (int i = 0; i < 50; i++)
{
var obj = UIFactory.CreateLabel(content, TextAnchor.MiddleCenter);
var text = obj.GetComponent<Text>();
text.text = "Hello world " + i;
AddSceneButton();
}
m_lastMaxIndex = 51;
}
private void RefreshSceneObjectList()
private void AddSceneButton()
{
ExplorerCore.Log("Would update scene list here");
var obj = UIFactory.CreateButton(m_sceneListContent);
var btn = obj.GetComponent<Button>();
var colors = btn.colors;
colors.normalColor = new Color(0.15f, 0.15f, 0.15f, 1);
btn.colors = colors;
int thisIndex = m_sceneListTexts.Count();
#if CPP
btn.onClick.AddListener(new Action(() => { SceneButtonClicked(thisIndex); }));
#else
btn.onClick.AddListener(() => { SceneButtonClicked(thisIndex); });
#endif
var text = obj.GetComponentInChildren<Text>();
text.text = "button " + thisIndex;
text.alignment = TextAnchor.MiddleLeft;
m_sceneListTexts.Add(text);
}
#endregion
#endregion
}
}

View File

@ -6,9 +6,11 @@ using UnityEngine.UI;
using UnityEngine.EventSystems;
using ExplorerBeta.Input;
using ExplorerBeta.Helpers;
using ExplorerBeta.Unstrip.ImageConversion;
using System.IO;
using System.Linq;
#if CPP
using ExplorerBeta.Unstrip.ImageConversion;
#endif
namespace ExplorerBeta.UI
{
@ -102,7 +104,7 @@ namespace ExplorerBeta.UI
return;
}
#region DRAGGING
#region DRAGGING
public RectTransform DragableArea { get; set; }
public bool WasDragging { get; set; }
@ -132,9 +134,9 @@ namespace ExplorerBeta.UI
UpdateResizeCache();
}
#endregion
#endregion
#region RESIZE
#region RESIZE
private const int RESIZE_THICKNESS = 10;
@ -339,13 +341,13 @@ namespace ExplorerBeta.UI
var image = m_resizeCursorImage.AddComponent<Image>();
image.sprite = sprite;
var rect = image.transform.TryCast<RectTransform>();
var rect = image.transform.GetComponent<RectTransform>();
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 32);
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 32);
m_resizeCursorImage.SetActive(false);
}
#endregion
#endregion
}
}

View File

@ -79,8 +79,6 @@ namespace ExplorerBeta.UI.Shared
#region UI
// TODO
private GameObject m_pageUIHolder;
private Text m_currentPageLabel;
@ -111,7 +109,11 @@ namespace ExplorerBeta.UI.Shared
var leftBtnObj = UIFactory.CreateButton(m_pageUIHolder);
var leftBtn = leftBtnObj.GetComponent<Button>();
#if CPP
leftBtn.onClick.AddListener(new Action(() => { TurnPage(Turn.Left); }));
#else
leftBtn.onClick.AddListener(() => { TurnPage(Turn.Left); });
#endif
var leftBtnText = leftBtnObj.GetComponentInChildren<Text>();
leftBtnText.text = "<";
var leftBtnLayout = leftBtnObj.AddComponent<LayoutElement>();
@ -131,7 +133,11 @@ namespace ExplorerBeta.UI.Shared
var rightBtnObj = UIFactory.CreateButton(m_pageUIHolder);
var rightBtn = rightBtnObj.GetComponent<Button>();
#if CPP
rightBtn.onClick.AddListener(new Action(() => { TurnPage(Turn.Right); }));
#else
rightBtn.onClick.AddListener(() => { TurnPage(Turn.Right); });
#endif
var rightBtnText = rightBtnObj.GetComponentInChildren<Text>();
rightBtnText.text = ">";
var rightBtnLayout = rightBtnObj.AddComponent<LayoutElement>();
@ -150,6 +156,6 @@ namespace ExplorerBeta.UI.Shared
m_currentPageLabel.text = $"Page {m_currentPage + 1} / {LastPage + 1}";
}
#endregion
#endregion
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using TMPro;
using UnityEngine;
@ -11,25 +12,10 @@ namespace ExplorerBeta.UI
{
public static class UIFactory
{
private static Vector2 s_ThickElementSize = new Vector2(160f, 30f);
private static Vector2 s_ThinElementSize = new Vector2(160f, 20f);
private static Color s_DefaultSelectableColor = new Color(1f, 1f, 1f, 1f);
private static Color s_TextColor = new Color(0.95f, 0.95f, 0.95f, 1f);
//private static Color s_PanelColor = new Color(0.1f, 0.1f, 0.1f, 1.0f);
//private static Vector2 s_ImageElementSize = new Vector2(100f, 100f);
public static Resources UIResources { get; set; }
public struct Resources
{
public Sprite standard;
public Sprite background;
public Sprite inputField;
public Sprite knob;
public Sprite checkmark;
public Sprite dropdown;
public Sprite mask;
}
private static Vector2 thickSize = new Vector2(160f, 30f);
private static Vector2 thinSize = new Vector2(160f, 20f);
private static Color defaultTextColor = new Color(0.95f, 0.95f, 0.95f, 1f);
private static Font m_defaultFont;
public static GameObject CreateUIObject(string name, GameObject parent, Vector2 size = default)
{
@ -48,10 +34,14 @@ namespace ExplorerBeta.UI
private static void SetDefaultTextValues(Text lbl)
{
lbl.color = s_TextColor;
lbl.AssignDefaultFont();
//lbl.alignment = alignment;
//lbl.resizeTextForBestFit = true;
lbl.color = defaultTextColor;
if (!m_defaultFont)
{
m_defaultFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
}
lbl.font = m_defaultFont;
}
private static void SetDefaultColorTransitionValues(Selectable selectable)
@ -65,9 +55,21 @@ namespace ExplorerBeta.UI
// fix to make all buttons become de-selected after being clicked.
// this is because i'm not setting any ColorBlock.selectedColor, because it is commonly stripped.
if (selectable is Button button)
{
button.onClick.AddListener(new Action(() => { button.OnDeselect(EventSystem.current?.baseEventDataCache); }));
}
{
#if CPP
button.onClick.AddListener(new Action(() =>
{
button.OnDeselect(null);
}));
#else
button.onClick.AddListener(Deselect);
void Deselect()
{
button.OnDeselect(null);
}
#endif
}
selectable.colors = colors;
}
@ -94,7 +96,7 @@ namespace ExplorerBeta.UI
public static GameObject CreatePanel(GameObject parent, string name, out GameObject content)
{
GameObject panelObj = CreateUIObject($"Panel_{name}", parent, s_ThickElementSize);
GameObject panelObj = CreateUIObject($"Panel_{name}", parent, thickSize);
RectTransform rect = panelObj.GetComponent<RectTransform>();
rect.anchorMin = Vector2.zero;
@ -173,7 +175,7 @@ namespace ExplorerBeta.UI
public static GameObject CreateLabel(GameObject parent, TextAnchor alignment)
{
GameObject labelObj = CreateUIObject("Label", parent, s_ThinElementSize);
GameObject labelObj = CreateUIObject("Label", parent, thinSize);
var text = labelObj.AddComponent<Text>();
SetDefaultTextValues(text);
@ -185,16 +187,15 @@ namespace ExplorerBeta.UI
public static GameObject CreateButton(GameObject parent)
{
GameObject buttonObj = CreateUIObject("Button", parent, s_ThinElementSize);
GameObject buttonObj = CreateUIObject("Button", parent, thinSize);
GameObject textObj = new GameObject("Text");
textObj.AddComponent<RectTransform>();
SetParentAndAlign(textObj, buttonObj);
Image image = buttonObj.AddComponent<Image>();
image.sprite = UIResources.standard;
image.type = Image.Type.Sliced;
image.color = s_DefaultSelectableColor;
image.color = new Color(1, 1, 1, 1);
SetDefaultColorTransitionValues(buttonObj.AddComponent<Button>());
@ -213,7 +214,7 @@ namespace ExplorerBeta.UI
public static GameObject CreateSlider(GameObject parent)
{
GameObject sliderObj = CreateUIObject("Slider", parent, s_ThinElementSize);
GameObject sliderObj = CreateUIObject("Slider", parent, thinSize);
GameObject bgObj = CreateUIObject("Background", sliderObj);
GameObject fillAreaObj = CreateUIObject("Fill Area", sliderObj);
@ -222,9 +223,8 @@ namespace ExplorerBeta.UI
GameObject handleObj = CreateUIObject("Handle", handleSlideAreaObj);
Image bgImage = bgObj.AddComponent<Image>();
bgImage.sprite = UIResources.background;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
bgImage.color = new Color(0.15f, 0.15f, 0.15f, 1.0f);
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = new Vector2(0f, 0.25f);
@ -238,9 +238,8 @@ namespace ExplorerBeta.UI
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
Image fillImage = fillObj.AddComponent<Image>();
fillImage.sprite = UIResources.standard;
fillImage.type = Image.Type.Sliced;
fillImage.color = s_DefaultSelectableColor;
fillImage.color = new Color(0.3f, 0.3f, 0.3f, 1.0f);
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
@ -250,8 +249,7 @@ namespace ExplorerBeta.UI
handleSlideRect.anchorMax = new Vector2(1f, 1f);
Image handleImage = handleObj.AddComponent<Image>();
handleImage.sprite = UIResources.knob;
handleImage.color = s_DefaultSelectableColor;
handleImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
handleObj.GetComponent<RectTransform>().sizeDelta = new Vector2(20f, 0f);
@ -267,7 +265,7 @@ namespace ExplorerBeta.UI
public static GameObject CreateScrollbar(GameObject parent)
{
GameObject scrollObj = CreateUIObject("Scrollbar", parent, s_ThinElementSize);
GameObject scrollObj = CreateUIObject("Scrollbar", parent, thinSize);
GameObject slideAreaObj = CreateUIObject("Sliding Area", scrollObj);
GameObject handleObj = CreateUIObject("Handle", slideAreaObj);
@ -277,7 +275,6 @@ namespace ExplorerBeta.UI
scrollImage.color = new Color(0.1f, 0.1f, 0.1f);
Image handleImage = handleObj.AddComponent<Image>();
handleImage.sprite = UIResources.standard;
handleImage.type = Image.Type.Sliced;
handleImage.color = new Color(0.4f, 0.4f, 0.4f);
@ -297,26 +294,39 @@ namespace ExplorerBeta.UI
return scrollObj;
}
public static GameObject CreateToggle(GameObject parent)
public static GameObject CreateToggle(GameObject parent, out Toggle toggle, out Text text)
{
GameObject toggleObj = CreateUIObject("Toggle", parent, s_ThinElementSize);
GameObject toggleObj = CreateUIObject("Toggle", parent, thinSize);
GameObject bgObj = CreateUIObject("Background", toggleObj);
GameObject checkObj = CreateUIObject("Checkmark", bgObj);
GameObject labelObj = CreateUIObject("Label", toggleObj);
Toggle toggle = toggleObj.AddComponent<Toggle>();
toggle = toggleObj.AddComponent<Toggle>();
toggle.isOn = true;
var toggleComp = toggle;
#if CPP
toggle.onValueChanged.AddListener(new Action<bool>((bool val) =>
{
toggleComp.OnDeselect(null);
}));
#else
toggle.onValueChanged.AddListener(Deselect);
void Deselect(bool _)
{
toggleComp.OnDeselect(null);
}
#endif
Image bgImage = bgObj.AddComponent<Image>();
bgImage.sprite = UIResources.standard;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
bgImage.color = new Color(0.1f, 0.1f, 0.1f, 1.0f);
Image checkImage = checkObj.AddComponent<Image>();
checkImage.sprite = UIResources.checkmark;
checkImage.color = new Color(90f/255f, 115f/255f, 90f/255f, 1.0f);
Text text = labelObj.AddComponent<Text>();
text = labelObj.AddComponent<Text>();
text.text = "Toggle";
SetDefaultTextValues(text);
@ -334,7 +344,7 @@ namespace ExplorerBeta.UI
checkRect.anchorMin = new Vector2(0.5f, 0.5f);
checkRect.anchorMax = new Vector2(0.5f, 0.5f);
checkRect.anchoredPosition = Vector2.zero;
checkRect.sizeDelta = new Vector2(20f, 20f);
checkRect.sizeDelta = new Vector2(14f, 14f);
RectTransform labelRect = labelObj.GetComponent<RectTransform>();
labelRect.anchorMin = new Vector2(0f, 0f);
@ -353,7 +363,9 @@ namespace ExplorerBeta.UI
mainImage.color = new Color(38f / 255f, 38f / 255f, 38f / 255f, 1.0f);
var mainInput = mainObj.AddComponent<TMP_InputField>();
mainInput.navigation.mode = Navigation.Mode.None;
var nav = mainInput.navigation;
nav.mode = Navigation.Mode.None;
mainInput.navigation = nav;
mainInput.richText = true;
mainInput.isRichTextEditingAllowed = true;
mainInput.lineType = TMP_InputField.LineType.MultiLineNewline;
@ -426,15 +438,14 @@ namespace ExplorerBeta.UI
public static GameObject CreateInputField(GameObject parent)
{
GameObject inputObj = CreateUIObject("InputField", parent, s_ThickElementSize);
GameObject inputObj = CreateUIObject("InputField", parent, thickSize);
GameObject placeholderObj = CreateUIObject("Placeholder", inputObj);
GameObject textObj = CreateUIObject("Text", inputObj);
Image inputImage = inputObj.AddComponent<Image>();
inputImage.sprite = UIResources.inputField;
inputImage.type = Image.Type.Sliced;
inputImage.color = s_DefaultSelectableColor;
inputImage.color = new Color(0.1f, 0.1f, 0.1f, 1.0f);
InputField inputField = inputObj.AddComponent<InputField>();
SetDefaultColorTransitionValues(inputField);
@ -470,12 +481,11 @@ namespace ExplorerBeta.UI
return inputObj;
}
public static GameObject CreateDropdown(GameObject parent)
public static GameObject CreateDropdown(GameObject parent, out Dropdown dropdown)
{
GameObject dropdownObj = CreateUIObject("Dropdown", parent, s_ThickElementSize);
GameObject dropdownObj = CreateUIObject("Dropdown", parent, thickSize);
GameObject labelObj = CreateUIObject("Label", dropdownObj);
GameObject arrowObj = CreateUIObject("Arrow", dropdownObj);
GameObject templateObj = CreateUIObject("Template", dropdownObj);
GameObject viewportObj = CreateUIObject("Viewport", templateObj);
GameObject contentObj = CreateUIObject("Content", viewportObj);
@ -500,19 +510,24 @@ namespace ExplorerBeta.UI
itemLabelText.alignment = TextAnchor.MiddleLeft;
Image itemBgImage = itemBgObj.AddComponent<Image>();
itemBgImage.color = new Color32(245, 245, 245, byte.MaxValue);
itemBgImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
Image itemCheckImage = itemCheckObj.AddComponent<Image>();
itemCheckImage.sprite = UIResources.checkmark;
Toggle itemToggle = itemObj.AddComponent<Toggle>();
itemToggle.targetGraphic = itemBgImage;
itemToggle.graphic = itemCheckImage;
itemToggle.isOn = true;
Toggle itemToggle = itemObj.AddComponent<Toggle>();
itemToggle.targetGraphic = itemBgImage;
itemToggle.isOn = true;
var colors = itemToggle.colors;
colors.normalColor = new Color(0.15f, 0.15f, 0.15f, 1.0f);
colors.highlightedColor = new Color(0.25f, 0.25f, 0.25f, 1.0f);
itemToggle.colors = colors;
#if CPP
itemToggle.onValueChanged.AddListener(new Action<bool>((bool val) => { itemToggle.OnDeselect(null); }));
#else
itemToggle.onValueChanged.AddListener((bool val) => { itemToggle.OnDeselect(null); });
#endif
Image templateImage = templateObj.AddComponent<Image>();
templateImage.sprite = UIResources.standard;
templateImage.type = Image.Type.Sliced;
templateImage.color = new Color(0.15f, 0.15f, 0.15f, 1.0f);
ScrollRect scrollRect = templateObj.AddComponent<ScrollRect>();
scrollRect.content = contentObj.GetComponent<RectTransform>();
@ -526,37 +541,29 @@ namespace ExplorerBeta.UI
viewportObj.AddComponent<Mask>().showMaskGraphic = false;
Image viewportImage = viewportObj.AddComponent<Image>();
viewportImage.sprite = UIResources.mask;
viewportImage.type = Image.Type.Sliced;
Text labelText = labelObj.AddComponent<Text>();
SetDefaultTextValues(labelText);
labelText.alignment = TextAnchor.MiddleLeft;
arrowObj.AddComponent<Image>().sprite = UIResources.dropdown;
Image dropdownImage = dropdownObj.AddComponent<Image>();
dropdownImage.sprite = UIResources.standard;
dropdownImage.color = s_DefaultSelectableColor;
dropdownImage.color = new Color(0.2f, 0.2f, 0.2f, 1);
dropdownImage.type = Image.Type.Sliced;
Dropdown dropdown = dropdownObj.AddComponent<Dropdown>();
dropdown = dropdownObj.AddComponent<Dropdown>();
dropdown.targetGraphic = dropdownImage;
SetDefaultColorTransitionValues(dropdown);
dropdown.template = templateObj.GetComponent<RectTransform>();
dropdown.captionText = labelText;
dropdown.itemText = itemLabelText;
itemLabelText.text = "Option A";
itemLabelText.text = "1";
dropdown.options.Add(new Dropdown.OptionData
{
text = "Option A"
text = "2"
});
dropdown.options.Add(new Dropdown.OptionData
{
text = "Option B"
});
dropdown.options.Add(new Dropdown.OptionData
{
text = "Option C"
text = "3"
});
dropdown.RefreshShownValue();
@ -567,12 +574,6 @@ namespace ExplorerBeta.UI
labelRect.offsetMin = new Vector2(10f, 6f);
labelRect.offsetMax = new Vector2(-25f, -7f);
RectTransform arrowRect = arrowObj.GetComponent<RectTransform>();
arrowRect.anchorMin = new Vector2(1f, 0.5f);
arrowRect.anchorMax = new Vector2(1f, 0.5f);
arrowRect.sizeDelta = new Vector2(20f, 20f);
arrowRect.anchoredPosition = new Vector2(-15f, 0f);
RectTransform templateRect = templateObj.GetComponent<RectTransform>();
templateRect.anchorMin = new Vector2(0f, 0f);
templateRect.anchorMax = new Vector2(1f, 0f);
@ -603,12 +604,6 @@ namespace ExplorerBeta.UI
itemBgRect.anchorMax = Vector2.one;
itemBgRect.sizeDelta = Vector2.zero;
RectTransform itemCheckRect = itemCheckObj.GetComponent<RectTransform>();
itemCheckRect.anchorMin = new Vector2(0f, 0.5f);
itemCheckRect.anchorMax = new Vector2(0f, 0.5f);
itemCheckRect.sizeDelta = new Vector2(20f, 20f);
itemCheckRect.anchoredPosition = new Vector2(10f, 0f);
RectTransform itemLabelRect = itemLabelObj.GetComponent<RectTransform>();
itemLabelRect.anchorMin = Vector2.zero;
itemLabelRect.anchorMax = Vector2.one;
@ -698,7 +693,7 @@ namespace ExplorerBeta.UI
scrollImage.color = (color == default) ? new Color(0.3f, 0.3f, 0.3f, 1f) : color;
Image viewportImage = viewportObj.AddComponent<Image>();
viewportImage.sprite = UIResources.mask;
//viewportImage.sprite = Theme.mask;
viewportImage.type = Image.Type.Sliced;
viewportImage.color = new Color(1, 1, 1, 1);

View File

@ -19,10 +19,6 @@ namespace ExplorerBeta.UI
public static void Init()
{
var res = UIFactory.UIResources = new UIFactory.Resources();
var bg = CreateSprite(MakeSolidTexture(new Color(0.16f, 0.16f, 0.16f), 1, 1));
res.background = bg;
// Create core UI Canvas and Event System handler
CreateRootCanvas();
@ -82,6 +78,7 @@ namespace ExplorerBeta.UI
}
// Fix for games which override the InputModule pointer events (eg, VRChat)
#if CPP
if (InputModule.m_InputPointerEvent != null)
{
var evt = InputModule.m_InputPointerEvent;
@ -90,6 +87,7 @@ namespace ExplorerBeta.UI
evt.eligibleForClick = true;
}
}
#endif
}
if (PanelDragger.Instance != null)

View File

@ -16,13 +16,18 @@ namespace ExplorerBeta.Unstrip.Scenes
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
public static GameObject[] GetRootGameObjects(Scene scene)
public static GameObject[] GetRootGameObjects(Scene scene) => GetRootGameObjects(scene.handle);
public static GameObject[] GetRootGameObjects(int handle)
{
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount(scene));
if (handle == -1)
return new GameObject[0];
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount(handle));
var iCall = ICallHelper.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
iCall.Invoke(scene.handle, list.Pointer);
iCall.Invoke(handle, list.Pointer);
return list.ToArray();
}
@ -31,10 +36,12 @@ namespace ExplorerBeta.Unstrip.Scenes
internal delegate int GetRootCountInternal_delegate(int handle);
public static int GetRootCount(Scene scene)
public static int GetRootCount(Scene scene) => GetRootCount(scene.handle);
public static int GetRootCount(int handle)
{
var iCall = ICallHelper.GetICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
return iCall.Invoke(scene.handle);
return iCall.Invoke(handle);
}
}
}