mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-17 14:37:49 +08:00
Made ParseUtility helper to simplify and improve parsing of various input types
This commit is contained in:
parent
c828d9b642
commit
c04a864b74
@ -92,17 +92,23 @@ namespace UnityExplorer
|
|||||||
public static string ReflectionExToString(this Exception e, bool innerMost = true)
|
public static string ReflectionExToString(this Exception e, bool innerMost = true)
|
||||||
{
|
{
|
||||||
if (innerMost)
|
if (innerMost)
|
||||||
{
|
e.GetInnerMostException();
|
||||||
while (e.InnerException != null)
|
|
||||||
{
|
|
||||||
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
|
||||||
break;
|
|
||||||
|
|
||||||
e = e.InnerException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{e.GetType()}: {e.Message}";
|
return $"{e.GetType()}: {e.Message}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Exception GetInnerMostException(this Exception e)
|
||||||
|
{
|
||||||
|
while (e.InnerException != null)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
e = e.InnerException;
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
var name = toType.AssemblyQualifiedName;
|
var name = toType.AssemblyQualifiedName;
|
||||||
|
|
||||||
if (!unboxMethods.ContainsKey(toType.AssemblyQualifiedName))
|
if (!unboxMethods.ContainsKey(name))
|
||||||
{
|
{
|
||||||
unboxMethods.Add(name, typeof(Il2CppObjectBase)
|
unboxMethods.Add(name, typeof(Il2CppObjectBase)
|
||||||
.GetMethod("Unbox")
|
.GetMethod("Unbox")
|
||||||
|
@ -182,7 +182,6 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Type and Generic Parameter implementation cache
|
#region Type and Generic Parameter implementation cache
|
||||||
|
|
||||||
// cache for GetImplementationsOf
|
// cache for GetImplementationsOf
|
||||||
@ -302,7 +301,6 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Internal MemberInfo Cache
|
#region Internal MemberInfo Cache
|
||||||
|
|
||||||
internal static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfos = new Dictionary<Type, Dictionary<string, FieldInfo>>();
|
internal static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfos = new Dictionary<Type, Dictionary<string, FieldInfo>>();
|
||||||
|
@ -8,14 +8,12 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
public static class MiscUtility
|
public static class MiscUtility
|
||||||
{
|
{
|
||||||
private static CultureInfo _enCulture = new CultureInfo("en-US");
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a string contains another string, case-insensitive.
|
/// Check if a string contains another string, case-insensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool ContainsIgnoreCase(this string _this, string s)
|
public static bool ContainsIgnoreCase(this string _this, string s)
|
||||||
{
|
{
|
||||||
return _enCulture.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0;
|
return ParseUtility.en_US.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
390
src/Core/Utility/ParseUtility.cs
Normal file
390
src/Core/Utility/ParseUtility.cs
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer
|
||||||
|
{
|
||||||
|
public static class ParseUtility
|
||||||
|
{
|
||||||
|
public static CultureInfo en_US = new CultureInfo("en-US");
|
||||||
|
|
||||||
|
private static readonly HashSet<Type> nonPrimitiveTypes = new HashSet<Type>
|
||||||
|
{
|
||||||
|
typeof(string),
|
||||||
|
typeof(decimal),
|
||||||
|
typeof(DateTime),
|
||||||
|
};
|
||||||
|
|
||||||
|
public static bool CanParse(Type type)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(type.FullName))
|
||||||
|
return false;
|
||||||
|
return type.IsPrimitive || nonPrimitiveTypes.Contains(type) || customTypes.ContainsKey(type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(string input, Type type, out object obj, out Exception parseException)
|
||||||
|
{
|
||||||
|
obj = null;
|
||||||
|
parseException = null;
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (type == typeof(string))
|
||||||
|
{
|
||||||
|
obj = input;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (customTypes.ContainsKey(type.FullName))
|
||||||
|
{
|
||||||
|
obj = customTypes[type.FullName].Invoke(input);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
|
||||||
|
.Invoke(null, new object[] { input });
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ex = ex.GetInnerMostException();
|
||||||
|
parseException = ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToStringForInput(object obj, Type type)
|
||||||
|
{
|
||||||
|
if (type == null || obj == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (type == typeof(string))
|
||||||
|
return obj as string;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (customTypes.ContainsKey(type.FullName))
|
||||||
|
{
|
||||||
|
return customTypesToString[type.FullName].Invoke(obj);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (obj is IntPtr ptr)
|
||||||
|
return ptr.ToString();
|
||||||
|
else if (obj is UIntPtr uPtr)
|
||||||
|
return uPtr.ToString();
|
||||||
|
else
|
||||||
|
return ReflectionUtility.GetMethodInfo(type, "ToString", new Type[] { typeof(IFormatProvider) })
|
||||||
|
.Invoke(obj, new object[] { en_US })
|
||||||
|
as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception formatting object for input: {ex}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, string> typeInputExamples = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public static string GetExampleInput(Type type)
|
||||||
|
{
|
||||||
|
if (!typeInputExamples.ContainsKey(type.AssemblyQualifiedName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var instance = Activator.CreateInstance(type);
|
||||||
|
typeInputExamples.Add(type.AssemblyQualifiedName, ToStringForInput(instance, type));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Exception generating default instance for example input for '" + type.FullName + "'");
|
||||||
|
ExplorerCore.Log(ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeInputExamples[type.AssemblyQualifiedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Custom parse methods
|
||||||
|
|
||||||
|
internal delegate object ParseMethod(string input);
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, ParseMethod> customTypes = new Dictionary<string, ParseMethod>
|
||||||
|
{
|
||||||
|
{ typeof(Vector2).FullName, TryParseVector2 },
|
||||||
|
{ typeof(Vector3).FullName, TryParseVector3 },
|
||||||
|
{ typeof(Vector4).FullName, TryParseVector4 },
|
||||||
|
{ typeof(Quaternion).FullName, TryParseQuaternion },
|
||||||
|
{ typeof(Rect).FullName, TryParseRect },
|
||||||
|
{ typeof(Color).FullName, TryParseColor },
|
||||||
|
{ typeof(Color32).FullName, TryParseColor32 },
|
||||||
|
{ typeof(LayerMask).FullName, TryParseLayerMask },
|
||||||
|
};
|
||||||
|
|
||||||
|
internal delegate string ToStringMethod(object obj);
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, ToStringMethod> customTypesToString = new Dictionary<string, ToStringMethod>
|
||||||
|
{
|
||||||
|
{ typeof(Vector2).FullName, Vector2ToString },
|
||||||
|
{ typeof(Vector3).FullName, Vector3ToString },
|
||||||
|
{ typeof(Vector4).FullName, Vector4ToString },
|
||||||
|
{ typeof(Quaternion).FullName, QuaternionToString },
|
||||||
|
{ typeof(Rect).FullName, RectToString },
|
||||||
|
{ typeof(Color).FullName, ColorToString },
|
||||||
|
{ typeof(Color32).FullName, Color32ToString },
|
||||||
|
{ typeof(LayerMask).FullName, LayerMaskToString },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Vector2
|
||||||
|
|
||||||
|
public static object TryParseVector2(string input)
|
||||||
|
{
|
||||||
|
Vector2 vector = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
vector.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
vector.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Vector2ToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Vector2 vector))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}", new object[]
|
||||||
|
{
|
||||||
|
vector.x,
|
||||||
|
vector.y
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector3
|
||||||
|
|
||||||
|
public static object TryParseVector3(string input)
|
||||||
|
{
|
||||||
|
Vector3 vector = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
vector.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
vector.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
vector.z = float.Parse(split[2].Trim(), en_US);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Vector3ToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Vector3 vector))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}", new object[]
|
||||||
|
{
|
||||||
|
vector.x,
|
||||||
|
vector.y,
|
||||||
|
vector.z
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector4
|
||||||
|
|
||||||
|
public static object TryParseVector4(string input)
|
||||||
|
{
|
||||||
|
Vector4 vector = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
vector.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
vector.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
vector.z = float.Parse(split[2].Trim(), en_US);
|
||||||
|
vector.w = float.Parse(split[3].Trim(), en_US);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Vector4ToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Vector4 vector))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}, {3}", new object[]
|
||||||
|
{
|
||||||
|
vector.x,
|
||||||
|
vector.y,
|
||||||
|
vector.z,
|
||||||
|
vector.w
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quaternion
|
||||||
|
|
||||||
|
public static object TryParseQuaternion(string input)
|
||||||
|
{
|
||||||
|
Vector3 vector = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
if (split.Length == 4)
|
||||||
|
{
|
||||||
|
Quaternion quat = default;
|
||||||
|
quat.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
quat.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
quat.z = float.Parse(split[2].Trim(), en_US);
|
||||||
|
quat.w = float.Parse(split[3].Trim(), en_US);
|
||||||
|
return quat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
vector.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
vector.z = float.Parse(split[2].Trim(), en_US);
|
||||||
|
return Quaternion.Euler(vector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string QuaternionToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Quaternion quaternion))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Vector3 vector = Quaternion.ToEulerAngles(quaternion);
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}", new object[]
|
||||||
|
{
|
||||||
|
vector.x,
|
||||||
|
vector.y,
|
||||||
|
vector.z,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rect
|
||||||
|
|
||||||
|
public static object TryParseRect(string input)
|
||||||
|
{
|
||||||
|
Rect rect = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
rect.x = float.Parse(split[0].Trim(), en_US);
|
||||||
|
rect.y = float.Parse(split[1].Trim(), en_US);
|
||||||
|
rect.width = float.Parse(split[2].Trim(), en_US);
|
||||||
|
rect.height = float.Parse(split[3].Trim(), en_US);
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string RectToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Rect rect))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}, {3}", new object[]
|
||||||
|
{
|
||||||
|
rect.x,
|
||||||
|
rect.y,
|
||||||
|
rect.width,
|
||||||
|
rect.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color
|
||||||
|
|
||||||
|
public static object TryParseColor(string input)
|
||||||
|
{
|
||||||
|
Color color = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
color.r = float.Parse(split[0].Trim(), en_US);
|
||||||
|
color.g = float.Parse(split[1].Trim(), en_US);
|
||||||
|
color.b = float.Parse(split[2].Trim(), en_US);
|
||||||
|
if (split.Length > 3)
|
||||||
|
color.a = float.Parse(split[3].Trim(), en_US);
|
||||||
|
else
|
||||||
|
color.a = 1;
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ColorToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Color color))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}, {3}", new object[]
|
||||||
|
{
|
||||||
|
color.r,
|
||||||
|
color.g,
|
||||||
|
color.b,
|
||||||
|
color.a
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color32
|
||||||
|
|
||||||
|
public static object TryParseColor32(string input)
|
||||||
|
{
|
||||||
|
Color32 color = default;
|
||||||
|
|
||||||
|
var split = input.Split(',');
|
||||||
|
|
||||||
|
color.r = byte.Parse(split[0].Trim(), en_US);
|
||||||
|
color.g = byte.Parse(split[1].Trim(), en_US);
|
||||||
|
color.b = byte.Parse(split[2].Trim(), en_US);
|
||||||
|
if (split.Length > 3)
|
||||||
|
color.a = byte.Parse(split[3].Trim(), en_US);
|
||||||
|
else
|
||||||
|
color.a = 255;
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Color32ToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Color32 color))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return string.Format(en_US, "{0}, {1}, {2}, {3}", new object[]
|
||||||
|
{
|
||||||
|
color.r,
|
||||||
|
color.g,
|
||||||
|
color.b,
|
||||||
|
color.a
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layermask (Int32)
|
||||||
|
|
||||||
|
public static object TryParseLayerMask(string input)
|
||||||
|
{
|
||||||
|
return (LayerMask)int.Parse(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string LayerMaskToString(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is LayerMask mask))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return mask.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -171,7 +171,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
|
|
||||||
#region Cache Member Util
|
#region Cache Member Util
|
||||||
|
|
||||||
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
public static bool CanParseArgs(ParameterInfo[] parameters)
|
||||||
{
|
{
|
||||||
foreach (var param in parameters)
|
foreach (var param in parameters)
|
||||||
{
|
{
|
||||||
@ -180,7 +180,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
if (pType.IsByRef && pType.HasElementType)
|
if (pType.IsByRef && pType.HasElementType)
|
||||||
pType = pType.GetElementType();
|
pType = pType.GetElementType();
|
||||||
|
|
||||||
if (pType != null && (pType.IsPrimitive || pType == typeof(string)))
|
if (pType != null && ParseUtility.CanParse(pType))
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -260,7 +260,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var args = mi.GetParameters();
|
var args = mi.GetParameters();
|
||||||
if (!CanProcessArgs(args))
|
if (!CanParseArgs(args))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sig += AppendArgsToSig(args);
|
sig += AppendArgsToSig(args);
|
||||||
@ -277,7 +277,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
var pi = member as PropertyInfo;
|
var pi = member as PropertyInfo;
|
||||||
|
|
||||||
var args = pi.GetIndexParameters();
|
var args = pi.GetIndexParameters();
|
||||||
if (!CanProcessArgs(args))
|
if (!CanParseArgs(args))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pi.CanRead && pi.CanWrite)
|
if (!pi.CanRead && pi.CanWrite)
|
||||||
|
@ -39,6 +39,9 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
public Type FallbackType { get; protected set; }
|
public Type FallbackType { get; protected set; }
|
||||||
public bool LastValueWasNull { get; private set; }
|
public bool LastValueWasNull { get; private set; }
|
||||||
|
|
||||||
|
public ValueState State = ValueState.NotEvaluated;
|
||||||
|
public Type LastValueType;
|
||||||
|
|
||||||
public InteractiveValue IValue { get; private set; }
|
public InteractiveValue IValue { get; private set; }
|
||||||
public Type CurrentIValueType { get; private set; }
|
public Type CurrentIValueType { get; private set; }
|
||||||
public bool SubContentShowWanted { get; private set; }
|
public bool SubContentShowWanted { get; private set; }
|
||||||
@ -58,12 +61,6 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
this.ValueLabelText = GetValueLabel();
|
this.ValueLabelText = GetValueLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// internals
|
|
||||||
|
|
||||||
// private static readonly Dictionary<string, MethodInfo> numberParseMethods = new Dictionary<string, MethodInfo>();
|
|
||||||
|
|
||||||
public ValueState State = ValueState.NotEvaluated;
|
|
||||||
|
|
||||||
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
||||||
|
|
||||||
public virtual void ReleasePooledObjects()
|
public virtual void ReleasePooledObjects()
|
||||||
@ -127,6 +124,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
if (HadException)
|
if (HadException)
|
||||||
{
|
{
|
||||||
LastValueWasNull = true;
|
LastValueWasNull = true;
|
||||||
|
LastValueType = FallbackType;
|
||||||
State = ValueState.Exception;
|
State = ValueState.Exception;
|
||||||
}
|
}
|
||||||
else if (Value.IsNullOrDestroyed())
|
else if (Value.IsNullOrDestroyed())
|
||||||
@ -158,6 +156,10 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
|
|
||||||
public ValueState GetStateForType(Type type)
|
public ValueState GetStateForType(Type type)
|
||||||
{
|
{
|
||||||
|
if (LastValueType == type)
|
||||||
|
return State;
|
||||||
|
|
||||||
|
LastValueType = type;
|
||||||
if (type == typeof(bool))
|
if (type == typeof(bool))
|
||||||
return ValueState.Boolean;
|
return ValueState.Boolean;
|
||||||
else if (type.IsPrimitive || type == typeof(decimal))
|
else if (type.IsPrimitive || type == typeof(decimal))
|
||||||
@ -184,17 +186,24 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
|
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
// bool and number dont want the label for the value at all
|
|
||||||
case ValueState.Boolean:
|
|
||||||
case ValueState.Number:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
case ValueState.NotEvaluated:
|
case ValueState.NotEvaluated:
|
||||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
|
||||||
|
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
return $"<i><color=red>{LastException.ReflectionExToString()}</color></i>";
|
||||||
|
|
||||||
|
// bool and number dont want the label for the value at all
|
||||||
|
case ValueState.Boolean:
|
||||||
|
case ValueState.Number:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// and valuestruct also doesnt want it if we can parse it
|
||||||
|
case ValueState.ValueStruct:
|
||||||
|
if (ParseUtility.CanParse(LastValueType))
|
||||||
|
return null;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// string wants it trimmed to max 200 chars
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (!LastValueWasNull)
|
if (!LastValueWasNull)
|
||||||
{
|
{
|
||||||
@ -205,6 +214,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// try to prefix the count of the collection for lists and dicts
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
if (!LastValueWasNull)
|
if (!LastValueWasNull)
|
||||||
{
|
{
|
||||||
@ -256,7 +266,6 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
//case ValueState.NullValue:
|
|
||||||
SetValueState(cell, ValueStateArgs.Default);
|
SetValueState(cell, ValueStateArgs.Default);
|
||||||
break;
|
break;
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
@ -274,10 +283,15 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
case ValueState.Enum:
|
case ValueState.Enum:
|
||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
|
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
|
case ValueState.Color:
|
||||||
|
case ValueState.ValueStruct:
|
||||||
|
if (ParseUtility.CanParse(LastValueType))
|
||||||
|
SetValueState(cell, new ValueStateArgs(false, false, null, true, false, true, CanWrite, true, true));
|
||||||
|
else
|
||||||
|
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
||||||
|
break;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
case ValueState.ValueStruct:
|
|
||||||
case ValueState.Color:
|
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
SetValueState(cell, new ValueStateArgs(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
||||||
break;
|
break;
|
||||||
case ValueState.Unsupported:
|
case ValueState.Unsupported:
|
||||||
@ -303,7 +317,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
// Type label (for primitives)
|
// Type label (for primitives)
|
||||||
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
|
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
|
||||||
if (args.typeLabelActive)
|
if (args.typeLabelActive)
|
||||||
cell.TypeLabel.text = SignatureHighlighter.Parse(Value.GetActualType(), false);
|
cell.TypeLabel.text = SignatureHighlighter.Parse(LastValueType, false);
|
||||||
|
|
||||||
// toggle for bools
|
// toggle for bools
|
||||||
cell.Toggle.gameObject.SetActive(args.toggleActive);
|
cell.Toggle.gameObject.SetActive(args.toggleActive);
|
||||||
@ -318,7 +332,7 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
cell.InputField.UIRoot.SetActive(args.inputActive);
|
cell.InputField.UIRoot.SetActive(args.inputActive);
|
||||||
if (args.inputActive)
|
if (args.inputActive)
|
||||||
{
|
{
|
||||||
cell.InputField.Text = Value.ToString();
|
cell.InputField.Text = ParseUtility.ToStringForInput(Value, LastValueType);
|
||||||
cell.InputField.InputField.readOnly = !CanWrite;
|
cell.InputField.InputField.readOnly = !CanWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,21 +356,15 @@ namespace UnityExplorer.UI.CacheObject
|
|||||||
SetUserValue(this.CellView.Toggle.isOn);
|
SetUserValue(this.CellView.Toggle.isOn);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
if (ParseUtility.TryParse(CellView.InputField.Text, LastValueType, out object value, out Exception ex))
|
||||||
{
|
{
|
||||||
var type = Value.GetType();
|
SetUserValue(value);
|
||||||
|
|
||||||
var val = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs)
|
|
||||||
.Invoke(null, new object[] { CellView.InputField.Text });
|
|
||||||
|
|
||||||
SetUserValue(val);
|
|
||||||
}
|
}
|
||||||
catch (ArgumentException) { } // ignore bad user input
|
else
|
||||||
catch (FormatException) { }
|
|
||||||
catch (OverflowException) { }
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("CacheObjectBase OnCellApplyClicked (number): " + ex.ToString());
|
ExplorerCore.LogWarning("Unable to parse input!");
|
||||||
|
if (ex != null)
|
||||||
|
ExplorerCore.Log(ex.ReflectionExToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,16 +155,18 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
InputField = UIFactory.CreateInputField(rightHoriGroup, "InputField", "...");
|
InputField = UIFactory.CreateInputField(rightHoriGroup, "InputField", "...");
|
||||||
UIFactory.SetLayoutElement(InputField.UIRoot, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(InputField.UIRoot, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
// Inspect and apply buttons
|
// Apply
|
||||||
|
|
||||||
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
|
ApplyButton = UIFactory.CreateButton(rightHoriGroup, "ApplyButton", "Apply", new Color(0.15f, 0.19f, 0.15f));
|
||||||
UIFactory.SetLayoutElement(InspectButton.Button.gameObject, minWidth: 60, flexibleWidth: 0, minHeight: 25);
|
|
||||||
InspectButton.OnClick += InspectClicked;
|
|
||||||
|
|
||||||
ApplyButton = UIFactory.CreateButton(rightHoriGroup, "ApplyButton", "Apply", new Color(0.15f, 0.15f, 0.15f));
|
|
||||||
UIFactory.SetLayoutElement(ApplyButton.Button.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(ApplyButton.Button.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
ApplyButton.OnClick += ApplyClicked;
|
ApplyButton.OnClick += ApplyClicked;
|
||||||
|
|
||||||
|
// Inspect
|
||||||
|
|
||||||
|
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
UIFactory.SetLayoutElement(InspectButton.Button.gameObject, minWidth: 70, flexibleWidth: 0, minHeight: 25);
|
||||||
|
InspectButton.OnClick += InspectClicked;
|
||||||
|
|
||||||
// Main value label
|
// Main value label
|
||||||
|
|
||||||
ValueLabel = UIFactory.CreateLabel(rightHoriGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
|
ValueLabel = UIFactory.CreateLabel(rightHoriGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
|
||||||
|
@ -33,7 +33,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
private readonly List<Text> genericArgLabels = new List<Text>();
|
private readonly List<Text> genericArgLabels = new List<Text>();
|
||||||
private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>();
|
private readonly List<TypeCompleter> genericAutocompleters = new List<TypeCompleter>();
|
||||||
|
|
||||||
private readonly List<InputFieldRef> inputFieldCache = new List<InputFieldRef>();
|
private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>();
|
||||||
|
|
||||||
public void OnBorrowedFromPool(CacheMember owner)
|
public void OnBorrowedFromPool(CacheMember owner)
|
||||||
{
|
{
|
||||||
@ -52,7 +52,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
|
|
||||||
public void OnReturnToPool()
|
public void OnReturnToPool()
|
||||||
{
|
{
|
||||||
foreach (var input in inputFieldCache)
|
foreach (var input in inputFields)
|
||||||
input.Text = "";
|
input.Text = "";
|
||||||
|
|
||||||
this.Owner = null;
|
this.Owner = null;
|
||||||
@ -99,15 +99,11 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
if (!ParseUtility.TryParse(input, type, out outArgs[i], out Exception ex))
|
||||||
{
|
{
|
||||||
var parse = ReflectionUtility.GetMethodInfo(type, "Parse", ArgumentUtility.ParseArgs);
|
|
||||||
outArgs[i] = parse.Invoke(null, new object[] { input });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name}), {ex.GetType().Name}: {ex.Message}");
|
|
||||||
outArgs[i] = null;
|
outArgs[i] = null;
|
||||||
|
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name})" +
|
||||||
|
$"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +195,15 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
|
|
||||||
argRows[i].SetActive(true);
|
argRows[i].SetActive(true);
|
||||||
argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
|
argLabels[i].text = $"{SignatureHighlighter.Parse(arg.ParameterType, false)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
|
||||||
|
if (arg.ParameterType == typeof(string))
|
||||||
|
inputFields[i].PlaceholderText.text = "";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var elemType = arg.ParameterType;
|
||||||
|
if (elemType.IsByRef)
|
||||||
|
elemType = elemType.GetElementType();
|
||||||
|
inputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(elemType)}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +233,7 @@ namespace UnityExplorer.UI.CacheObject.Views
|
|||||||
inputField.InputField.lineType = InputField.LineType.MultiLineNewline;
|
inputField.InputField.lineType = InputField.LineType.MultiLineNewline;
|
||||||
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
inputField.OnValueChanged += (string val) => { inputArray[index] = val; };
|
inputField.OnValueChanged += (string val) => { inputArray[index] = val; };
|
||||||
inputFieldCache.Add(inputField);
|
inputFields.Add(inputField);
|
||||||
|
|
||||||
if (autocomplete)
|
if (autocomplete)
|
||||||
genericAutocompleters.Add(new TypeCompleter(null, inputField));
|
genericAutocompleters.Add(new TypeCompleter(null, inputField));
|
||||||
|
@ -26,33 +26,31 @@ namespace UnityExplorer.UI.IValues
|
|||||||
Fields = fields;
|
Fields = fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(object instance, string value, int fieldIndex)
|
public void SetValue(object instance, string input, int fieldIndex)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var field = Fields[fieldIndex];
|
var field = Fields[fieldIndex];
|
||||||
|
|
||||||
object val;
|
object val;
|
||||||
if (field.FieldType == typeof(string))
|
if (field.FieldType == typeof(string))
|
||||||
val = value;
|
val = input;
|
||||||
else
|
else
|
||||||
val = ReflectionUtility.GetMethodInfo(field.FieldType, "Parse", ArgumentUtility.ParseArgs)
|
{
|
||||||
.Invoke(null, new object[] { value });
|
if (!ParseUtility.TryParse(input, field.FieldType, out val, out Exception ex))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Unable to parse input!");
|
||||||
|
if (ex != null) ExplorerCore.Log(ex.ReflectionExToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
field.SetValue(instance, val);
|
field.SetValue(instance, val);
|
||||||
}
|
}
|
||||||
catch (FormatException) { ExplorerCore.LogWarning($"Invalid argument '{value}'!"); }
|
|
||||||
catch (ArgumentException) { ExplorerCore.LogWarning($"Invalid argument '{value}'!"); }
|
|
||||||
catch (OverflowException) { ExplorerCore.LogWarning($"Invalid argument '{value}'!"); }
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Excepting setting value '" + value + "'! " + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetValue(object instance, int fieldIndex)
|
public string GetValue(object instance, int fieldIndex)
|
||||||
{
|
{
|
||||||
return Fields[fieldIndex].GetValue(instance)?.ToString() ?? "";
|
var field = Fields[fieldIndex];
|
||||||
|
var value = field.GetValue(instance);
|
||||||
|
return ParseUtility.ToStringForInput(value, field.FieldType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +67,12 @@ namespace UnityExplorer.UI.IValues
|
|||||||
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out var info))
|
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out var info))
|
||||||
return info.IsSupported;
|
return info.IsSupported;
|
||||||
|
|
||||||
var supported = true;
|
var supported = false;
|
||||||
|
|
||||||
var fields = type.GetFields(INSTANCE_FLAGS);
|
var fields = type.GetFields(INSTANCE_FLAGS);
|
||||||
|
if (fields.Length > 0)
|
||||||
if (fields.Any(it => !it.FieldType.IsPrimitive && it.FieldType != typeof(string)))
|
{
|
||||||
|
if (fields.Any(it => !ParseUtility.CanParse(it.FieldType)))
|
||||||
{
|
{
|
||||||
supported = false;
|
supported = false;
|
||||||
info = new StructInfo(supported, null);
|
info = new StructInfo(supported, null);
|
||||||
@ -83,6 +82,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
supported = true;
|
supported = true;
|
||||||
info = new StructInfo(supported, fields);
|
info = new StructInfo(supported, fields);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typeSupportCache.Add(type.AssemblyQualifiedName, info);
|
typeSupportCache.Add(type.AssemblyQualifiedName, info);
|
||||||
|
|
||||||
@ -182,12 +182,12 @@ namespace UnityExplorer.UI.IValues
|
|||||||
fieldRows.Add(row);
|
fieldRows.Add(row);
|
||||||
|
|
||||||
var label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleRight);
|
var label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleRight);
|
||||||
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
||||||
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
labels.Add(label);
|
labels.Add(label);
|
||||||
|
|
||||||
var input = UIFactory.CreateInputField(row, "InputField", "...");
|
var input = UIFactory.CreateInputField(row, "InputField", "...");
|
||||||
UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 100);
|
UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 200);
|
||||||
var fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
|
var fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
|
||||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
@ -204,7 +204,7 @@ namespace UnityExplorer.UI.IValues
|
|||||||
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
applyButton = UIFactory.CreateButton(UIRoot, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
|
applyButton = UIFactory.CreateButton(UIRoot, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(applyButton.Button.gameObject, minHeight: 25, minWidth: 100);
|
UIFactory.SetLayoutElement(applyButton.Button.gameObject, minHeight: 25, minWidth: 175);
|
||||||
applyButton.OnClick += OnApplyClicked;
|
applyButton.OnClick += OnApplyClicked;
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
|
@ -295,14 +295,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
// Window Anchors helpers
|
// Window Anchors helpers
|
||||||
|
|
||||||
internal static CultureInfo _enCulture = new CultureInfo("en-US");
|
|
||||||
|
|
||||||
internal static string RectAnchorsToString(this RectTransform rect)
|
internal static string RectAnchorsToString(this RectTransform rect)
|
||||||
{
|
{
|
||||||
if (!rect)
|
if (!rect)
|
||||||
throw new ArgumentNullException("rect");
|
throw new ArgumentNullException("rect");
|
||||||
|
|
||||||
return string.Format(_enCulture, "{0},{1},{2},{3}", new object[]
|
return string.Format(ParseUtility.en_US, "{0},{1},{2},{3}", new object[]
|
||||||
{
|
{
|
||||||
rect.anchorMin.x,
|
rect.anchorMin.x,
|
||||||
rect.anchorMin.y,
|
rect.anchorMin.y,
|
||||||
@ -322,10 +320,10 @@ namespace UnityExplorer.UI.Panels
|
|||||||
throw new Exception($"stringAnchors split is unexpected length: {split.Length}");
|
throw new Exception($"stringAnchors split is unexpected length: {split.Length}");
|
||||||
|
|
||||||
Vector4 anchors;
|
Vector4 anchors;
|
||||||
anchors.x = float.Parse(split[0], _enCulture);
|
anchors.x = float.Parse(split[0], ParseUtility.en_US);
|
||||||
anchors.y = float.Parse(split[1], _enCulture);
|
anchors.y = float.Parse(split[1], ParseUtility.en_US);
|
||||||
anchors.z = float.Parse(split[2], _enCulture);
|
anchors.z = float.Parse(split[2], ParseUtility.en_US);
|
||||||
anchors.w = float.Parse(split[3], _enCulture);
|
anchors.w = float.Parse(split[3], ParseUtility.en_US);
|
||||||
|
|
||||||
panel.anchorMin = new Vector2(anchors.x, anchors.y);
|
panel.anchorMin = new Vector2(anchors.x, anchors.y);
|
||||||
panel.anchorMax = new Vector2(anchors.z, anchors.w);
|
panel.anchorMax = new Vector2(anchors.z, anchors.w);
|
||||||
@ -336,7 +334,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
if (!rect)
|
if (!rect)
|
||||||
throw new ArgumentNullException("rect");
|
throw new ArgumentNullException("rect");
|
||||||
|
|
||||||
return string.Format(_enCulture, "{0},{1}", new object[]
|
return string.Format(ParseUtility.en_US, "{0},{1}", new object[]
|
||||||
{
|
{
|
||||||
rect.localPosition.x, rect.localPosition.y
|
rect.localPosition.x, rect.localPosition.y
|
||||||
});
|
});
|
||||||
@ -350,8 +348,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
|
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
|
||||||
|
|
||||||
Vector3 vector = rect.localPosition;
|
Vector3 vector = rect.localPosition;
|
||||||
vector.x = float.Parse(split[0], _enCulture);
|
vector.x = float.Parse(split[0], ParseUtility.en_US);
|
||||||
vector.y = float.Parse(split[1], _enCulture);
|
vector.y = float.Parse(split[1], ParseUtility.en_US);
|
||||||
rect.localPosition = vector;
|
rect.localPosition = vector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,7 @@
|
|||||||
<Compile Include="Core\Reflection\Il2CppReflection.cs" />
|
<Compile Include="Core\Reflection\Il2CppReflection.cs" />
|
||||||
<Compile Include="Core\Utility\ArgumentUtility.cs" />
|
<Compile Include="Core\Utility\ArgumentUtility.cs" />
|
||||||
<Compile Include="Core\Utility\MiscUtility.cs" />
|
<Compile Include="Core\Utility\MiscUtility.cs" />
|
||||||
|
<Compile Include="Core\Utility\ParseUtility.cs" />
|
||||||
<Compile Include="UI\Inspectors\TODO_InspectUnderMouse.cs" />
|
<Compile Include="UI\Inspectors\TODO_InspectUnderMouse.cs" />
|
||||||
<Compile Include="UI\CSConsole\CSConsoleManager.cs" />
|
<Compile Include="UI\CSConsole\CSConsoleManager.cs" />
|
||||||
<Compile Include="UI\CacheObject\CacheField.cs" />
|
<Compile Include="UI\CacheObject\CacheField.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user