mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-01-09 10:38:59 +08:00
commit
6970dcbbc7
@ -20,7 +20,6 @@
|
||||
| Standalone | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
||||
|
||||
### Known issues
|
||||
* UI layouts broken/unusable after changing resolutions: delete the file `data.ini` in the UnityExplorer folder (same place as where you put the DLL). Better fix being worked on.
|
||||
* Any `MissingMethodException` or `NotSupportedException`: please report the issue and provide a copy of your mod loader log and/or Unity log.
|
||||
* The C# console may unexpectedly produce a GC Mark Overflow crash when calling certain outside methods. Not clear yet what is causing this, but it's being looked into.
|
||||
* In IL2CPP, some IEnumerable and IDictionary types may fail enumeration. Waiting for the Unhollower rewrite to address this any further.
|
||||
@ -95,8 +94,7 @@ Depending on the release you are using, the config file will be found at:
|
||||
|
||||
## Building
|
||||
|
||||
Building the project should be straight-forward, the references are all inside the `lib\` folder.
|
||||
|
||||
0. Clone the repository and run `git submodule update --init --recursive` to get the submodules.
|
||||
1. Open the `src\UnityExplorer.sln` project in Visual Studio.
|
||||
2. Select `Solution 'UnityExplorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> property to the version you want to build, then build it. Alternatively, use "Batch Build" and select all releases.
|
||||
3. The DLLs are built to the `Release\` folder in the root of the repository.
|
||||
|
@ -36,6 +36,27 @@ namespace UnityExplorer
|
||||
|
||||
// ------- Misc extensions --------
|
||||
|
||||
/// <summary>
|
||||
/// Recursively check the type and its base types to find any generic arguments.
|
||||
/// </summary>
|
||||
public static bool TryGetGenericArguments(this Type type, out Type[] args)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
args = type.GetGenericArguments();
|
||||
return true;
|
||||
}
|
||||
else if (type.BaseType != null)
|
||||
{
|
||||
return TryGetGenericArguments(type.BaseType, out args);
|
||||
}
|
||||
else
|
||||
{
|
||||
args = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely try to get all Types inside an Assembly.
|
||||
/// </summary>
|
||||
|
@ -14,8 +14,40 @@ using UnhollowerBaseLib;
|
||||
|
||||
namespace UnityExplorer.Tests
|
||||
{
|
||||
public class TestIndexer : IList<int>
|
||||
{
|
||||
private readonly List<int> list = new List<int>() { 1,2,3,4,5 };
|
||||
|
||||
public int Count => list.Count;
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
int IList<int>.this[int index]
|
||||
{
|
||||
get => list[index];
|
||||
set => list[index] = value;
|
||||
}
|
||||
|
||||
public int IndexOf(int item) => list.IndexOf(item);
|
||||
public bool Contains(int item) => list.Contains(item);
|
||||
|
||||
public void Add(int item) => list.Add(item);
|
||||
public void Insert(int index, int item) => list.Insert(index, item);
|
||||
|
||||
public bool Remove(int item) => list.Remove(item);
|
||||
public void RemoveAt(int index) => list.RemoveAt(index);
|
||||
|
||||
public void Clear() => list.Clear();
|
||||
|
||||
public void CopyTo(int[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);
|
||||
|
||||
public IEnumerator<int> GetEnumerator() => list.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
|
||||
}
|
||||
|
||||
public static class TestClass
|
||||
{
|
||||
public static readonly TestIndexer AAAAATest = new TestIndexer();
|
||||
|
||||
public static void ATestMethod(string s, float f, Vector3 vector, DateTime date, Quaternion quater, bool b, CameraClearFlags enumvalue)
|
||||
{
|
||||
ExplorerCore.Log($"{s}, {f}, {vector.ToString()}, {date}, {quater.eulerAngles.ToString()}, {b}, {enumvalue}");
|
||||
|
@ -19,7 +19,7 @@ namespace UnityExplorer
|
||||
public static class ExplorerCore
|
||||
{
|
||||
public const string NAME = "UnityExplorer";
|
||||
public const string VERSION = "4.0.0";
|
||||
public const string VERSION = "4.0.1";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.unityexplorer";
|
||||
|
||||
|
@ -75,10 +75,11 @@ namespace UnityExplorer.UI.IValues
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
if (type.IsGenericType && type.GetGenericArguments().Length == 2)
|
||||
{
|
||||
KeyType = type.GetGenericArguments()[0];
|
||||
ValueType = type.GetGenericArguments()[1];
|
||||
|
||||
if (type.TryGetGenericArguments(out var args) && args.Length == 2)
|
||||
{
|
||||
KeyType = args[0];
|
||||
ValueType = args[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
@ -19,13 +20,15 @@ namespace UnityExplorer.UI.IValues
|
||||
object ICacheObjectController.Target => this.CurrentOwner.Value;
|
||||
public Type TargetType { get; private set; }
|
||||
|
||||
public override bool CanWrite => base.CanWrite && RefIList != null && !RefIList.IsReadOnly;
|
||||
public override bool CanWrite => base.CanWrite && ((RefIList != null && !RefIList.IsReadOnly) || IsWritableGenericIList);
|
||||
|
||||
public Type EntryType;
|
||||
public IList RefIList;
|
||||
|
||||
public int ItemCount => values.Count;
|
||||
private readonly List<object> values = new List<object>();
|
||||
private bool IsWritableGenericIList;
|
||||
private PropertyInfo genericIndexer;
|
||||
|
||||
public int ItemCount => cachedEntries.Count;
|
||||
private readonly List<CacheListEntry> cachedEntries = new List<CacheListEntry>();
|
||||
|
||||
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
||||
@ -49,7 +52,6 @@ namespace UnityExplorer.UI.IValues
|
||||
private void ClearAndRelease()
|
||||
{
|
||||
RefIList = null;
|
||||
values.Clear();
|
||||
|
||||
foreach (var entry in cachedEntries)
|
||||
{
|
||||
@ -66,14 +68,14 @@ namespace UnityExplorer.UI.IValues
|
||||
if (value == null)
|
||||
{
|
||||
// should never be null
|
||||
if (values.Any())
|
||||
if (cachedEntries.Any())
|
||||
ClearAndRelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
if (type.IsGenericType)
|
||||
EntryType = type.GetGenericArguments()[0];
|
||||
if (type.TryGetGenericArguments(out var args))
|
||||
EntryType = args[0];
|
||||
else if (type.HasElementType)
|
||||
EntryType = type.GetElementType();
|
||||
else
|
||||
@ -92,7 +94,12 @@ namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
RefIList = value as IList;
|
||||
|
||||
values.Clear();
|
||||
// Check if the type implements IList<T> but not IList (ie. Il2CppArrayBase)
|
||||
if (RefIList == null)
|
||||
CheckGenericIList(value);
|
||||
else
|
||||
IsWritableGenericIList = false;
|
||||
|
||||
int idx = 0;
|
||||
|
||||
if (ReflectionUtility.TryGetEnumerator(value, out IEnumerator enumerator))
|
||||
@ -103,8 +110,6 @@ namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
var entry = enumerator.Current;
|
||||
|
||||
values.Add(entry);
|
||||
|
||||
// If list count increased, create new cache entries
|
||||
CacheListEntry cache;
|
||||
if (idx >= cachedEntries.Count)
|
||||
@ -122,9 +127,9 @@ namespace UnityExplorer.UI.IValues
|
||||
}
|
||||
|
||||
// Remove excess cached entries if list count decreased
|
||||
if (cachedEntries.Count > values.Count)
|
||||
if (cachedEntries.Count > idx)
|
||||
{
|
||||
for (int i = cachedEntries.Count - 1; i >= values.Count; i--)
|
||||
for (int i = cachedEntries.Count - 1; i >= idx; i--)
|
||||
{
|
||||
var cache = cachedEntries[i];
|
||||
if (cache.CellView != null)
|
||||
@ -141,14 +146,61 @@ namespace UnityExplorer.UI.IValues
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckGenericIList(object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = value.GetType();
|
||||
if (type.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
IsWritableGenericIList = !(bool)type.GetProperty("IsReadOnly").GetValue(value, null);
|
||||
else
|
||||
IsWritableGenericIList = false;
|
||||
|
||||
if (IsWritableGenericIList)
|
||||
{
|
||||
// Find the "this[int index]" property.
|
||||
// It might be a private implementation.
|
||||
foreach (var prop in type.GetProperties(ReflectionUtility.FLAGS))
|
||||
{
|
||||
if ((prop.Name == "Item"
|
||||
|| (prop.Name.StartsWith("System.Collections.Generic.IList<") && prop.Name.EndsWith(">.Item")))
|
||||
&& prop.GetIndexParameters() is ParameterInfo[] parameters
|
||||
&& parameters.Length == 1
|
||||
&& parameters[0].ParameterType == typeof(int))
|
||||
{
|
||||
genericIndexer = prop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (genericIndexer == null)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Failed to find indexer property for IList<T> type '{type.FullName}'!");
|
||||
IsWritableGenericIList = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception processing IEnumerable for IList<T> check: {ex.ReflectionExToString()}");
|
||||
IsWritableGenericIList = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Setting the value of an index to the list
|
||||
|
||||
public void TrySetValueToIndex(object value, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
//value = value.TryCast(this.EntryType);
|
||||
RefIList[index] = value;
|
||||
if (!IsWritableGenericIList)
|
||||
{
|
||||
RefIList[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
genericIndexer.SetValue(CurrentOwner.Value, value, new object[] { index });
|
||||
}
|
||||
|
||||
var entry = cachedEntries[index];
|
||||
entry.SetValueFromSource(value);
|
||||
|
@ -226,7 +226,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar,
|
||||
new Color(0.065f, 0.065f, 0.065f));
|
||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 300, flexibleWidth: 9999, flexibleHeight: 1);
|
||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(Content, spacing: 3, padTop: 2, padBottom: 2, padLeft: 2, padRight: 2);
|
||||
|
||||
@ -244,10 +244,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
var listHolder = UIFactory.CreateUIObject("ListHolders", UIRoot);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listHolder, false, true, true, true, 8, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(listHolder, minHeight: 350, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
//var listRect = listHolder.GetComponent<RectTransform>();
|
||||
//listRect.anchorMin = new Vector2(0, 1);
|
||||
//listRect.anchorMax = new Vector2(1, 1);
|
||||
UIFactory.SetLayoutElement(listHolder, minHeight: 150, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// Left group (Children)
|
||||
|
||||
|
@ -155,8 +155,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
mousePos.x = 350;
|
||||
if (mousePos.x > Screen.width - 350)
|
||||
mousePos.x = Screen.width - 350;
|
||||
if (mousePos.y < mainPanelRect.rect.height)
|
||||
mousePos.y += mainPanelRect.rect.height + 10;
|
||||
if (mousePos.y < Rect.rect.height)
|
||||
mousePos.y += Rect.rect.height + 10;
|
||||
else
|
||||
mousePos.y -= 10;
|
||||
|
||||
@ -341,10 +341,10 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.anchorMin = Vector2.zero;
|
||||
mainPanelRect.anchorMax = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0.5f, 1);
|
||||
mainPanelRect.sizeDelta = new Vector2(700, 150);
|
||||
Rect.anchorMin = Vector2.zero;
|
||||
Rect.anchorMax = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0.5f, 1);
|
||||
Rect.sizeDelta = new Vector2(700, 150);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
|
@ -62,10 +62,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.4f, 0.175f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.85f, 0.925f);
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.4f, 0.175f);
|
||||
Rect.anchorMax = new Vector2(0.85f, 0.925f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
|
@ -26,8 +26,8 @@ namespace UnityExplorer.UI.Panels
|
||||
public GameObject ContentHolder;
|
||||
public RectTransform ContentRect;
|
||||
|
||||
public static float CurrentPanelWidth => Instance.mainPanelRect.rect.width;
|
||||
public static float CurrentPanelHeight => Instance.mainPanelRect.rect.height;
|
||||
public static float CurrentPanelWidth => Instance.Rect.rect.width;
|
||||
public static float CurrentPanelHeight => Instance.Rect.rect.height;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
@ -38,7 +38,7 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
base.OnFinishResize(panel);
|
||||
|
||||
InspectorManager.PanelWidth = this.mainPanelRect.rect.width;
|
||||
InspectorManager.PanelWidth = this.Rect.rect.width;
|
||||
InspectorManager.OnPanelResized(panel.rect.width);
|
||||
}
|
||||
|
||||
@ -51,10 +51,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.35f, 0.175f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.8f, 0.925f);
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.35f, 0.175f);
|
||||
Rect.anchorMax = new Vector2(0.8f, 0.925f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
|
@ -51,7 +51,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
if (active && !DoneScrollPoolInit)
|
||||
{
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(this.mainPanelRect);
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(this.Rect);
|
||||
logScrollPool.Initialize(this);
|
||||
DoneScrollPoolInit = true;
|
||||
}
|
||||
@ -158,10 +158,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.5f, 0.03f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.9f, 0.2f);
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.5f, 0.03f);
|
||||
Rect.anchorMax = new Vector2(0.9f, 0.2f);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
@ -99,10 +99,10 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.125f, 0.175f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.325f, 0.925f);
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.125f, 0.175f);
|
||||
Rect.anchorMax = new Vector2(0.325f, 0.925f);
|
||||
//mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 350);
|
||||
}
|
||||
|
||||
|
@ -69,11 +69,11 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.5f, 0.1f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.5f, 0.85f);
|
||||
mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
||||
Rect.localPosition = Vector2.zero;
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.5f, 0.1f);
|
||||
Rect.anchorMax = new Vector2(0.5f, 0.85f);
|
||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
@ -250,15 +250,9 @@ namespace UnityExplorer.UI.Panels
|
||||
Vector2 diff = (Vector2)mousePos - m_lastDragPosition;
|
||||
m_lastDragPosition = mousePos;
|
||||
|
||||
var pos = Panel.localPosition + (Vector3)diff;
|
||||
Panel.localPosition = Panel.localPosition + (Vector3)diff;
|
||||
|
||||
// Prevent panel going oustide screen bounds
|
||||
var halfW = Screen.width * 0.5f;
|
||||
var halfH = Screen.height * 0.5f;
|
||||
pos.x = Math.Max(-halfW, Math.Min(pos.x, halfW - Panel.rect.width));
|
||||
pos.y = Math.Max(-halfH + Panel.rect.height, Math.Min(pos.y, halfH));
|
||||
|
||||
Panel.localPosition = pos;
|
||||
UIPanel.EnsureValidPosition(Panel);
|
||||
}
|
||||
|
||||
public void OnEndDrag()
|
||||
@ -425,6 +419,9 @@ namespace UnityExplorer.UI.Panels
|
||||
if ((Vector2)mousePos == m_lastResizePos)
|
||||
return;
|
||||
|
||||
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > Screen.width || mousePos.y > Screen.height)
|
||||
return;
|
||||
|
||||
m_lastResizePos = mousePos;
|
||||
|
||||
float diffX = (float)((decimal)diff.x / Screen.width);
|
||||
|
@ -44,8 +44,8 @@ namespace UnityExplorer.UI.Panels
|
||||
continue;
|
||||
|
||||
// check if our mouse is clicking inside the panel
|
||||
var pos = panel.mainPanelRect.InverseTransformPoint(mousePos);
|
||||
if (!panel.Enabled || !panel.mainPanelRect.rect.Contains(pos))
|
||||
var pos = panel.Rect.InverseTransformPoint(mousePos);
|
||||
if (!panel.Enabled || !panel.Rect.rect.Contains(pos))
|
||||
continue;
|
||||
|
||||
// if this is not the top panel, reorder and invoke the onchanged event
|
||||
@ -88,9 +88,11 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public override GameObject UIRoot => uiRoot;
|
||||
protected GameObject uiRoot;
|
||||
protected RectTransform mainPanelRect;
|
||||
public RectTransform Rect;
|
||||
public GameObject content;
|
||||
|
||||
public GameObject titleBar;
|
||||
|
||||
public abstract void ConstructPanelContent();
|
||||
|
||||
public virtual void OnFinishResize(RectTransform panel)
|
||||
@ -136,14 +138,85 @@ namespace UnityExplorer.UI.Panels
|
||||
public void SetTransformDefaults()
|
||||
{
|
||||
DoSetDefaultPosAndAnchors();
|
||||
|
||||
if (mainPanelRect.rect.width < MinWidth)
|
||||
mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
|
||||
if (mainPanelRect.rect.height < MinHeight)
|
||||
mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||
}
|
||||
|
||||
public GameObject titleBar;
|
||||
public void EnsureValidSize()
|
||||
{
|
||||
if (Rect.rect.width < MinWidth)
|
||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
|
||||
if (Rect.rect.height < MinHeight)
|
||||
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||
}
|
||||
|
||||
public static void EnsureValidPosition(RectTransform panel)
|
||||
{
|
||||
var pos = panel.localPosition;
|
||||
|
||||
// Prevent panel going oustide screen bounds
|
||||
var halfW = Screen.width * 0.5f;
|
||||
var halfH = Screen.height * 0.5f;
|
||||
pos.x = Math.Max(-halfW, Math.Min(pos.x, halfW - panel.rect.width));
|
||||
pos.y = Math.Max(-halfH + panel.rect.height, Math.Min(pos.y, halfH));
|
||||
|
||||
panel.localPosition = pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Save Data
|
||||
|
||||
public abstract void DoSaveToConfigElement();
|
||||
|
||||
public void SaveToConfigManager()
|
||||
{
|
||||
if (UIManager.Initializing)
|
||||
return;
|
||||
|
||||
DoSaveToConfigElement();
|
||||
}
|
||||
|
||||
public abstract string GetSaveDataFromConfigManager();
|
||||
|
||||
public bool ApplyingSaveData { get; set; }
|
||||
|
||||
public virtual string ToSaveData()
|
||||
{
|
||||
try
|
||||
{
|
||||
return $"{ShouldSaveActiveState && Enabled}" +
|
||||
$"|{Rect.RectAnchorsToString()}" +
|
||||
$"|{Rect.RectPositionToString()}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception generating Panel save data: {ex}");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ApplySaveData(string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
return;
|
||||
|
||||
var split = data.Split('|');
|
||||
|
||||
try
|
||||
{
|
||||
Rect.SetAnchorsFromString(split[1]);
|
||||
Rect.SetPositionFromString(split[2]);
|
||||
UIManager.SetPanelActive(this.PanelType, bool.Parse(split[0]));
|
||||
}
|
||||
catch
|
||||
{
|
||||
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
|
||||
SetTransformDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// UI Construction
|
||||
|
||||
public void ConstructUI()
|
||||
{
|
||||
@ -168,7 +241,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// create core canvas
|
||||
uiRoot = UIFactory.CreatePanel(Name, out GameObject panelContent);
|
||||
mainPanelRect = this.uiRoot.GetComponent<RectTransform>();
|
||||
Rect = this.uiRoot.GetComponent<RectTransform>();
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, false, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
|
||||
int id = this.uiRoot.transform.GetInstanceID();
|
||||
@ -177,9 +250,6 @@ namespace UnityExplorer.UI.Panels
|
||||
content = panelContent;
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, false, false, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
|
||||
// always apply default pos and anchors (save data may only be partial)
|
||||
SetTransformDefaults();
|
||||
|
||||
// Title bar
|
||||
titleBar = UIFactory.CreateHorizontalGroup(content, "TitleBar", false, true, true, true, 2,
|
||||
new Vector4(2, 2, 2, 2), new Color(0.06f, 0.06f, 0.06f));
|
||||
@ -210,7 +280,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Panel dragger
|
||||
|
||||
Dragger = new PanelDragger(titleBar.GetComponent<RectTransform>(), mainPanelRect, this);
|
||||
Dragger = new PanelDragger(titleBar.GetComponent<RectTransform>(), Rect, this);
|
||||
Dragger.OnFinishResize += OnFinishResize;
|
||||
Dragger.OnFinishDrag += OnFinishDrag;
|
||||
|
||||
@ -223,6 +293,7 @@ namespace UnityExplorer.UI.Panels
|
||||
UIManager.SetPanelActive(this.PanelType, ShowByDefault);
|
||||
|
||||
ApplyingSaveData = true;
|
||||
SetTransformDefaults();
|
||||
// apply panel save data or revert to default
|
||||
try
|
||||
{
|
||||
@ -234,6 +305,13 @@ namespace UnityExplorer.UI.Panels
|
||||
SetTransformDefaults();
|
||||
}
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(this.Rect);
|
||||
|
||||
// ensure initialized position is valid
|
||||
EnsureValidSize();
|
||||
EnsureValidPosition(this.Rect);
|
||||
|
||||
// update dragger and save data
|
||||
Dragger.OnEndResize();
|
||||
|
||||
// simple listener for saving enabled state
|
||||
@ -241,61 +319,11 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
SaveToConfigManager();
|
||||
};
|
||||
|
||||
ApplyingSaveData = false;
|
||||
}
|
||||
|
||||
public override void ConstructUI(GameObject parent) => ConstructUI();
|
||||
|
||||
// SAVE DATA
|
||||
|
||||
public abstract void DoSaveToConfigElement();
|
||||
|
||||
public void SaveToConfigManager()
|
||||
{
|
||||
if (UIManager.Initializing)
|
||||
return;
|
||||
|
||||
DoSaveToConfigElement();
|
||||
}
|
||||
|
||||
public abstract string GetSaveDataFromConfigManager();
|
||||
|
||||
public bool ApplyingSaveData { get; set; }
|
||||
|
||||
public virtual string ToSaveData()
|
||||
{
|
||||
try
|
||||
{
|
||||
return $"{ShouldSaveActiveState && Enabled}" +
|
||||
$"|{mainPanelRect.RectAnchorsToString()}" +
|
||||
$"|{mainPanelRect.RectPositionToString()}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception generating Panel save data: {ex}");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ApplySaveData(string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
return;
|
||||
|
||||
var split = data.Split('|');
|
||||
|
||||
try
|
||||
{
|
||||
mainPanelRect.SetAnchorsFromString(split[1]);
|
||||
mainPanelRect.SetPositionFromString(split[2]);
|
||||
UIManager.SetPanelActive(this.PanelType, bool.Parse(split[0]));
|
||||
}
|
||||
catch
|
||||
{
|
||||
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
|
||||
SetTransformDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region WINDOW ANCHORS / POSITION HELPERS
|
||||
|
@ -123,6 +123,9 @@ namespace UnityExplorer.UI
|
||||
|
||||
// Main UI Update loop
|
||||
|
||||
private static int lastScreenWidth;
|
||||
private static int lastScreenHeight;
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (!CanvasRoot || Initializing)
|
||||
@ -150,6 +153,19 @@ namespace UnityExplorer.UI
|
||||
PanelDragger.UpdateInstances();
|
||||
InputFieldRef.UpdateInstances();
|
||||
UIBehaviourModel.UpdateInstances();
|
||||
|
||||
if (Screen.width != lastScreenWidth || Screen.height != lastScreenHeight)
|
||||
{
|
||||
lastScreenWidth = Screen.width;
|
||||
lastScreenHeight = Screen.height;
|
||||
|
||||
foreach (var panel in UIPanels)
|
||||
{
|
||||
panel.Value.EnsureValidSize();
|
||||
UIPanel.EnsureValidPosition(panel.Value.Rect);
|
||||
panel.Value.Dragger.OnEndResize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization and UI Construction
|
||||
@ -184,6 +200,9 @@ namespace UnityExplorer.UI
|
||||
|
||||
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
|
||||
|
||||
lastScreenWidth = Screen.width;
|
||||
lastScreenHeight = Screen.height;
|
||||
|
||||
Initializing = false;
|
||||
}
|
||||
|
||||
|
@ -292,9 +292,9 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.42f, 0.4f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.68f, 0.6f);
|
||||
Rect.pivot = new Vector2(0f, 1f);
|
||||
Rect.anchorMin = new Vector2(0.42f, 0.4f);
|
||||
Rect.anchorMax = new Vector2(0.68f, 0.6f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
|
Loading…
x
Reference in New Issue
Block a user