mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-24 01:12:41 +08:00
A few important fixes
* Reflection on Il2CppSystem-namespace instances has been fixed * Type/Value Syntax highlighting generalized and improved globally * Scene changes now refresh the scene-picker dropdown * probably other minor stuff too
This commit is contained in:
@ -98,39 +98,55 @@ namespace UnityExplorer.UI
|
||||
|
||||
public void SetPage(Page page)
|
||||
{
|
||||
if (m_activePage == page || page == null)
|
||||
{
|
||||
if (page == null || m_activePage == page)
|
||||
return;
|
||||
}
|
||||
|
||||
// WIP, was going to hide current page if you press current page's button,
|
||||
// but the main panel does not resize so its just a big empty gap there.
|
||||
// Could be good if I resize that gap, not bothering for now.
|
||||
// Would need a fix in PanelDragger as well.
|
||||
|
||||
//if (m_activePage == page)
|
||||
//{
|
||||
// SetButtonInactiveColors(page.RefNavbarButton);
|
||||
// m_activePage.Content.SetActive(false);
|
||||
// m_activePage = null;
|
||||
// return;
|
||||
//}
|
||||
|
||||
m_activePage?.Content?.SetActive(false);
|
||||
|
||||
// unique case for console page, at the moment this will just go here
|
||||
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;
|
||||
SetButtonActiveColors(button);
|
||||
|
||||
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;
|
||||
}
|
||||
SetButtonInactiveColors(m_lastNavButtonPressed);
|
||||
|
||||
m_lastNavButtonPressed = button;
|
||||
}
|
||||
|
||||
internal void SetButtonActiveColors(Button button)
|
||||
{
|
||||
ColorBlock colors = button.colors;
|
||||
colors.normalColor = m_navButtonSelected;
|
||||
button.colors = colors;
|
||||
}
|
||||
|
||||
internal void SetButtonInactiveColors(Button button)
|
||||
{
|
||||
ColorBlock colors = button.colors;
|
||||
colors.normalColor = m_navButtonNormal;
|
||||
button.colors = colors;
|
||||
}
|
||||
|
||||
#region UI Construction
|
||||
|
||||
private void ConstructMenu()
|
||||
|
@ -18,12 +18,13 @@ namespace UnityExplorer.UI.Modules
|
||||
public static bool LogUnity { get; set; } = ModConfig.Instance.Log_Unity_Debug;
|
||||
public static bool SaveToDisk { get; set; } = ModConfig.Instance.Save_Logs_To_Disk;
|
||||
|
||||
internal static bool m_savedToDiskChecked;
|
||||
internal static StreamWriter s_streamWriter;
|
||||
|
||||
public static readonly List<string> AllMessages = new List<string>();
|
||||
public static readonly List<Text> MessageHolders = new List<Text>();
|
||||
|
||||
// logs that occured before the actual UI was ready.
|
||||
// these ones include the hex color codes.
|
||||
internal static readonly List<string> s_preInitMessages = new List<string>();
|
||||
|
||||
private InputField m_textInput;
|
||||
@ -34,6 +35,7 @@ namespace UnityExplorer.UI.Modules
|
||||
|
||||
ConstructUI(parent);
|
||||
|
||||
// append messages that logged before we were set up
|
||||
string preAppend = "";
|
||||
for (int i = s_preInitMessages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@ -43,14 +45,8 @@ namespace UnityExplorer.UI.Modules
|
||||
preAppend += msg;
|
||||
}
|
||||
m_textInput.text = preAppend;
|
||||
}
|
||||
|
||||
public static void OnQuit()
|
||||
{
|
||||
if (m_savedToDiskChecked)
|
||||
return;
|
||||
|
||||
m_savedToDiskChecked = true;
|
||||
// set up IO
|
||||
|
||||
if (!SaveToDisk)
|
||||
return;
|
||||
@ -60,20 +56,28 @@ namespace UnityExplorer.UI.Modules
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
// delete oldest log
|
||||
// clean old log(s)
|
||||
var files = Directory.GetFiles(path);
|
||||
if (files.Length >= 10)
|
||||
{
|
||||
var sorted = files.ToList();
|
||||
// sort by datetime.ToString will put the oldest one first
|
||||
// sort by 'datetime.ToString("u")' will put the oldest ones first
|
||||
sorted.Sort();
|
||||
File.Delete(sorted[0]);
|
||||
for (int i = 0; i < files.Length - 9; i++)
|
||||
File.Delete(files[i]);
|
||||
}
|
||||
|
||||
var fileName = "UnityExplorer " + DateTime.Now.ToString("u") + ".txt";
|
||||
fileName = ExplorerCore.RemoveInvalidFilenameChars(fileName);
|
||||
|
||||
File.WriteAllText(path + @"\" + fileName, Instance.m_textInput.text);
|
||||
var stream = File.Create(path + @"\" + fileName);
|
||||
s_streamWriter = new StreamWriter(stream)
|
||||
{
|
||||
AutoFlush = true
|
||||
};
|
||||
|
||||
foreach (var msg in AllMessages)
|
||||
s_streamWriter.WriteLine(msg);
|
||||
}
|
||||
|
||||
public static void Log(string message)
|
||||
@ -91,6 +95,7 @@ namespace UnityExplorer.UI.Modules
|
||||
message = $"{AllMessages.Count}: {message}";
|
||||
|
||||
AllMessages.Add(message);
|
||||
s_streamWriter?.WriteLine(message);
|
||||
|
||||
if (hexColor != null)
|
||||
message = $"<color=#{hexColor}>{message}</color>";
|
||||
@ -139,7 +144,6 @@ namespace UnityExplorer.UI.Modules
|
||||
inputScroll.inputField.readOnly = true;
|
||||
|
||||
m_textInput = inputScroll.inputField;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BOTTOM BAR
|
||||
|
@ -20,8 +20,6 @@ namespace UnityExplorer.UI
|
||||
|
||||
public static event Action OnFinishResize;
|
||||
|
||||
private static bool s_loadedCursorImage;
|
||||
|
||||
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag)
|
||||
{
|
||||
Instance = this;
|
||||
@ -39,7 +37,7 @@ namespace UnityExplorer.UI
|
||||
Vector3 resizePos = Panel.InverseTransformPoint(rawMousePos);
|
||||
Vector3 dragPos = DragableArea.InverseTransformPoint(rawMousePos);
|
||||
|
||||
if (WasHoveringResize && m_resizeCursorImage)
|
||||
if (WasHoveringResize && s_resizeCursorImage)
|
||||
{
|
||||
UpdateHoverImagePos();
|
||||
}
|
||||
@ -141,7 +139,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
private bool WasHoveringResize { get; set; }
|
||||
private ResizeTypes m_lastResizeHoverType;
|
||||
public GameObject m_resizeCursorImage;
|
||||
public static GameObject s_resizeCursorImage;
|
||||
|
||||
private Rect m_resizeRect;
|
||||
|
||||
@ -202,48 +200,33 @@ namespace UnityExplorer.UI
|
||||
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;
|
||||
ResizeTypes mask = 0;
|
||||
|
||||
if (m_resizeMask[ResizeTypes.Top].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Top;
|
||||
}
|
||||
mask |= ResizeTypes.Top;
|
||||
else if (m_resizeMask[ResizeTypes.Bottom].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Bottom;
|
||||
}
|
||||
mask |= ResizeTypes.Bottom;
|
||||
|
||||
if (m_resizeMask[ResizeTypes.Left].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Left;
|
||||
}
|
||||
mask |= ResizeTypes.Left;
|
||||
else if (m_resizeMask[ResizeTypes.Right].Contains(mousePos))
|
||||
{
|
||||
mask |= (int)ResizeTypes.Right;
|
||||
}
|
||||
mask |= ResizeTypes.Right;
|
||||
|
||||
return (ResizeTypes)mask;
|
||||
return 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);
|
||||
s_resizeCursorImage.SetActive(true);
|
||||
|
||||
// set the rotation for the resize icon
|
||||
float iconRotation = 0f;
|
||||
@ -260,9 +243,9 @@ namespace UnityExplorer.UI
|
||||
iconRotation = 135f; break;
|
||||
}
|
||||
|
||||
Quaternion rot = m_resizeCursorImage.transform.rotation;
|
||||
Quaternion rot = s_resizeCursorImage.transform.rotation;
|
||||
rot.eulerAngles = new Vector3(0, 0, iconRotation);
|
||||
m_resizeCursorImage.transform.rotation = rot;
|
||||
s_resizeCursorImage.transform.rotation = rot;
|
||||
|
||||
UpdateHoverImagePos();
|
||||
}
|
||||
@ -271,13 +254,13 @@ namespace UnityExplorer.UI
|
||||
private void UpdateHoverImagePos()
|
||||
{
|
||||
RectTransform t = UIManager.CanvasRoot.GetComponent<RectTransform>();
|
||||
m_resizeCursorImage.transform.localPosition = t.InverseTransformPoint(InputManager.MousePosition);
|
||||
s_resizeCursorImage.transform.localPosition = t.InverseTransformPoint(InputManager.MousePosition);
|
||||
}
|
||||
|
||||
public void OnHoverResizeEnd()
|
||||
{
|
||||
WasHoveringResize = false;
|
||||
m_resizeCursorImage.SetActive(false);
|
||||
s_resizeCursorImage.SetActive(false);
|
||||
}
|
||||
|
||||
public void OnBeginResize(ResizeTypes resizeType)
|
||||
@ -335,25 +318,23 @@ namespace UnityExplorer.UI
|
||||
OnFinishResize?.Invoke();
|
||||
}
|
||||
|
||||
private void LoadCursorImage()
|
||||
internal static void LoadCursorImage()
|
||||
{
|
||||
try
|
||||
{
|
||||
var sprite = UIManager.ResizeCursor;
|
||||
|
||||
m_resizeCursorImage = new GameObject("ResizeCursorImage");
|
||||
m_resizeCursorImage.transform.SetParent(UIManager.CanvasRoot.transform);
|
||||
s_resizeCursorImage = new GameObject("ResizeCursorImage");
|
||||
s_resizeCursorImage.transform.SetParent(UIManager.CanvasRoot.transform);
|
||||
|
||||
Image image = m_resizeCursorImage.AddComponent<Image>();
|
||||
Image image = s_resizeCursorImage.AddComponent<Image>();
|
||||
image.sprite = sprite;
|
||||
image.material = Graphic.defaultGraphicMaterial;
|
||||
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;
|
||||
s_resizeCursorImage.SetActive(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ namespace UnityExplorer.UI.Shared
|
||||
get => m_currentPage;
|
||||
set
|
||||
{
|
||||
if (value < LastPage)
|
||||
if (value < PageCount)
|
||||
m_currentPage = value;
|
||||
}
|
||||
}
|
||||
@ -60,11 +60,11 @@ namespace UnityExplorer.UI.Shared
|
||||
{
|
||||
m_listCount = value;
|
||||
|
||||
if (LastPage <= 0 && m_pageUIHolder.activeSelf)
|
||||
if (PageCount <= 0 && m_pageUIHolder.activeSelf)
|
||||
{
|
||||
m_pageUIHolder.SetActive(false);
|
||||
}
|
||||
else if (LastPage > 0 && !m_pageUIHolder.activeSelf)
|
||||
else if (PageCount > 0 && !m_pageUIHolder.activeSelf)
|
||||
{
|
||||
m_pageUIHolder.SetActive(true);
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace UnityExplorer.UI.Shared
|
||||
}
|
||||
}
|
||||
|
||||
public int LastPage => (int)Math.Ceiling(ListCount / (decimal)ItemsPerPage) - 1;
|
||||
public int PageCount => (int)Math.Ceiling(ListCount / (decimal)ItemsPerPage) - 1;
|
||||
|
||||
// The index of the first element of the current page
|
||||
public int StartIndex
|
||||
@ -138,7 +138,7 @@ namespace UnityExplorer.UI.Shared
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_currentPage < LastPage)
|
||||
if (m_currentPage < PageCount)
|
||||
{
|
||||
m_currentPage++;
|
||||
didTurn = true;
|
||||
@ -160,7 +160,7 @@ namespace UnityExplorer.UI.Shared
|
||||
|
||||
public void RefreshUI()
|
||||
{
|
||||
m_currentPageLabel.text = $"Page {m_currentPage + 1} / {LastPage + 1}";
|
||||
m_currentPageLabel.text = $"Page {m_currentPage + 1} / {PageCount + 1}";
|
||||
}
|
||||
|
||||
public void ConstructUI(GameObject parent)
|
||||
|
@ -22,7 +22,7 @@ namespace UnityExplorer.UI.Shared
|
||||
|
||||
public const string Local = "#a6e9e9";
|
||||
|
||||
public const string StructGreen = "#0e9931";
|
||||
public const string StructGreen = "#0fba3a";
|
||||
|
||||
public static string Enum = "#92c470";
|
||||
|
||||
@ -33,7 +33,7 @@ namespace UnityExplorer.UI.Shared
|
||||
string classColor;
|
||||
if (type.IsAbstract && type.IsSealed)
|
||||
classColor = Class_Static;
|
||||
else if (type.IsEnum)
|
||||
else if (type.IsEnum || type.IsGenericParameter)
|
||||
classColor = Enum;
|
||||
else if (type.IsValueType)
|
||||
classColor = StructGreen;
|
||||
@ -43,7 +43,7 @@ namespace UnityExplorer.UI.Shared
|
||||
return classColor;
|
||||
}
|
||||
|
||||
public static string GetHighlight(Type type, bool includeNamespace, MemberInfo memberInfo = null)
|
||||
public static string ParseFullSyntax(Type type, bool includeNamespace, MemberInfo memberInfo = null)
|
||||
{
|
||||
string ret = "";
|
||||
|
||||
@ -55,91 +55,132 @@ namespace UnityExplorer.UI.Shared
|
||||
}
|
||||
else
|
||||
{
|
||||
string ns = includeNamespace
|
||||
? $"<color=#{s_silver.ToHex()}>{type.Namespace}</color>."
|
||||
: "";
|
||||
|
||||
ret += ns;
|
||||
if (includeNamespace && !string.IsNullOrEmpty(type.Namespace))
|
||||
ret += $"<color=#{s_silver.ToHex()}>{type.Namespace}</color>.";
|
||||
|
||||
var declaring = type.DeclaringType;
|
||||
while (declaring != null)
|
||||
{
|
||||
ret += $"<color={GetClassColor(declaring)}>{declaring.Name}</color>.";
|
||||
ret += HighlightTypeName(declaring) + ".";
|
||||
declaring = declaring.DeclaringType;
|
||||
}
|
||||
|
||||
ret += $"<color={GetClassColor(type)}>{type.Name}</color>";
|
||||
ret += HighlightTypeName(type);
|
||||
}
|
||||
|
||||
// todo MemberInfo
|
||||
if (memberInfo != null)
|
||||
{
|
||||
ret += ".";
|
||||
|
||||
string memberColor = "";
|
||||
bool isStatic = false;
|
||||
string memberColor = GetMemberInfoColor(memberInfo, out bool isStatic);
|
||||
string memberHighlight = $"<color={memberColor}>{memberInfo.Name}</color>";
|
||||
|
||||
if (memberInfo is FieldInfo fi)
|
||||
{
|
||||
if (fi.IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Field_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Field_Instance;
|
||||
}
|
||||
else if (memberInfo is MethodInfo mi)
|
||||
{
|
||||
if (mi.IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Method_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Method_Instance;
|
||||
}
|
||||
else if (memberInfo is PropertyInfo pi)
|
||||
{
|
||||
if (pi.GetAccessors(true)[0].IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Prop_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Prop_Instance;
|
||||
}
|
||||
if (isStatic)
|
||||
memberHighlight = $"<i>{memberHighlight}</i>";
|
||||
|
||||
if (isStatic)
|
||||
ret += "<i>";
|
||||
|
||||
ret += $"<color={memberColor}>{memberInfo.Name}</color>";
|
||||
|
||||
if (isStatic)
|
||||
ret += "</i>";
|
||||
ret += memberHighlight;
|
||||
|
||||
// generic method args
|
||||
if (memberInfo is MethodInfo method)
|
||||
{
|
||||
var gArgs = method.GetGenericArguments();
|
||||
if (gArgs.Length > 0)
|
||||
{
|
||||
ret += "<";
|
||||
|
||||
var args = "";
|
||||
for (int i = 0; i < gArgs.Length; i++)
|
||||
{
|
||||
if (i > 0) args += ", ";
|
||||
args += $"<color={Enum}>{gArgs[i].Name}</color>";
|
||||
}
|
||||
ret += args;
|
||||
|
||||
ret += ">";
|
||||
}
|
||||
ret += ParseGenericArgs(gArgs, true);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static string HighlightTypeName(Type type)
|
||||
{
|
||||
var typeName = type.Name;
|
||||
|
||||
var gArgs = type.GetGenericArguments();
|
||||
|
||||
if (gArgs.Length > 0)
|
||||
{
|
||||
// remove the `N from the end of the type name
|
||||
// this could actually be >9 in some cases, so get the length of the length string and use that.
|
||||
// eg, if it was "List`15", we would remove the ending 3 chars
|
||||
|
||||
int suffixLen = 1 + gArgs.Length.ToString().Length;
|
||||
|
||||
// make sure the typename actually has expected "`N" format.
|
||||
if (typeName[typeName.Length - suffixLen] == '`')
|
||||
typeName = typeName.Substring(0, typeName.Length - suffixLen);
|
||||
}
|
||||
|
||||
// highlight the base name itself
|
||||
// do this after removing the `N suffix, so only the name itself is in the color tags.
|
||||
typeName = $"<color={GetClassColor(type)}>{typeName}</color>";
|
||||
|
||||
// parse the generic args, if any
|
||||
if (gArgs.Length > 0)
|
||||
typeName += ParseGenericArgs(gArgs);
|
||||
|
||||
return typeName;
|
||||
}
|
||||
|
||||
private static string ParseGenericArgs(Type[] gArgs, bool allGeneric = false)
|
||||
{
|
||||
if (gArgs.Length < 1)
|
||||
return "";
|
||||
|
||||
var args = "<";
|
||||
for (int i = 0; i < gArgs.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
args += ", ";
|
||||
|
||||
var arg = gArgs[i];
|
||||
|
||||
if (allGeneric)
|
||||
{
|
||||
args += $"<color={Enum}>{arg.Name}</color>";
|
||||
continue;
|
||||
}
|
||||
|
||||
// using HighlightTypeName makes it recursive, so we can parse nested generic args.
|
||||
args += HighlightTypeName(arg);
|
||||
}
|
||||
return args + ">";
|
||||
}
|
||||
|
||||
private static string GetMemberInfoColor(MemberInfo memberInfo, out bool isStatic)
|
||||
{
|
||||
string memberColor = "";
|
||||
isStatic = false;
|
||||
if (memberInfo is FieldInfo fi)
|
||||
{
|
||||
if (fi.IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Field_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Field_Instance;
|
||||
}
|
||||
else if (memberInfo is MethodInfo mi)
|
||||
{
|
||||
if (mi.IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Method_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Method_Instance;
|
||||
}
|
||||
else if (memberInfo is PropertyInfo pi)
|
||||
{
|
||||
if (pi.GetAccessors(true)[0].IsStatic)
|
||||
{
|
||||
isStatic = true;
|
||||
memberColor = Prop_Static;
|
||||
}
|
||||
else
|
||||
memberColor = Prop_Instance;
|
||||
}
|
||||
return memberColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,11 +56,10 @@ namespace UnityExplorer.UI
|
||||
// Create submodules
|
||||
new MainMenu();
|
||||
MouseInspector.ConstructUI();
|
||||
PanelDragger.LoadCursorImage();
|
||||
|
||||
// Force refresh of anchors
|
||||
Canvas.ForceUpdateCanvases();
|
||||
//CanvasRoot.SetActive(false);
|
||||
//CanvasRoot.SetActive(true);
|
||||
}
|
||||
|
||||
public static void SetEventSystem()
|
||||
|
Reference in New Issue
Block a user