almost done, just interactive unity structs and a few minor things to finish off.

This commit is contained in:
sinaioutlander 2020-11-16 21:21:04 +11:00
parent 4a1125cf1d
commit 91d5fc284f
26 changed files with 1020 additions and 232 deletions

BIN
lib/UnityEngine.UI.dll Normal file

Binary file not shown.

BIN
lib/UnityEngine.dll Normal file

Binary file not shown.

View File

@ -34,7 +34,7 @@ namespace UnityExplorer.CSConsole
public static char indentOpen = '{';
public static char indentClose = '}';
private static readonly StringBuilder indentBuilder = new StringBuilder();
private static StringBuilder indentBuilder = new StringBuilder();
public static char[] delimiters = new[]
{
@ -153,7 +153,7 @@ namespace UnityExplorer.CSConsole
public static string GetIndentForInput(string input, int indent, out int caretPosition)
{
indentBuilder.Clear();
indentBuilder = new StringBuilder();
indent += 1;

View File

@ -61,11 +61,9 @@ namespace UnityExplorer
var obj = new GameObject(
"ExplorerBehaviour",
new Il2CppSystem.Type[]
{
Il2CppType.Of<ExplorerBehaviour>()
}
new Il2CppSystem.Type[] { Il2CppType.Of<ExplorerBehaviour>() }
);
obj.hideFlags = HideFlags.HideAndDontSave;
GameObject.DontDestroyOnLoad(obj);
new ExplorerCore();

View File

@ -77,7 +77,11 @@ namespace UnityExplorer.Helpers
// check if type is injected
IntPtr classPtr = il2cpp_object_get_class(ilObject.Pointer);
if (RuntimeSpecificsStore.IsInjected(classPtr))
return GetTypeByName(il2cppType.FullName);
{
var typeByName = GetTypeByName(il2cppType.FullName);
if (typeByName != null)
return typeByName;
}
// this should be fine for all other il2cpp objects
var getType = GetMonoType(il2cppType);
@ -252,7 +256,13 @@ namespace UnityExplorer.Helpers
public static string ExceptionToString(Exception e, bool innerMost = false)
{
while (innerMost && e.InnerException != null)
{
#if CPP
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException runtimeEx)
break;
#endif
e = e.InnerException;
}
return e.GetType() + ", " + e.Message;
}

View File

@ -12,7 +12,7 @@ namespace UnityExplorer.Inspectors.Reflection
public class CacheEnumerated : CacheObjectBase
{
public override Type FallbackType => ParentEnumeration.m_baseEntryType;
public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite;
public override bool CanWrite => RefIList != null && ParentEnumeration.Owner.CanWrite;
public int Index { get; set; }
public IList RefIList { get; set; }
@ -29,7 +29,7 @@ namespace UnityExplorer.Inspectors.Reflection
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.OwnerCacheObject = this;
IValue.Owner = this;
}
public override void SetValue()
@ -37,7 +37,7 @@ namespace UnityExplorer.Inspectors.Reflection
RefIList[Index] = IValue.Value;
ParentEnumeration.Value = RefIList;
ParentEnumeration.OwnerCacheObject.SetValue();
ParentEnumeration.Owner.SetValue();
}
internal override void ConstructUI()

View File

@ -48,6 +48,10 @@ namespace UnityExplorer.Inspectors.Reflection
MemInfo = memberInfo;
DeclaringType = memberInfo.DeclaringType;
DeclaringInstance = declaringInstance;
#if CPP
if (DeclaringInstance != null)
DeclaringInstance = DeclaringInstance.Il2CppCast(DeclaringType);
#endif
}
public static bool CanProcessArgs(ParameterInfo[] parameters)
@ -70,7 +74,7 @@ namespace UnityExplorer.Inspectors.Reflection
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.OwnerCacheObject = this;
IValue.Owner = this;
IValue.m_mainContentParent = this.m_rightGroup;
IValue.m_subContentParent = this.m_subContent;
}
@ -384,7 +388,7 @@ namespace UnityExplorer.Inspectors.Reflection
argInputLayout.minWidth = 20;
argInputLayout.minHeight = 25;
argInputLayout.flexibleHeight = 0;
argInputLayout.layoutPriority = 2;
//argInputLayout.layoutPriority = 2;
var argInput = argInputObj.GetComponent<InputField>();
argInput.onValueChanged.AddListener((string val) => { m_argumentInput[i] = val; });

View File

@ -37,7 +37,8 @@ namespace UnityExplorer.Inspectors.Reflection
public virtual void Disable()
{
m_mainContent?.SetActive(false);
if (m_mainContent)
m_mainContent.SetActive(false);
}
public void Destroy()

View File

@ -41,7 +41,7 @@ namespace UnityExplorer.Inspectors.Reflection
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.OwnerCacheObject = this;
IValue.Owner = this;
}
#region UI CONSTRUCTION

View File

@ -43,7 +43,16 @@ namespace UnityExplorer.Inspectors.Reflection
}
else
{
// todo write-only properties?
if (FallbackType == typeof(string))
{
IValue.Value = "";
}
else if (FallbackType.IsPrimitive)
{
IValue.Value = Activator.CreateInstance(FallbackType);
}
m_evaluated = true;
ReflectionException = null;
}
}

View File

@ -18,61 +18,96 @@ namespace UnityExplorer.Inspectors.Reflection
public override bool WantInspectBtn => false;
internal Toggle m_toggle;
internal Button m_applyBtn;
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
if (!Value.IsNullOrDestroyed())
public override void RefreshUIForValue()
{
GetDefaultLabel();
if (Owner.HasEvaluated)
{
if (OwnerCacheObject.CanWrite)
var val = (bool)Value;
if (Owner.CanWrite)
{
if (!m_toggle.gameObject.activeSelf)
m_toggle.gameObject.SetActive(true);
var val = (bool)Value;
if (m_toggle.isOn != val)
if (!m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(true);
if (val != m_toggle.isOn)
m_toggle.isOn = val;
}
RefreshUIElements();
var color = val
? "6bc981" // on
: "c96b6b"; // off
m_baseLabel.text = $"<color=#{color}>{val}</color>";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
internal void RefreshUIElements()
public override void OnException(CacheMember member)
{
if (m_baseLabel)
{
var val = (bool)Value;
var color = val
? "00FF00" // on
: "FF0000"; // off
base.OnException(member);
m_baseLabel.text = $"<color=#{color}>{val}</color> ({m_richValueType})";
if (Owner.CanWrite)
{
if (m_toggle.gameObject.activeSelf)
m_toggle.gameObject.SetActive(false);
if (m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(false);
}
}
internal void OnToggleValueChanged(bool val)
{
Value = val;
OwnerCacheObject.SetValue();
RefreshUIElements();
RefreshUIForValue();
}
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
if (OwnerCacheObject.CanWrite)
var baseLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
baseLayout.flexibleWidth = 0;
baseLayout.minWidth = 50;
if (Owner.CanWrite)
{
var toggleObj = UIFactory.CreateToggle(m_valueContent, out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
toggleObj.SetActive(false);
var toggleLayout = toggleObj.AddComponent<LayoutElement>();
toggleLayout.minWidth = 24;
m_toggle.onValueChanged.AddListener(OnToggleValueChanged);
m_baseLabel.transform.SetAsLastSibling();
var applyBtnObj = UIFactory.CreateButton(m_valueContent, new Color(0.2f, 0.2f, 0.2f));
var applyLayout = applyBtnObj.AddComponent<LayoutElement>();
applyLayout.minWidth = 50;
applyLayout.minHeight = 25;
applyLayout.flexibleWidth = 0;
m_applyBtn = applyBtnObj.GetComponent<Button>();
m_applyBtn.onClick.AddListener(() => { Owner.SetValue(); });
var applyText = applyBtnObj.GetComponentInChildren<Text>();
applyText.text = "Apply";
toggleObj.SetActive(false);
applyBtnObj.SetActive(false);
}
}
}

View File

@ -9,6 +9,7 @@ using UnityExplorer.Config;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
using UnityExplorer.UI.Shared;
using System.Reflection;
namespace UnityExplorer.Inspectors.Reflection
{
@ -62,26 +63,22 @@ namespace UnityExplorer.Inspectors.Reflection
public override void OnValueUpdated()
{
RefIDictionary = Value as IDictionary;
if (Value != null)
{
if (m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
}
else
m_recacheWanted = true;
}
else
m_entries.Clear();
base.OnValueUpdated();
if (!Value.IsNullOrDestroyed())
{
RefIDictionary = Value as IDictionary;
UpdateLabel();
}
else
{
m_baseLabel.text = base.GetLabelForValue();
RefIDictionary = null;
}
if (m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
}
else
m_recacheWanted = true;
}
internal void OnPageTurned()
@ -89,15 +86,24 @@ namespace UnityExplorer.Inspectors.Reflection
RefreshDisplay();
}
internal void UpdateLabel()
public override void RefreshUIForValue()
{
string count = "?";
if (m_recacheWanted && RefIDictionary != null)
count = RefIDictionary.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
GetDefaultLabel();
m_baseLabel.text = $"[{count}] {m_richValueType}";
if (Value != null)
{
string count = "?";
if (m_recacheWanted && RefIDictionary != null)
count = RefIDictionary.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
m_baseLabel.text = $"[{count}] {m_richValueType}";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
public void GetCacheEntries()
@ -115,6 +121,11 @@ namespace UnityExplorer.Inspectors.Reflection
m_entries.Clear();
}
#if CPP
if (RefIDictionary == null && !Value.IsNullOrDestroyed())
RefIDictionary = EnumerateWithReflection();
#endif
if (RefIDictionary != null)
{
int index = 0;
@ -194,12 +205,61 @@ namespace UnityExplorer.Inspectors.Reflection
{
m_recacheWanted = false;
GetCacheEntries();
UpdateLabel();
RefreshUIForValue();
}
RefreshDisplay();
}
#region CPP fixes
#if CPP
// temp fix for Il2Cpp IDictionary until interfaces are fixed
private IDictionary EnumerateWithReflection()
{
var valueType = Value?.GetType() ?? FallbackType;
// get keys and values
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
var values = valueType.GetProperty("Values").GetValue(Value, null);
// create lists to hold them
var keyList = new List<object>();
var valueList = new List<object>();
// store entries with reflection
EnumerateWithReflection(keys, keyList);
EnumerateWithReflection(values, valueList);
// make actual mono dictionary
var dict = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>)
.MakeGenericType(m_typeOfKeys, m_typeofValues));
// finally iterate into mono dictionary
for (int i = 0; i < keyList.Count; i++)
dict.Add(keyList[i], valueList[i]);
return dict;
}
private void EnumerateWithReflection(object collection, List<object> list)
{
// invoke GetEnumerator
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
// get the type of it
var enumeratorType = enumerator.GetType();
// reflect MoveNext and Current
var moveNext = enumeratorType.GetMethod("MoveNext");
var current = enumeratorType.GetProperty("Current");
// iterate
while ((bool)moveNext.Invoke(enumerator, null))
{
list.Add(current.GetValue(enumerator, null));
}
}
#endif
#endregion
#region UI CONSTRUCTION
internal GameObject m_listContent;
@ -228,10 +288,10 @@ namespace UnityExplorer.Inspectors.Reflection
var scrollRect = scrollObj.GetComponent<RectTransform>();
scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
m_listLayout = OwnerCacheObject.m_mainContent.GetComponent<LayoutElement>();
m_listLayout = Owner.m_mainContent.GetComponent<LayoutElement>();
m_listLayout.minHeight = 25;
m_listLayout.flexibleHeight = 0;
OwnerCacheObject.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
var scrollGroup = m_listContent.GetComponent<VerticalLayoutGroup>();
scrollGroup.childForceExpandHeight = true;

View File

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
namespace UnityExplorer.Inspectors.Reflection
{
public class InteractiveEnum : InteractiveValue
{
internal static Dictionary<Type, KeyValuePair<int,string>[]> s_enumNamesCache = new Dictionary<Type, KeyValuePair<int, string>[]>();
public InteractiveEnum(object value, Type valueType) : base(value, valueType)
{
GetNames();
}
public override bool HasSubContent => true;
public override bool SubContentWanted => Owner.CanWrite;
public override bool WantInspectBtn => false;
internal KeyValuePair<int,string>[] m_values = new KeyValuePair<int, string>[0];
internal void GetNames()
{
var type = Value?.GetType() ?? FallbackType;
if (!s_enumNamesCache.ContainsKey(type))
{
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
var values = Enum.GetValues(type);
var list = new List<KeyValuePair<int, string>>();
var set = new HashSet<string>();
foreach (var value in values)
{
var name = value.ToString();
if (set.Contains(name))
continue;
set.Add(name);
list.Add(new KeyValuePair<int, string>((int)value, name));
}
s_enumNamesCache.Add(type, list.ToArray());
}
m_values = s_enumNamesCache[type];
}
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
public override void RefreshUIForValue()
{
base.RefreshUIForValue();
if (m_subContentConstructed)
{
m_dropdownText.text = Value?.ToString() ?? "<no value set>";
}
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUIForValue();
}
private void SetValueFromDropdown()
{
var type = Value?.GetType() ?? FallbackType;
var value = Enum.Parse(type, m_dropdownText.text);
if (value != null)
{
Value = value;
Owner.SetValue();
RefreshUIForValue();
}
}
internal Dropdown m_dropdown;
internal Text m_dropdownText;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
if (Owner.CanWrite)
{
var groupObj = UIFactory.CreateHorizontalGroup(m_subContentParent, new Color(1, 1, 1, 0));
var group = groupObj.GetComponent<HorizontalLayoutGroup>();
group.padding.top = 3;
group.padding.left = 3;
group.padding.right = 3;
group.padding.bottom = 3;
group.spacing = 5;
// apply button
var applyObj = UIFactory.CreateButton(groupObj, new Color(0.3f, 0.3f, 0.3f));
var applyLayout = applyObj.AddComponent<LayoutElement>();
applyLayout.minHeight = 25;
applyLayout.minWidth = 50;
var applyText = applyObj.GetComponentInChildren<Text>();
applyText.text = "Apply";
var applyBtn = applyObj.GetComponent<Button>();
applyBtn.onClick.AddListener(SetValueFromDropdown);
// dropdown
var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown);
var dropLayout = dropdownObj.AddComponent<LayoutElement>();
dropLayout.minWidth = 150;
dropLayout.minHeight = 25;
dropLayout.flexibleWidth = 120;
foreach (var kvp in m_values)
{
m_dropdown.options.Add(new Dropdown.OptionData
{
text = $"{kvp.Key}: {kvp.Value}"
});
}
m_dropdownText = m_dropdown.transform.Find("Label").GetComponent<Text>();
}
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
@ -45,30 +46,28 @@ namespace UnityExplorer.Inspectors.Reflection
public override void OnValueUpdated()
{
RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList;
if (Value != null)
{
if (m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
}
else
m_recacheWanted = true;
}
else
m_entries.Clear();
base.OnValueUpdated();
}
if (!Value.IsNullOrDestroyed())
{
RefIEnumerable = Value as IEnumerable; // todo il2cpp
RefIList = Value as IList;
UpdateLabel();
}
else
{
m_baseLabel.text = base.GetLabelForValue();
RefIEnumerable = null;
RefIList = null;
}
if (m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
}
else
m_recacheWanted = true;
public override void OnException(CacheMember member)
{
base.OnException(member);
}
private void OnPageTurned()
@ -76,15 +75,24 @@ namespace UnityExplorer.Inspectors.Reflection
RefreshDisplay();
}
internal void UpdateLabel()
public override void RefreshUIForValue()
{
string count = "?";
if (m_recacheWanted && RefIList != null)
count = RefIList.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
GetDefaultLabel();
m_baseLabel.text = $"[{count}] {m_richValueType}";
if (Value != null)
{
string count = "?";
if (m_recacheWanted && RefIList != null)
count = RefIList.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
m_baseLabel.text = $"[{count}] {m_richValueType}";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
public void GetCacheEntries()
@ -99,6 +107,11 @@ namespace UnityExplorer.Inspectors.Reflection
m_entries.Clear();
}
#if CPP
if (RefIEnumerable == null && !Value.IsNullOrDestroyed())
RefIEnumerable = EnumerateWithReflection();
#endif
if (RefIEnumerable != null)
{
int index = 0;
@ -155,12 +168,94 @@ namespace UnityExplorer.Inspectors.Reflection
{
m_recacheWanted = false;
GetCacheEntries();
UpdateLabel();
RefreshUIForValue();
}
RefreshDisplay();
}
#region CPP Helpers
#if CPP
// some temp fixes for Il2Cpp IEnumerables until interfaces are fixed
private IEnumerable EnumerateWithReflection()
{
if (Value.IsNullOrDestroyed())
return null;
var genericDef = Value.GetType().GetGenericTypeDefinition();
if (genericDef == typeof(Il2CppSystem.Collections.Generic.List<>))
return CppListToMono(genericDef);
else if (genericDef == typeof(Il2CppSystem.Collections.Generic.HashSet<>))
return CppHashSetToMono();
else
return CppIListToMono();
}
// List<T>.ToArray()
private IEnumerable CppListToMono(Type genericTypeDef)
{
if (genericTypeDef == null) return null;
return genericTypeDef
.MakeGenericType(new Type[] { this.m_baseEntryType })
.GetMethod("ToArray")
.Invoke(Value, new object[0]) as IEnumerable;
}
// HashSet.GetEnumerator
private IEnumerable CppHashSetToMono()
{
var set = new HashSet<object>();
// invoke GetEnumerator
var enumerator = Value.GetType().GetMethod("GetEnumerator").Invoke(Value, null);
// get the type of it
var enumeratorType = enumerator.GetType();
// reflect MoveNext and Current
var moveNext = enumeratorType.GetMethod("MoveNext");
var current = enumeratorType.GetProperty("Current");
// iterate
while ((bool)moveNext.Invoke(enumerator, null))
set.Add(current.GetValue(enumerator));
return set;
}
// IList.Item
private IList CppIListToMono()
{
try
{
var genericType = typeof(List<>).MakeGenericType(new Type[] { this.m_baseEntryType });
var list = (IList)Activator.CreateInstance(genericType);
for (int i = 0; ; i++)
{
try
{
var itm = Value?.GetType()
.GetProperty("Item")
.GetValue(Value, new object[] { i });
list.Add(itm);
}
catch { break; }
}
return list;
}
catch (Exception e)
{
ExplorerCore.Log("Exception converting Il2Cpp IList to Mono IList: " + e.GetType() + ", " + e.Message);
return null;
}
}
#endif
#endregion
#region UI CONSTRUCTION
internal GameObject m_listContent;
@ -187,10 +282,10 @@ namespace UnityExplorer.Inspectors.Reflection
var scrollRect = scrollObj.GetComponent<RectTransform>();
scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
m_listLayout = OwnerCacheObject.m_mainContent.GetComponent<LayoutElement>();
m_listLayout = Owner.m_mainContent.GetComponent<LayoutElement>();
m_listLayout.minHeight = 25;
m_listLayout.flexibleHeight = 0;
OwnerCacheObject.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
var scrollGroup = m_listContent.GetComponent<VerticalLayoutGroup>();
scrollGroup.childForceExpandHeight = true;

View File

@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
namespace UnityExplorer.Inspectors.Reflection
{
public class InteractiveFlags : InteractiveEnum
{
public InteractiveFlags(object value, Type valueType) : base(value, valueType)
{
m_toggles = new Toggle[m_values.Length];
m_enabledFlags = new bool[m_values.Length];
}
public override bool HasSubContent => true;
public override bool SubContentWanted => Owner.CanWrite;
public override bool WantInspectBtn => false;
internal bool[] m_enabledFlags;
internal Toggle[] m_toggles;
public override void OnValueUpdated()
{
base.OnValueUpdated();
if (Owner.CanWrite)
{
var enabledNames = new List<string>();
var enabled = Value?.ToString().Split(',').Select(it => it.Trim());
if (enabled != null)
enabledNames.AddRange(enabled);
for (int i = 0; i < m_values.Length; i++)
{
m_enabledFlags[i] = enabledNames.Contains(m_values[i].Value);
}
}
}
public override void RefreshUIForValue()
{
//base.RefreshUIForValue();
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
if (m_subContentConstructed)
{
for (int i = 0; i < m_values.Length; i++)
{
var toggle = m_toggles[i];
if (toggle.isOn != m_enabledFlags[i])
toggle.isOn = m_enabledFlags[i];
}
}
}
private void SetValueFromToggles()
{
string val = "";
for (int i = 0; i < m_values.Length; i++)
{
if (m_enabledFlags[i])
{
if (val != "") val += ", ";
val += m_values[i].Value;
}
}
var type = Value?.GetType() ?? FallbackType;
Value = Enum.Parse(type, val);
RefreshUIForValue();
Owner.SetValue();
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUIForValue();
}
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
m_subContentConstructed = true;
if (Owner.CanWrite)
{
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, new Color(1, 1, 1, 0));
var group = groupObj.GetComponent<VerticalLayoutGroup>();
group.childForceExpandHeight = true;
group.childForceExpandWidth = false;
group.childControlHeight = true;
group.childControlWidth = true;
group.padding.top = 3;
group.padding.left = 3;
group.padding.right = 3;
group.padding.bottom = 3;
group.spacing = 5;
// apply button
var applyObj = UIFactory.CreateButton(groupObj, new Color(0.3f, 0.3f, 0.3f));
var applyLayout = applyObj.AddComponent<LayoutElement>();
applyLayout.minHeight = 25;
applyLayout.minWidth = 50;
var applyText = applyObj.GetComponentInChildren<Text>();
applyText.text = "Apply";
var applyBtn = applyObj.GetComponent<Button>();
applyBtn.onClick.AddListener(SetValueFromToggles);
// toggles
for (int i = 0; i < m_values.Length; i++)
{
AddToggle(i, groupObj);
}
}
}
internal void AddToggle(int index, GameObject groupObj)
{
var value = m_values[index];
var toggleObj = UIFactory.CreateToggle(groupObj, out Toggle toggle, out Text text, new Color(0.1f, 0.1f, 0.1f));
var toggleLayout = toggleObj.AddComponent<LayoutElement>();
toggleLayout.minWidth = 100;
toggleLayout.flexibleWidth = 2000;
toggleLayout.minHeight = 25;
m_toggles[index] = toggle;
toggle.onValueChanged.AddListener((bool val) => { m_enabledFlags[index] = val; });
text.text = $"{value.Key}: {value.Value}";
}
}
}

View File

@ -2,7 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
namespace UnityExplorer.Inspectors.Reflection
{
@ -14,16 +18,108 @@ namespace UnityExplorer.Inspectors.Reflection
public override bool SubContentWanted => false;
public override bool WantInspectBtn => false;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
public override void OnException(CacheMember member)
{
base.OnException(member);
if (m_valueInput.gameObject.activeSelf)
m_valueInput.gameObject.SetActive(false);
if (Owner.CanWrite)
{
if (m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(false);
}
}
public override void RefreshUIForValue()
{
if (!Owner.HasEvaluated)
{
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
return;
}
m_baseLabel.text = UISyntaxHighlight.ParseFullSyntax(FallbackType, false);
m_valueInput.text = Value.ToString();
if (Owner.CanWrite)
{
if (!m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(true);
}
if (!m_valueInput.gameObject.activeSelf)
m_valueInput.gameObject.SetActive(true);
}
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
private MethodInfo m_parseMethod;
internal void OnApplyClicked()
{
try
{
Value = ParseMethod.Invoke(null, new object[] { m_valueInput.text });
Owner.SetValue();
RefreshUIForValue();
}
catch (Exception e)
{
ExplorerCore.LogWarning("Could not parse input! " + ReflectionHelpers.ExceptionToString(e, true));
}
}
internal InputField m_valueInput;
internal Button m_applyBtn;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
var labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
labelLayout.minWidth = 50;
labelLayout.flexibleWidth = 0;
var inputObj = UIFactory.CreateInputField(m_valueContent);
var inputLayout = inputObj.AddComponent<LayoutElement>();
inputLayout.minWidth = 120;
inputLayout.minHeight = 25;
inputLayout.flexibleWidth = 0;
m_valueInput = inputObj.GetComponent<InputField>();
m_valueInput.gameObject.SetActive(false);
if (this.FallbackType == typeof(float)
|| this.FallbackType == typeof(double)
|| this.FallbackType == typeof(decimal))
{
m_valueInput.characterValidation = InputField.CharacterValidation.Decimal;
}
else
{
m_valueInput.characterValidation = InputField.CharacterValidation.Integer;
}
if (Owner.CanWrite)
{
var applyBtnObj = UIFactory.CreateButton(m_valueContent, new Color(0.2f, 0.2f, 0.2f));
var applyLayout = applyBtnObj.AddComponent<LayoutElement>();
applyLayout.minWidth = 50;
applyLayout.minHeight = 25;
applyLayout.flexibleWidth = 0;
m_applyBtn = applyBtnObj.GetComponent<Button>();
m_applyBtn.onClick.AddListener(OnApplyClicked);
var applyText = applyBtnObj.GetComponentInChildren<Text>();
applyText.text = "Apply";
}
}
}
}

View File

@ -2,7 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Helpers;
using UnityExplorer.UI;
namespace UnityExplorer.Inspectors.Reflection
{
@ -14,16 +18,132 @@ namespace UnityExplorer.Inspectors.Reflection
public override bool SubContentWanted => false;
public override bool WantInspectBtn => false;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
public override void OnException(CacheMember member)
{
base.OnException(member);
if (m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(false);
// m_baseLabel.text = DefaultLabel;
m_labelLayout.minWidth = 200;
m_labelLayout.flexibleWidth = 5000;
}
public override void RefreshUIForValue()
{
GetDefaultLabel(false);
if (!Owner.HasEvaluated)
{
m_baseLabel.text = DefaultLabel;
return;
}
if (!m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(true);
m_baseLabel.text = m_richValueType;
if (Value != null)
{
var toString = Value.ToString();
if (toString.Length > 15000)
toString = toString.Substring(0, 15000);
m_valueInput.text = toString;
m_placeholderText.text = toString;
}
else
{
m_valueInput.text = "";
m_placeholderText.text = "null";
}
m_labelLayout.minWidth = 50;
m_labelLayout.flexibleWidth = 0;
}
internal void OnApplyClicked()
{
Value = m_valueInput.text;
Owner.SetValue();
}
internal InputField m_valueInput;
internal LayoutElement m_labelLayout;
internal GameObject m_hiddenObj;
internal Text m_placeholderText;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
GetDefaultLabel(false);
m_richValueType = UISyntaxHighlight.ParseFullSyntax(FallbackType, false);
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
m_hiddenObj = UIFactory.CreateLabel(m_valueContent, TextAnchor.MiddleLeft);
m_hiddenObj.SetActive(false);
var hiddenText = m_hiddenObj.GetComponent<Text>();
hiddenText.color = Color.clear;
hiddenText.fontSize = 14;
hiddenText.raycastTarget = false;
var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>();
hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var hiddenLayout = m_hiddenObj.AddComponent<LayoutElement>();
hiddenLayout.minHeight = 25;
hiddenLayout.flexibleHeight = 500;
hiddenLayout.minWidth = 250;
hiddenLayout.flexibleWidth = 9000;
var hiddenGroup = m_hiddenObj.AddComponent<HorizontalLayoutGroup>();
hiddenGroup.childForceExpandWidth = true;
hiddenGroup.childControlWidth = true;
hiddenGroup.childForceExpandHeight = true;
hiddenGroup.childControlHeight = true;
var inputObj = UIFactory.CreateInputField(m_hiddenObj, 14, 3);
var inputLayout = inputObj.AddComponent<LayoutElement>();
inputLayout.minWidth = 120;
inputLayout.minHeight = 25;
inputLayout.flexibleWidth = 5000;
inputLayout.flexibleHeight = 5000;
m_valueInput = inputObj.GetComponent<InputField>();
m_valueInput.lineType = InputField.LineType.MultiLineNewline;
m_placeholderText = m_valueInput.placeholder.GetComponent<Text>();
m_valueInput.onValueChanged.AddListener((string val) =>
{
hiddenText.text = val;
LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect);
});
if (Owner.CanWrite)
{
var applyBtnObj = UIFactory.CreateButton(m_valueContent, new Color(0.2f, 0.2f, 0.2f));
var applyLayout = applyBtnObj.AddComponent<LayoutElement>();
applyLayout.minWidth = 50;
applyLayout.minHeight = 25;
applyLayout.flexibleWidth = 0;
var applyBtn = applyBtnObj.GetComponent<Button>();
applyBtn.onClick.AddListener(OnApplyClicked);
var applyText = applyBtnObj.GetComponentInChildren<Text>();
applyText.text = "Apply";
}
else
{
m_valueInput.readOnly = true;
}
}
}
}

View File

@ -21,6 +21,13 @@ namespace UnityExplorer.Inspectors.Reflection
return typeof(InteractiveString);
else if (type.IsPrimitive)
return typeof(InteractiveNumber);
else if (typeof(Enum).IsAssignableFrom(type))
{
if (type.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
return typeof(InteractiveFlags);
else
return typeof(InteractiveEnum);
}
else if (typeof(Transform).IsAssignableFrom(type))
return typeof(InteractiveValue);
else if (ReflectionHelpers.IsDictionary(type))
@ -47,7 +54,7 @@ namespace UnityExplorer.Inspectors.Reflection
this.FallbackType = valueType;
}
public CacheObjectBase OwnerCacheObject;
public CacheObjectBase Owner;
public object Value { get; set; }
public readonly Type FallbackType;
@ -56,8 +63,8 @@ namespace UnityExplorer.Inspectors.Reflection
public virtual bool SubContentWanted => false;
public virtual bool WantInspectBtn => true;
public string RichTextValue => m_richValue ?? GetLabelForValue();
internal string m_richValue;
public string DefaultLabel => m_defaultLabel ?? GetDefaultLabel();
internal string m_defaultLabel;
internal string m_richValueType;
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
@ -73,6 +80,15 @@ namespace UnityExplorer.Inspectors.Reflection
m_valueContent.SetActive(false);
GameObject.Destroy(this.m_valueContent.gameObject);
}
if (this.m_subContentParent && SubContentWanted)
{
for (int i = 0; i < this.m_subContentParent.transform.childCount; i++)
{
var child = m_subContentParent.transform.GetChild(i);
if (child)
GameObject.Destroy(child.gameObject);
}
}
}
public virtual void OnValueUpdated()
@ -80,18 +96,28 @@ namespace UnityExplorer.Inspectors.Reflection
if (!m_UIConstructed)
ConstructUI(m_mainContentParent, m_subContentParent);
if (OwnerCacheObject is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
{
m_baseLabel.text = "<color=red>" + ownerMember.ReflectionException + "</color>";
Value = null;
OnException(ownerMember);
}
else
{
GetLabelForValue();
m_baseLabel.text = RichTextValue;
RefreshUIForValue();
}
}
public virtual void OnException(CacheMember member)
{
m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>";
Value = null;
}
public virtual void RefreshUIForValue()
{
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
}
public void RefreshElementsAfterUpdate()
{
if (WantInspectBtn)
@ -103,7 +129,7 @@ namespace UnityExplorer.Inspectors.Reflection
}
bool subContentWanted = SubContentWanted;
if (OwnerCacheObject is CacheMember cm && !cm.HasEvaluated)
if (Owner is CacheMember cm && (!cm.HasEvaluated || !string.IsNullOrEmpty(cm.ReflectionException)))
subContentWanted = false;
if (HasSubContent)
@ -116,7 +142,7 @@ namespace UnityExplorer.Inspectors.Reflection
}
}
public virtual void ConstructSubcontent()
public virtual void ConstructSubcontent()
{
m_subContentConstructed = true;
}
@ -146,23 +172,21 @@ namespace UnityExplorer.Inspectors.Reflection
ConstructSubcontent();
}
public string GetLabelForValue()
public string GetDefaultLabel(bool updateType = true)
{
var valueType = Value?.GetType() ?? this.FallbackType;
if (updateType)
m_richValueType = UISyntaxHighlight.ParseFullSyntax(valueType, true);
m_richValueType = UISyntaxHighlight.ParseFullSyntax(valueType, true);
if (OwnerCacheObject is CacheMember cm && !cm.HasEvaluated)
return $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
if (!Owner.HasEvaluated)
return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
if (Value.IsNullOrDestroyed())
{
return $"<color=grey>null</color> ({m_richValueType})";
}
return m_defaultLabel = $"<color=grey>null</color> ({m_richValueType})";
string label;
if (valueType == typeof(TextAsset) && Value is TextAsset textAsset)
if (Value is TextAsset textAsset)
{
label = textAsset.text;
@ -171,7 +195,7 @@ namespace UnityExplorer.Inspectors.Reflection
label = $"\"{label}\" {textAsset.name} ({m_richValueType})";
}
else if (valueType == typeof(EventSystem))
else if (Value is EventSystem)
{
label = m_richValueType;
}
@ -204,7 +228,7 @@ namespace UnityExplorer.Inspectors.Reflection
}
}
return m_richValue = label;
return m_defaultLabel = label;
}
private MethodInfo GetToStringMethod()

View File

@ -617,7 +617,7 @@ namespace UnityExplorer.Inspectors
internal void ConstructMemberList()
{
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.12f, 0.12f, 0.12f));
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.08f, 0.08f, 0.08f));
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();

View File

@ -29,8 +29,12 @@ namespace UnityExplorer.Inspectors
private const float UPDATE_INTERVAL = 1f;
private float m_timeOfLastSceneUpdate;
// private int m_currentSceneHandle = -1;
public static Scene DontDestroyScene => DontDestroyObject.scene;
internal Scene m_currentScene;
internal Scene[] m_currentScenes = new Scene[0];
private GameObject m_selectedSceneObject;
private int m_currentSceneHandle = -1;
private int m_lastCount;
private Dropdown m_sceneDropdown;
@ -46,7 +50,6 @@ namespace UnityExplorer.Inspectors
private readonly List<Text> m_shortListTexts = new List<Text>();
private readonly List<Toggle> m_shortListToggles = new List<Toggle>();
public static int DontDestroyHandle => DontDestroyObject.scene.handle;
internal static GameObject DontDestroyObject
{
@ -79,9 +82,13 @@ namespace UnityExplorer.Inspectors
if (!m_selectedSceneObject)
{
if (m_currentSceneHandle != -1)
if (m_currentScene != default)
{
SetSceneObjectList(SceneUnstrip.GetRootGameObjects(m_currentSceneHandle));
#if CPP
SetSceneObjectList(SceneUnstrip.GetRootGameObjects(m_currentScene.handle));
#else
SetSceneObjectList(m_currentScene.GetRootGameObjects());
#endif
}
}
else
@ -90,19 +97,21 @@ namespace UnityExplorer.Inspectors
}
}
public int GetSceneHandle(string sceneName)
{
if (sceneName == "DontDestroyOnLoad")
return DontDestroyHandle;
//#if CPP
// public int GetSceneHandle(string sceneName)
// {
// if (sceneName == "DontDestroyOnLoad")
// return DontDestroyScene;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (scene.name == sceneName)
return scene.handle;
}
return -1;
}
// for (int i = 0; i < SceneManager.sceneCount; i++)
// {
// var scene = SceneManager.GetSceneAt(i);
// if (scene.name == sceneName)
// return scene.handle;
// }
// return -1;
// }
//#endif
internal void OnSceneChange()
{
@ -113,23 +122,21 @@ namespace UnityExplorer.Inspectors
private void RefreshSceneSelector()
{
var names = new List<string>();
var handles = new List<int>();
var scenes = new List<Scene>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
int handle = scene.handle;
if (scene == null || handle == -1 || string.IsNullOrEmpty(scene.name))
if (scene == default)
continue;
handles.Add(handle);
scenes.Add(scene);
names.Add(scene.name);
}
names.Add("DontDestroyOnLoad");
handles.Add(DontDestroyHandle);
scenes.Add(DontDestroyScene);
m_sceneDropdown.options.Clear();
@ -141,20 +148,27 @@ namespace UnityExplorer.Inspectors
if (!names.Contains(m_sceneDropdownText.text))
{
m_sceneDropdownText.text = names[0];
SetTargetScene(handles[0]);
SetTargetScene(scenes[0]);
}
m_currentScenes = scenes.ToArray();
}
public void SetTargetScene(string name) => SetTargetScene(GetSceneHandle(name));
//#if CPP
// public void SetTargetScene(string name) => SetTargetScene(scene.handle);
//#endif
public void SetTargetScene(int handle)
public void SetTargetScene(Scene scene)
{
if (handle == -1)
if (scene == default)
return;
m_currentSceneHandle = handle;
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(handle);
m_currentScene = scene;
#if CPP
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(scene.handle);
#else
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(scene);
#endif
SetSceneObjectList(rootObjs);
m_selectedSceneObject = null;
@ -301,7 +315,7 @@ namespace UnityExplorer.Inspectors
m_lastCount = newCount;
}
#region UI CONSTRUCTION
#region UI CONSTRUCTION
public void ConstructScenePane()
{
@ -341,8 +355,8 @@ namespace UnityExplorer.Inspectors
void SetSceneFromDropdown(int val)
{
string scene = m_sceneDropdown.options[val].text;
SetTargetScene(scene);
//string scene = m_sceneDropdown.options[val].text;
SetTargetScene(m_currentScenes[val]);
}
GameObject scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, new Color(1, 1, 1, 0f));
@ -375,7 +389,7 @@ namespace UnityExplorer.Inspectors
if (!m_selectedSceneObject || !m_selectedSceneObject.transform.parent?.gameObject)
{
m_selectedSceneObject = null;
SetTargetScene(m_currentSceneHandle);
SetTargetScene(m_currentScene);
}
else
{
@ -540,6 +554,6 @@ namespace UnityExplorer.Inspectors
inspectBtn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_shortList[thisIndex]); });
}
#endregion
#endregion
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using UnityExplorer.UI;
using UnityEngine;
using System;
#if CPP
#endif
@ -23,21 +24,54 @@ namespace UnityExplorer.Tests
public class TestClass
{
public bool ATestBoolMethod() => false;
public bool this[int index]
{
get => index % 2 == 0;
set => m_thisBool = value;
}
internal bool m_thisBool;
static int testInt;
public static List<string> ExceptionList
{
get
{
testInt++;
if (testInt % 2 == 0)
throw new Exception("its even");
else
return new List<string> { "one" };
}
}
static bool abool;
public static bool ATestExceptionBool
{
get
{
abool = !abool;
if (!abool)
throw new Exception("false");
else
return true;
}
}
public static string ExceptionString => throw new NotImplementedException();
public static string ANullString = null;
public static float ATestFloat = 420.69f;
public static int ATestInt = -1;
public static string ATestString = "hello world";
public static uint ATestUInt = 1u;
public static byte ATestByte = 255;
public static ulong AReadonlyUlong = 82934UL;
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
private static TestClass m_instance;
public Dictionary<string, List<string>> AComboTest = new Dictionary<string, List<string>>
{
{
"key",
new List<string>
{
"1",
"2"
}
}
};
public object AmbigObject;
public List<List<List<string>>> ANestedNestedList = new List<List<List<string>>>
@ -76,7 +110,9 @@ namespace UnityExplorer.Tests
public static Sprite TestSprite;
#if CPP
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
public static Il2CppSystem.Collections.Generic.HashSet<string> CppHashSetTest;
public static Il2CppSystem.Collections.Generic.List<string> CppStringTest;
public static Il2CppSystem.Collections.IList CppIList;
#endif
public TestClass()
@ -107,10 +143,14 @@ namespace UnityExplorer.Tests
//var dataToLoad = System.IO.File.ReadAllBytes(@"Mods\UnityExplorer\Tex_Nemundis_Nebula.png");
//ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
ILHashSetTest.Add("1");
ILHashSetTest.Add("2");
ILHashSetTest.Add("3");
CppHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
CppHashSetTest.Add("1");
CppHashSetTest.Add("2");
CppHashSetTest.Add("3");
CppStringTest = new Il2CppSystem.Collections.Generic.List<string>();
CppStringTest.Add("1");
CppStringTest.Add("2");
#endif
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using UnityExplorer.Unstrip;
//using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;

View File

@ -295,8 +295,8 @@ namespace UnityExplorer.UI
else if (m_currentResizeType.HasFlag(ResizeTypes.Bottom))
anchorMin.y -= diffY;
//Panel.anchorMin = new Vector2(anchorMin.x, anchorMin.y);
//Panel.anchorMax = new Vector2(anchorMax.x, anchorMax.y);
Panel.anchorMin = new Vector2(anchorMin.x, anchorMin.y);
Panel.anchorMax = new Vector2(anchorMax.x, anchorMax.y);
var newWidth = (anchorMax.x - anchorMin.x) * Screen.width;
var newHeight = (anchorMax.y - anchorMin.y) * Screen.height;
@ -346,4 +346,14 @@ namespace UnityExplorer.UI
#endregion
}
// Just to allow Enum to do .HasFlag() in NET 3.5
public static class Net35FlagsEx
{
public static bool HasFlag(this Enum flags, Enum value)
{
ulong num = Convert.ToUInt64(value);
return (Convert.ToUInt64(flags) & num) == num;
}
}
}

View File

@ -44,6 +44,9 @@ namespace UnityExplorer.UI
{
string ret = "";
if (type == null)
return "????????????";
if (type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter))
{
ret = $"<color={Enum}>{type.Name}</color>";

View File

@ -6,7 +6,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}</ProjectGuid>
<OutputType>Library</OutputType>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<!--<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>-->
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
@ -40,7 +40,7 @@
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
<!-- <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> -->
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OutputPath>..\Release\UnityExplorer.MelonLoader.Il2Cpp\</OutputPath>
<DefineConstants>CPP,ML</DefineConstants>
<AssemblyName>UnityExplorer.ML.IL2CPP</AssemblyName>
@ -49,7 +49,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<OutputPath>..\Release\UnityExplorer.MelonLoader.Mono\</OutputPath>
<DefineConstants>MONO,ML</DefineConstants>
<AssemblyName>UnityExplorer.ML.Mono</AssemblyName>
@ -59,15 +59,16 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
<!-- <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> -->
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<OutputPath>..\Release\UnityExplorer.BepInEx.Il2Cpp\</OutputPath>
<DefineConstants>CPP,BIE</DefineConstants>
<AssemblyName>UnityExplorer.BIE.IL2CPP</AssemblyName>
<IsCpp>true</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<OutputPath>..\Release\UnityExplorer.BepInEx.Mono\</OutputPath>
<DefineConstants>MONO,BIE</DefineConstants>
<AssemblyName>UnityExplorer.BIE.Mono</AssemblyName>
@ -89,7 +90,6 @@
</Reference>
</ItemGroup>
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
<!--
<ItemGroup Condition="'$(IsCpp)'=='false'">
<Reference Include="UnityEngine">
<HintPath>..\lib\UnityEngine.dll</HintPath>
@ -99,26 +99,14 @@
<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>-->
</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.TextCoreModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.TextCoreModule.dll</HintPath>
<Private>False</Private>
</Reference> -->
<Reference Include="UnityEngine">
<!--<Reference Include="UnityEngine">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
@ -149,7 +137,7 @@
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>$(MLMonoManagedFolder)\UnityEngine.ImageConversionModule.dll</HintPath>
<Private>False</Private>
</Reference>
</Reference>-->
</ItemGroup>
<!-- BepInEx Mono refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|false'">
@ -161,15 +149,7 @@
<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.TextCoreModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.TextCoreModule.dll</HintPath>
<Private>False</Private>
</Reference> -->
<Reference Include="UnityEngine.AssetBundleModule">
<!--<Reference Include="UnityEngine.AssetBundleModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.AssetBundleModule.dll</HintPath>
<Private>False</Private>
</Reference>
@ -204,7 +184,7 @@
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>$(BIEMonoManagedFolder)\UnityEngine.ImageConversionModule.dll</HintPath>
<Private>False</Private>
</Reference>
</Reference>-->
</ItemGroup>
<!-- MelonLoader Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='true|true'">
@ -346,7 +326,9 @@
<Compile Include="Inspectors\GameObjects\GameObjectControls.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveBool.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveDictionary.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveEnum.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveEnumerable.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveFlags.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveNumber.cs" />
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveString.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" />

View File

@ -11,26 +11,26 @@ namespace UnityExplorer.Unstrip
#if MONO
public static GameObject[] GetRootGameObjects(Scene scene) => scene.GetRootGameObjects();
public static GameObject[] GetRootGameObjects(int handle)
{
Scene scene = default;
if (handle == SceneExplorer.DontDestroyHandle)
scene = SceneExplorer.DontDestroyObject.scene;
else
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var iscene = SceneManager.GetSceneAt(i);
if (iscene.handle == handle)
scene = iscene;
}
}
//public static GameObject[] GetRootGameObjects(int handle)
//{
// Scene scene = default;
// if (handle == SceneExplorer.DontDestroyHandle)
// scene = SceneExplorer.DontDestroyObject.scene;
// else
// {
// for (int i = 0; i < SceneManager.sceneCount; i++)
// {
// var iscene = SceneManager.GetSceneAt(i);
// if (iscene.handle == handle)
// scene = iscene;
// }
// }
if (scene != default && scene.handle != -1)
return scene.GetRootGameObjects();
// if (scene != default && scene.handle != -1)
// return scene.GetRootGameObjects();
return new GameObject[0];
}
// return new GameObject[0];
//}
#endif
#if CPP