mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-01 11:12:49 +08:00
Setting values from IList / IDictionary to source
This commit is contained in:
@ -311,6 +311,8 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return il2cppPtr != IntPtr.Zero;
|
||||
}
|
||||
|
||||
#region EXTERN CAST METHODS
|
||||
|
||||
// Extern C++ methods
|
||||
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
public static extern bool il2cpp_class_is_assignable_from(IntPtr klass, IntPtr oklass);
|
||||
@ -318,10 +320,13 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr il2cpp_object_get_class(IntPtr obj);
|
||||
|
||||
public override bool IsString(object obj)
|
||||
{
|
||||
return obj is string || obj is Il2CppSystem.String;
|
||||
}
|
||||
#endregion
|
||||
|
||||
// Strings
|
||||
|
||||
private const string IL2CPP_STRING_FULLNAME = "Il2CppSystem.String";
|
||||
|
||||
public override bool IsString(object obj) => obj is string || obj.GetActualType().FullName == IL2CPP_STRING_FULLNAME;
|
||||
|
||||
public override void BoxStringToType(ref object value, Type castTo)
|
||||
{
|
||||
|
@ -9,6 +9,9 @@ namespace UnityExplorer.Tests
|
||||
{
|
||||
public static class TestClass
|
||||
{
|
||||
public static List<int> AWritableList = new List<int> { 1, 2, 3, 4, 5 };
|
||||
public static Dictionary<string, int> AWritableDict = new Dictionary<string, int> { { "one", 1 }, { "two", 2 } };
|
||||
|
||||
public static IEnumerable ANestedList = new List<List<List<string>>>
|
||||
{
|
||||
new List<List<string>>
|
||||
@ -86,11 +89,6 @@ namespace UnityExplorer.Tests
|
||||
ExplorerCore.Log("Test2 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
//private static void TestGenericMultiInterface<T>() where T : IEnumerable, IList, ICollection
|
||||
//{
|
||||
// ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
//}
|
||||
|
||||
private static void TestComponent<T>() where T : Component
|
||||
{
|
||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
@ -121,22 +119,23 @@ namespace UnityExplorer.Tests
|
||||
}
|
||||
|
||||
#if CPP
|
||||
public static List<Il2CppSystem.Object> TestWritableBoxedList;
|
||||
|
||||
public static string testStringOne = "Test";
|
||||
public static Il2CppSystem.Object testStringTwo = "string boxed as cpp object";
|
||||
public static Il2CppSystem.String testStringThree = "string boxed as cpp string";
|
||||
public static string nullString = null;
|
||||
|
||||
public static List<Il2CppSystem.Object> boxedList;
|
||||
public static List<Il2CppSystem.Object> cppBoxedList;
|
||||
public static UnhollowerBaseLib.Il2CppStructArray<int> CppIntStructArray;
|
||||
public static UnhollowerBaseLib.Il2CppStringArray CppStringArray;
|
||||
public static UnhollowerBaseLib.Il2CppReferenceArray<Il2CppSystem.Object> CppReferenceArray;
|
||||
|
||||
public static Il2CppSystem.Object boxedInt;
|
||||
public static Il2CppSystem.Int32 cppint;
|
||||
public static Il2CppSystem.Object cppBoxedInt;
|
||||
public static Il2CppSystem.Int32 cppInt;
|
||||
|
||||
public static Il2CppSystem.Collections.Hashtable testHashset;
|
||||
public static Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> testList;
|
||||
public static Il2CppSystem.Collections.Hashtable cppHashset;
|
||||
|
||||
//public static Il2CppSystem.Nullable<Quaternion> NullableQuaternion;
|
||||
//public static Il2CppSystem.Nullable<int> NullableInt = new Il2CppSystem.Nullable<int>(5);
|
||||
//public static Il2CppSystem.Nullable<bool> NullableBool = new Il2CppSystem.Nullable<bool>(false);
|
||||
#endif
|
||||
|
||||
static TestClass()
|
||||
@ -145,24 +144,39 @@ namespace UnityExplorer.Tests
|
||||
BigList.Add(i.ToString());
|
||||
|
||||
#if CPP
|
||||
//NullableQuaternion = new Il2CppSystem.Nullable<Quaternion>();
|
||||
//NullableQuaternion.value = Quaternion.identity;
|
||||
CppIntStructArray = new UnhollowerBaseLib.Il2CppStructArray<int>(5);
|
||||
CppIntStructArray[0] = 0;
|
||||
CppIntStructArray[1] = 1;
|
||||
CppIntStructArray[2] = 2;
|
||||
CppIntStructArray[3] = 3;
|
||||
CppIntStructArray[4] = 4;
|
||||
|
||||
boxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
||||
boxedList = new List<Il2CppSystem.Object>();
|
||||
boxedList.Add((Il2CppSystem.String)"boxedString");
|
||||
boxedList.Add(new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject());
|
||||
cppint = new Il2CppSystem.Int32 { m_value = 420 };
|
||||
CppStringArray = new UnhollowerBaseLib.Il2CppStringArray(2);
|
||||
CppStringArray[0] = "hello, ";
|
||||
CppStringArray[1] = "world!";
|
||||
|
||||
testHashset = new Il2CppSystem.Collections.Hashtable();
|
||||
testHashset.Add("key1", "itemOne");
|
||||
testHashset.Add("key2", "itemTwo");
|
||||
testHashset.Add("key3", "itemThree");
|
||||
CppReferenceArray = new UnhollowerBaseLib.Il2CppReferenceArray<Il2CppSystem.Object>(3);
|
||||
CppReferenceArray[0] = new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject();
|
||||
CppReferenceArray[1] = null;
|
||||
CppReferenceArray[2] = (Il2CppSystem.String)"whats up";
|
||||
|
||||
cppBoxedInt = new Il2CppSystem.Int32() { m_value = 5 }.BoxIl2CppObject();
|
||||
cppBoxedList = new List<Il2CppSystem.Object>();
|
||||
cppBoxedList.Add((Il2CppSystem.String)"boxedString");
|
||||
cppBoxedList.Add(new Il2CppSystem.Int32 { m_value = 5 }.BoxIl2CppObject());
|
||||
cppInt = new Il2CppSystem.Int32 { m_value = 420 };
|
||||
|
||||
TestWritableBoxedList = new List<Il2CppSystem.Object>();
|
||||
TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 1 }.BoxIl2CppObject());
|
||||
TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 2 }.BoxIl2CppObject());
|
||||
TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 3 }.BoxIl2CppObject());
|
||||
TestWritableBoxedList.Add(new Il2CppSystem.Int32 { m_value = 4 }.BoxIl2CppObject());
|
||||
|
||||
cppHashset = new Il2CppSystem.Collections.Hashtable();
|
||||
cppHashset.Add("key1", "itemOne");
|
||||
cppHashset.Add("key2", "itemTwo");
|
||||
cppHashset.Add("key3", "itemThree");
|
||||
|
||||
testList = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(3);
|
||||
testList.Add("One");
|
||||
testList.Add("Two");
|
||||
testList.Add("Three");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
|
||||
public override bool ShouldAutoEvaluate => true;
|
||||
public override bool HasArguments => false;
|
||||
public override bool CanWrite => false; // TODO Parent.CanWrite;
|
||||
public override bool CanWrite => Owner.CanWrite;
|
||||
|
||||
public void SetDictOwner(InteractiveDictionary dict, int index)
|
||||
{
|
||||
@ -84,7 +84,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
|
||||
public override void TrySetUserValue(object value)
|
||||
{
|
||||
throw new NotImplementedException("TODO");
|
||||
(Owner as InteractiveDictionary).TrySetValueToKey(DictKey, value, DictIndex);
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
|
||||
public override void TrySetUserValue(object value)
|
||||
{
|
||||
throw new NotImplementedException("TODO");
|
||||
(Owner as InteractiveList).TrySetValueToIndex(value, this.ListIndex);
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,6 +100,7 @@ namespace UnityExplorer.UI.CacheObject
|
||||
ReflectionProvider.Instance.BoxStringToType(ref value, FallbackType);
|
||||
else
|
||||
value = value.TryCast(FallbackType);
|
||||
|
||||
TrySetUserValue(value);
|
||||
}
|
||||
|
||||
@ -283,62 +284,6 @@ namespace UnityExplorer.UI.CacheObject
|
||||
cell.SubContentButton.Button.gameObject.SetActive(args.subContentButtonActive);
|
||||
}
|
||||
|
||||
// IValues
|
||||
|
||||
internal static GameObject InactiveIValueHolder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!inactiveIValueHolder)
|
||||
{
|
||||
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||
inactiveIValueHolder.transform.parent = UIManager.PoolHolder.transform;
|
||||
inactiveIValueHolder.SetActive(false);
|
||||
}
|
||||
return inactiveIValueHolder;
|
||||
}
|
||||
}
|
||||
private static GameObject inactiveIValueHolder;
|
||||
|
||||
public virtual void OnCellSubContentToggle()
|
||||
{
|
||||
if (this.IValue == null)
|
||||
{
|
||||
var ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
||||
IValue = (InteractiveValue)Pool.Borrow(ivalueType);
|
||||
CurrentIValueType = ivalueType;
|
||||
|
||||
IValue.OnBorrowed(this);
|
||||
IValue.SetValue(this.Value);
|
||||
IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);
|
||||
CellView.SubContentHolder.SetActive(true);
|
||||
SubContentShowWanted = true;
|
||||
|
||||
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
|
||||
this.ProcessOnEvaluate();
|
||||
this.SetDataToCell(this.CellView);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubContentShowWanted = !SubContentShowWanted;
|
||||
CellView.SubContentHolder.SetActive(SubContentShowWanted);
|
||||
}
|
||||
|
||||
CellView.RefreshSubcontentButton();
|
||||
}
|
||||
|
||||
public virtual void ReleaseIValue()
|
||||
{
|
||||
if (IValue == null)
|
||||
return;
|
||||
|
||||
IValue.ReleaseFromOwner();
|
||||
Pool.Return(CurrentIValueType, IValue);
|
||||
|
||||
IValue = null;
|
||||
}
|
||||
|
||||
// CacheObjectCell Apply
|
||||
|
||||
public virtual void OnCellApplyClicked()
|
||||
@ -368,6 +313,76 @@ namespace UnityExplorer.UI.CacheObject
|
||||
SetDataToCell(this.CellView);
|
||||
}
|
||||
|
||||
// IValues
|
||||
|
||||
public virtual void OnCellSubContentToggle()
|
||||
{
|
||||
if (this.IValue == null)
|
||||
{
|
||||
var ivalueType = InteractiveValue.GetIValueTypeForState(State);
|
||||
IValue = (InteractiveValue)Pool.Borrow(ivalueType);
|
||||
CurrentIValueType = ivalueType;
|
||||
|
||||
IValue.OnBorrowed(this);
|
||||
IValue.SetValue(this.Value);
|
||||
IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);
|
||||
CellView.SubContentHolder.SetActive(true);
|
||||
SubContentShowWanted = true;
|
||||
|
||||
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
|
||||
this.ProcessOnEvaluate();
|
||||
this.SetDataToCell(this.CellView);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubContentShowWanted = !SubContentShowWanted;
|
||||
CellView.SubContentHolder.SetActive(SubContentShowWanted);
|
||||
}
|
||||
|
||||
CellView.RefreshSubcontentButton();
|
||||
}
|
||||
|
||||
public virtual void SetValueFromIValue(object value)
|
||||
{
|
||||
if (CellView == null)
|
||||
{
|
||||
ExplorerCore.LogWarning("Trying to set value from IValue but CellView is null!?");
|
||||
return;
|
||||
}
|
||||
|
||||
SetUserValue(value);
|
||||
SetDataToCell(CellView);
|
||||
}
|
||||
|
||||
public virtual void ReleaseIValue()
|
||||
{
|
||||
if (IValue == null)
|
||||
return;
|
||||
|
||||
IValue.ReleaseFromOwner();
|
||||
Pool.Return(CurrentIValueType, IValue);
|
||||
|
||||
IValue = null;
|
||||
}
|
||||
|
||||
internal static GameObject InactiveIValueHolder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!inactiveIValueHolder)
|
||||
{
|
||||
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||
inactiveIValueHolder.transform.parent = UIManager.PoolHolder.transform;
|
||||
inactiveIValueHolder.SetActive(false);
|
||||
}
|
||||
return inactiveIValueHolder;
|
||||
}
|
||||
}
|
||||
private static GameObject inactiveIValueHolder;
|
||||
|
||||
// Value state args helper
|
||||
|
||||
public struct ValueStateArgs
|
||||
{
|
||||
public ValueStateArgs(bool valueActive = true, bool valueRichText = true, Color? valueColor = null,
|
||||
|
@ -84,10 +84,5 @@ namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
// not used
|
||||
}
|
||||
|
||||
//protected override void ConstructUpdateToggle(GameObject parent)
|
||||
//{
|
||||
// // not used
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace UnityExplorer.UI.IValues
|
||||
object ICacheObjectController.Target => this.CurrentOwner.Value;
|
||||
public Type TargetType { get; private set; }
|
||||
|
||||
public override bool CanWrite => false;// TODO RefIDictionary != null && !RefIDictionary.IsReadOnly;
|
||||
public override bool CanWrite => base.CanWrite && RefIDictionary != null && !RefIDictionary.IsReadOnly;
|
||||
|
||||
public Type KeyType;
|
||||
public Type ValueType;
|
||||
@ -149,6 +149,24 @@ namespace UnityExplorer.UI.IValues
|
||||
}
|
||||
}
|
||||
|
||||
// Setting value to dictionary
|
||||
|
||||
public void TrySetValueToKey(object key, object value, int keyIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
RefIDictionary[key] = value;
|
||||
|
||||
var entry = cachedEntries[keyIndex];
|
||||
entry.SetValueFromSource(value);
|
||||
entry.SetDataToCell(entry.CellView);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception setting IDictionary key! {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// KVP entry scroll pool
|
||||
|
||||
public void OnCellBorrowed(CacheKeyValuePairCell cell)
|
||||
|
@ -19,7 +19,7 @@ namespace UnityExplorer.UI.IValues
|
||||
object ICacheObjectController.Target => this.CurrentOwner.Value;
|
||||
public Type TargetType { get; private set; }
|
||||
|
||||
public override bool CanWrite => RefIList != null && !RefIList.IsReadOnly;
|
||||
public override bool CanWrite => base.CanWrite && RefIList != null && !RefIList.IsReadOnly;
|
||||
|
||||
public Type EntryType;
|
||||
public IEnumerable RefIEnumerable;
|
||||
@ -60,6 +60,7 @@ namespace UnityExplorer.UI.IValues
|
||||
cachedEntries.Clear();
|
||||
}
|
||||
|
||||
// Setting the List value itself to this model
|
||||
public override void SetValue(object value)
|
||||
{
|
||||
if (value == null)
|
||||
@ -100,6 +101,8 @@ namespace UnityExplorer.UI.IValues
|
||||
int idx = 0;
|
||||
foreach (var entry in RefIEnumerable)
|
||||
{
|
||||
// var entry = item.TryCast();
|
||||
|
||||
values.Add(entry);
|
||||
|
||||
// If list count increased, create new cache entries
|
||||
@ -133,6 +136,24 @@ namespace UnityExplorer.UI.IValues
|
||||
}
|
||||
}
|
||||
|
||||
// Setting the value of an index to the list
|
||||
|
||||
public void TrySetValueToIndex(object value, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
RefIList[index] = value;
|
||||
|
||||
var entry = cachedEntries[index];
|
||||
entry.SetValueFromSource(value);
|
||||
entry.SetDataToCell(entry.CellView);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception setting IList value: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// List entry scroll pool
|
||||
|
||||
public override void SetLayout()
|
||||
|
@ -17,10 +17,10 @@ namespace UnityExplorer.UI.IValues
|
||||
|
||||
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
|
||||
|
||||
public CacheObjectBase CurrentOwner { get; }
|
||||
public CacheObjectBase CurrentOwner => m_owner;
|
||||
private CacheObjectBase m_owner;
|
||||
|
||||
public object EditedValue { get; private set; }
|
||||
//public object EditedValue { get; private set; }
|
||||
|
||||
public virtual void SetLayout() { }
|
||||
|
||||
@ -53,12 +53,6 @@ namespace UnityExplorer.UI.IValues
|
||||
}
|
||||
|
||||
this.m_owner = owner;
|
||||
// ...
|
||||
}
|
||||
|
||||
public virtual void SetValue(object value)
|
||||
{
|
||||
this.EditedValue = value;
|
||||
}
|
||||
|
||||
public virtual void ReleaseFromOwner()
|
||||
@ -69,6 +63,13 @@ namespace UnityExplorer.UI.IValues
|
||||
this.m_owner = null;
|
||||
}
|
||||
|
||||
public virtual void SetValue(object value) { }
|
||||
|
||||
//public virtual void SetValue(object value)
|
||||
//{
|
||||
// this.EditedValue = value;
|
||||
//}
|
||||
|
||||
public virtual GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent);
|
||||
|
Reference in New Issue
Block a user