Initial Commit

This commit is contained in:
2026-03-16 14:38:46 +02:00
commit b8f7327a21
2327 changed files with 253610 additions and 0 deletions
@@ -0,0 +1,433 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Zenject;
namespace ModestTree
{
public static class Assert
{
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void That(bool condition)
{
if (!condition)
{
throw CreateException("Assert hit!");
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotEmpty(string str)
{
if (String.IsNullOrEmpty(str))
{
throw CreateException("Unexpected null or empty string");
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
// This is better because IsEmpty with IEnumerable causes a memory alloc
public static void IsEmpty<T>(IList<T> list)
{
if (list.Count != 0)
{
throw CreateException(
"Expected collection to be empty but instead found '{0}' elements", list.Count);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsEmpty<T>(IEnumerable<T> sequence)
{
if (!sequence.IsEmpty())
{
throw CreateException("Expected collection to be empty but instead found '{0}' elements",
sequence.Count());
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsType<T>(object obj)
{
IsType<T>(obj, "");
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsType<T>(object obj, string message)
{
if (!(obj is T))
{
throw CreateException("Assert Hit! {0}\nWrong type found. Expected '{1}' (left) but found '{2}' (right). ", message, typeof(T).PrettyName(), obj.GetType().PrettyName());
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void DerivesFrom<T>(Type type)
{
if (!type.DerivesFrom<T>())
{
throw CreateException("Expected type '{0}' to derive from '{1}'", type.Name, typeof(T).Name);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void DerivesFromOrEqual<T>(Type type)
{
if (!type.DerivesFromOrEqual<T>())
{
throw CreateException("Expected type '{0}' to derive from or be equal to '{1}'", type.Name, typeof(T).Name);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void DerivesFrom(Type childType, Type parentType)
{
if (!childType.DerivesFrom(parentType))
{
throw CreateException("Expected type '{0}' to derive from '{1}'", childType.Name, parentType.Name);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void DerivesFromOrEqual(Type childType, Type parentType)
{
if (!childType.DerivesFromOrEqual(parentType))
{
throw CreateException("Expected type '{0}' to derive from or be equal to '{1}'", childType.Name, parentType.Name);
}
}
// Use AssertEquals to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsEqual(object left, object right)
{
IsEqual(left, right, "");
}
// Use AssertEquals to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsEqual(object left, object right, Func<string> messageGenerator)
{
if (!object.Equals(left, right))
{
left = left ?? "<NULL>";
right = right ?? "<NULL>";
throw CreateException("Assert Hit! {0}. Expected '{1}' (left) but found '{2}' (right). ", messageGenerator(), left, right);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsApproximately(float left, float right, float epsilon = 0.00001f)
{
bool isEqual = Math.Abs(left - right) < epsilon;
if (!isEqual)
{
throw CreateException("Assert Hit! Expected '{0}' (left) but found '{1}' (right). ", left, right);
}
}
// Use AssertEquals to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsEqual(object left, object right, string message)
{
if (!object.Equals(left, right))
{
left = left ?? "<NULL>";
right = right ?? "<NULL>";
throw CreateException("Assert Hit! {0}\nExpected '{1}' (left) but found '{2}' (right). ", message, left, right);
}
}
// Use Assert.IsNotEqual to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotEqual(object left, object right)
{
IsNotEqual(left, right, "");
}
// Use Assert.IsNotEqual to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotEqual(object left, object right, Func<string> messageGenerator)
{
if(object.Equals(left, right))
{
left = left ?? "<NULL>";
right = right ?? "<NULL>";
throw CreateException("Assert Hit! {0}. Expected '{1}' (left) to differ from '{2}' (right). ", messageGenerator(), left, right);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNull(object val)
{
if (val != null)
{
throw CreateException(
"Assert Hit! Expected null pointer but instead found '{0}'", val);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNull(object val, string message)
{
if (val != null)
{
throw CreateException(
"Assert Hit! {0}", message);
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNull(object val, string message, object p1)
{
if (val != null)
{
throw CreateException(
"Assert Hit! {0}", message.Fmt(p1));
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotNull(object val)
{
if (val == null)
{
throw CreateException("Assert Hit! Found null pointer when value was expected");
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotNull(object val, string message)
{
if (val == null)
{
throw CreateException("Assert Hit! {0}", message);
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotNull(object val, string message, object p1)
{
if (val == null)
{
throw CreateException("Assert Hit! {0}", message.Fmt(p1));
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotNull(object val, string message, object p1, object p2)
{
if (val == null)
{
throw CreateException("Assert Hit! {0}", message.Fmt(p1, p2));
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotEmpty<T>(IEnumerable<T> val, string message = "")
{
if (!val.Any())
{
throw CreateException("Assert Hit! Expected empty collection but found {0} values. {1}", val.Count(), message);
}
}
// Use Assert.IsNotEqual to get better error output (with values)
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void IsNotEqual(object left, object right, string message)
{
if (object.Equals(left, right))
{
left = left ?? "<NULL>";
right = right ?? "<NULL>";
throw CreateException("Assert Hit! {0}. Unexpected value found '{1}'. ", message, left);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void Warn(bool condition)
{
if (!condition)
{
ModestTree.Log.Warn("Warning! See call stack");
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void Warn(bool condition, Func<string> messageGenerator)
{
if (!condition)
{
ModestTree.Log.Warn("Warning Assert hit! " + messageGenerator());
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void That(
bool condition, string message)
{
if (!condition)
{
throw CreateException("Assert hit! " + message);
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void That(
bool condition, string message, object p1)
{
if (!condition)
{
throw CreateException("Assert hit! " + message.Fmt(p1));
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void That(
bool condition, string message, object p1, object p2)
{
if (!condition)
{
throw CreateException("Assert hit! " + message.Fmt(p1, p2));
}
}
// We don't use params here to avoid the memory alloc
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void That(
bool condition, string message, object p1, object p2, object p3)
{
if (!condition)
{
throw CreateException("Assert hit! " + message.Fmt(p1, p2, p3));
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void Warn(bool condition, string message)
{
if (!condition)
{
ModestTree.Log.Warn("Warning Assert hit! " + message);
}
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void Throws(Action action)
{
Throws<Exception>(action);
}
#if ZEN_STRIP_ASSERTS_IN_BUILDS
[Conditional("UNITY_EDITOR")]
#endif
public static void Throws<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch (TException)
{
return;
}
throw CreateException(
"Expected to receive exception of type '{0}' but nothing was thrown", typeof(TException).Name);
}
public static ZenjectException CreateException()
{
return new ZenjectException("Assert hit!");
}
public static ZenjectException CreateException(string message)
{
return new ZenjectException(message);
}
public static ZenjectException CreateException(string message, params object[] parameters)
{
return new ZenjectException(message.Fmt(parameters));
}
public static ZenjectException CreateException(Exception innerException, string message, params object[] parameters)
{
return new ZenjectException(message.Fmt(parameters), innerException);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2968c9f42475ea146aec3ced9cbd99ad
timeCreated: 1427464253
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
#if !NET_4_6
namespace ModestTree.Util
{
// C# 3.5 only defines Func and Action to a maximum of 4 generic parameters
// Note that if you are using .NET framework > 3.5 you will have to comment these out to avoid ambiguous errors
public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
public delegate void Action<T1, T2, T3, T4, T5, T6, T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
}
#endif
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: cf53ad544fd972d4eb4716fb02fb5e9e
timeCreated: 1491195389
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using ModestTree.Util;
namespace ModestTree
{
public static class LinqExtensions
{
public static IEnumerable<T> Yield<T>(this T item)
{
yield return item;
}
// Return the first item when the list is of length one and otherwise returns default
public static TSource OnlyOrDefault<TSource>(this IEnumerable<TSource> source)
{
Assert.IsNotNull(source);
if (source.Count() > 1)
{
return default(TSource);
}
return source.FirstOrDefault();
}
// These are more efficient than Count() in cases where the size of the collection is not known
public static bool HasAtLeast<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.Take(amount).Count() == amount;
}
public static bool HasMoreThan<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.HasAtLeast(amount+1);
}
public static bool HasLessThan<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.HasAtMost(amount-1);
}
public static bool HasAtMost<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.Take(amount + 1).Count() <= amount;
}
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable.Any();
}
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> list)
{
return list.GroupBy(x => x).Where(x => x.Skip(1).Any()).Select(x => x.Key);
}
public static IEnumerable<T> Except<T>(this IEnumerable<T> list, T item)
{
return list.Except(item.Yield());
}
// LINQ already has a method called "Contains" that does the same thing as this
// BUT it fails to work with Mono 3.5 in some cases.
// For example the following prints False, True in Mono 3.5 instead of True, True like it should:
//
// IEnumerable<string> args = new string[]
// {
// "",
// null,
// };
// Log.Info(args.ContainsItem(null));
// Log.Info(args.Where(x => x == null).Any());
public static bool ContainsItem<T>(this IEnumerable<T> list, T value)
{
// Use object.Equals to support null values
return list.Where(x => object.Equals(x, value)).Any();
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 68fac2f8aa1edec4b9ef45794638a59c
timeCreated: 1427464292
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,84 @@
using System;
using System.Diagnostics;
namespace ModestTree
{
// Simple wrapper around unity's logging system
public static class Log
{
// Strip out debug logs outside of unity
[Conditional("UNITY_EDITOR")]
public static void Debug(string message, params object[] args)
{
#if NOT_UNITY3D
//Console.WriteLine(message.Fmt(args));
#else
//UnityEngine.Debug.Log(message.Fmt(args));
#endif
}
/////////////
public static void Info(string message, params object[] args)
{
#if NOT_UNITY3D
Console.WriteLine(message.Fmt(args));
#else
UnityEngine.Debug.Log(message.Fmt(args));
#endif
}
/////////////
public static void Warn(string message, params object[] args)
{
#if NOT_UNITY3D
Console.WriteLine(message.Fmt(args));
#else
UnityEngine.Debug.LogWarning(message.Fmt(args));
#endif
}
/////////////
public static void Trace(string message, params object[] args)
{
#if NOT_UNITY3D
Console.WriteLine(message.Fmt(args));
#else
UnityEngine.Debug.Log(message.Fmt(args));
#endif
}
/////////////
public static void ErrorException(Exception e)
{
#if NOT_UNITY3D
Console.WriteLine(e.ToString());
#else
UnityEngine.Debug.LogException(e);
#endif
}
public static void ErrorException(string message, Exception e)
{
#if NOT_UNITY3D
Console.WriteLine(message);
#else
UnityEngine.Debug.LogError(message);
UnityEngine.Debug.LogException(e);
#endif
}
public static void Error(string message, params object[] args)
{
#if NOT_UNITY3D
Console.WriteLine(message.Fmt(args));
#else
UnityEngine.Debug.LogError(message.Fmt(args));
#endif
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 622a24d4c6769414495ea1786bfee872
timeCreated: 1427464253
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ModestTree
{
public static class MiscExtensions
{
// We'd prefer to use the name Format here but that conflicts with
// the existing string.Format method
public static string Fmt(this string s, params object[] args)
{
// Do in-place change to avoid the memory alloc
// This should be fine because the params is always used instead of directly
// passing an array
for (int i = 0; i < args.Length; i++)
{
var arg = args[i];
if (arg == null)
{
// This is much more understandable than just the empty string
args[i] = "NULL";
}
else if (arg is Type)
{
// This often reads much better sometimes
args[i] = ((Type)arg).PrettyName();
}
}
return String.Format(s, args);
}
public static int IndexOf<T>(this IList<T> list, T item)
{
for (int i = 0; i < list.Count; i++)
{
if (object.Equals(list[i], item))
{
return i;
}
}
return -1;
}
public static string Join(this IEnumerable<string> values, string separator)
{
return string.Join(separator, values.ToArray());
}
// When using C# 4.6, for some reason the normal AddRange causes some allocations
// https://issuetracker.unity3d.com/issues/dot-net-4-dot-6-unexpected-gc-allocations-in-list-dot-addrange
public static void AllocFreeAddRange<T>(this IList<T> list, IList<T> items)
{
for (int i = 0; i < items.Count; i++)
{
list.Add(items[i]);
}
}
// Most of the time when you call remove you always intend on removing something
// so assert in that case
public static void RemoveWithConfirm<T>(this IList<T> list, T item)
{
bool removed = list.Remove(item);
Assert.That(removed);
}
public static void RemoveWithConfirm<T>(this LinkedList<T> list, T item)
{
bool removed = list.Remove(item);
Assert.That(removed);
}
public static void RemoveWithConfirm<TKey, TVal>(this IDictionary<TKey, TVal> dictionary, TKey key)
{
bool removed = dictionary.Remove(key);
Assert.That(removed);
}
public static void RemoveWithConfirm<T>(this HashSet<T> set, T item)
{
bool removed = set.Remove(item);
Assert.That(removed);
}
public static TVal GetValueAndRemove<TKey, TVal>(this IDictionary<TKey, TVal> dictionary, TKey key)
{
TVal val = dictionary[key];
dictionary.RemoveWithConfirm(key);
return val;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: da4e9bf39c1ac464d84d2f743a25f8d1
timeCreated: 1427464359
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
using System;
namespace ModestTree.Util
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class PreserveAttribute : Attribute
{
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: de17d24691e2bfd458a9d10cb1d49098
timeCreated: 1453682156
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,391 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ModestTree
{
public static class TypeExtensions
{
static readonly Dictionary<Type, bool> _isClosedGenericType = new Dictionary<Type, bool>();
static readonly Dictionary<Type, bool> _isOpenGenericType = new Dictionary<Type, bool>();
static readonly Dictionary<Type, bool> _isValueType = new Dictionary<Type, bool>();
static readonly Dictionary<Type, Type[]> _interfaces = new Dictionary<Type, Type[]>();
public static bool DerivesFrom<T>(this Type a)
{
return DerivesFrom(a, typeof(T));
}
// This seems easier to think about than IsAssignableFrom
public static bool DerivesFrom(this Type a, Type b)
{
return b != a && a.DerivesFromOrEqual(b);
}
public static bool DerivesFromOrEqual<T>(this Type a)
{
return DerivesFromOrEqual(a, typeof(T));
}
public static bool DerivesFromOrEqual(this Type a, Type b)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return b == a || b.GetTypeInfo().IsAssignableFrom(a.GetTypeInfo());
#else
return b == a || b.IsAssignableFrom(a);
#endif
}
#if !(UNITY_WSA && ENABLE_DOTNET)
// TODO: Is it possible to do this on WSA?
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.Interfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
{
return true;
}
Type baseType = givenType.BaseType;
if (baseType == null)
{
return false;
}
return IsAssignableToGenericType(baseType, genericType);
}
#endif
public static bool IsEnum(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsEnum;
#else
return type.IsEnum;
#endif
}
public static bool IsValueType(this Type type)
{
bool result;
if (!_isValueType.TryGetValue(type, out result))
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
result = type.GetTypeInfo().IsValueType;
#else
result = type.IsValueType;
#endif
_isValueType[type] = result;
}
return result;
}
public static MethodInfo[] DeclaredInstanceMethods(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetRuntimeMethods()
.Where(x => x.DeclaringType == type).ToArray();
#else
return type.GetMethods(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
#endif
}
public static PropertyInfo[] DeclaredInstanceProperties(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
// There doesn't appear to be an IsStatic member on PropertyInfo
return type.GetRuntimeProperties()
.Where(x => x.DeclaringType == type).ToArray();
#else
return type.GetProperties(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
#endif
}
public static FieldInfo[] DeclaredInstanceFields(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetRuntimeFields()
.Where(x => x.DeclaringType == type && !x.IsStatic).ToArray();
#else
return type.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
#endif
}
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
public static bool IsAssignableFrom(this Type a, Type b)
{
return a.GetTypeInfo().IsAssignableFrom(b.GetTypeInfo());
}
#endif
public static Type BaseType(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().BaseType;
#else
return type.BaseType;
#endif
}
public static bool IsGenericType(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsGenericType;
#else
return type.IsGenericType;
#endif
}
public static bool IsGenericTypeDefinition(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsGenericTypeDefinition;
#else
return type.IsGenericTypeDefinition;
#endif
}
public static bool IsPrimitive(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsPrimitive;
#else
return type.IsPrimitive;
#endif
}
public static bool IsInterface(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsInterface;
#else
return type.IsInterface;
#endif
}
public static bool ContainsGenericParameters(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().ContainsGenericParameters;
#else
return type.ContainsGenericParameters;
#endif
}
public static bool IsAbstract(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsAbstract;
#else
return type.IsAbstract;
#endif
}
public static bool IsSealed(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().IsSealed;
#else
return type.IsSealed;
#endif
}
public static MethodInfo Method(this Delegate del)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return del.GetMethodInfo();
#else
return del.Method;
#endif
}
public static Type[] GenericArguments(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().GenericTypeArguments;
#else
return type.GetGenericArguments();
#endif
}
public static Type[] Interfaces(this Type type)
{
Type[] result;
if (!_interfaces.TryGetValue(type, out result))
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
result = type.GetTypeInfo().ImplementedInterfaces.ToArray();
#else
result = type.GetInterfaces();
#endif
_interfaces.Add(type, result);
}
return result;
}
public static ConstructorInfo[] Constructors(this Type type)
{
#if UNITY_WSA && ENABLE_DOTNET && !UNITY_EDITOR
return type.GetTypeInfo().DeclaredConstructors.ToArray();
#else
return type.GetConstructors(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#endif
}
public static object GetDefaultValue(this Type type)
{
#if ENABLE_IL2CPP
// Workaround for IL2CPP returning default(T) for Activator.CreateInstance(typeof(T?))
if (type.IsGenericType() && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return null;
}
#endif
if (type.IsValueType())
{
return Activator.CreateInstance(type);
}
return null;
}
public static bool IsClosedGenericType(this Type type)
{
bool result;
if (!_isClosedGenericType.TryGetValue(type, out result))
{
result = type.IsGenericType() && type != type.GetGenericTypeDefinition();
_isClosedGenericType[type] = result;
}
return result;
}
public static IEnumerable<Type> GetParentTypes(this Type type)
{
if (type == null || type.BaseType() == null || type == typeof(object) || type.BaseType() == typeof(object))
{
yield break;
}
yield return type.BaseType();
foreach (var ancestor in type.BaseType().GetParentTypes())
{
yield return ancestor;
}
}
public static bool IsOpenGenericType(this Type type)
{
bool result;
if (!_isOpenGenericType.TryGetValue(type, out result))
{
result = type.IsGenericType() && type == type.GetGenericTypeDefinition();
_isOpenGenericType[type] = result;
}
return result;
}
public static T GetAttribute<T>(this MemberInfo provider)
where T : Attribute
{
return provider.AllAttributes<T>().Single();
}
public static T TryGetAttribute<T>(this MemberInfo provider)
where T : Attribute
{
return provider.AllAttributes<T>().OnlyOrDefault();
}
public static bool HasAttribute(
this MemberInfo provider, params Type[] attributeTypes)
{
return provider.AllAttributes(attributeTypes).Any();
}
public static bool HasAttribute<T>(this MemberInfo provider)
where T : Attribute
{
return provider.AllAttributes(typeof(T)).Any();
}
public static IEnumerable<T> AllAttributes<T>(
this MemberInfo provider)
where T : Attribute
{
return provider.AllAttributes(typeof(T)).Cast<T>();
}
public static IEnumerable<Attribute> AllAttributes(
this MemberInfo provider, params Type[] attributeTypes)
{
Attribute[] allAttributes;
#if NETFX_CORE
allAttributes = provider.GetCustomAttributes<Attribute>(true).ToArray();
#else
allAttributes = System.Attribute.GetCustomAttributes(provider, typeof(Attribute), true);
#endif
if (attributeTypes.Length == 0)
{
return allAttributes;
}
return allAttributes.Where(a => attributeTypes.Any(x => a.GetType().DerivesFromOrEqual(x)));
}
// We could avoid this duplication here by using ICustomAttributeProvider but this class
// does not exist on the WP8 platform
public static bool HasAttribute(
this ParameterInfo provider, params Type[] attributeTypes)
{
return provider.AllAttributes(attributeTypes).Any();
}
public static bool HasAttribute<T>(this ParameterInfo provider)
where T : Attribute
{
return provider.AllAttributes(typeof(T)).Any();
}
public static IEnumerable<T> AllAttributes<T>(
this ParameterInfo provider)
where T : Attribute
{
return provider.AllAttributes(typeof(T)).Cast<T>();
}
public static IEnumerable<Attribute> AllAttributes(
this ParameterInfo provider, params Type[] attributeTypes)
{
Attribute[] allAttributes;
#if NETFX_CORE
allAttributes = provider.GetCustomAttributes<Attribute>(true).ToArray();
#else
allAttributes = System.Attribute.GetCustomAttributes(provider, typeof(Attribute), true);
#endif
if (attributeTypes.Length == 0)
{
return allAttributes;
}
return allAttributes.Where(a => attributeTypes.Any(x => a.GetType().DerivesFromOrEqual(x)));
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2697c251f47f2bc40b32922c5a796f65
timeCreated: 1427464253
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ModestTree
{
public static class TypeStringFormatter
{
static readonly Dictionary<Type, string> _prettyNameCache = new Dictionary<Type, string>();
public static string PrettyName(this Type type)
{
string prettyName;
if (!_prettyNameCache.TryGetValue(type, out prettyName))
{
prettyName = PrettyNameInternal(type);
_prettyNameCache.Add(type, prettyName);
}
return prettyName;
}
static string PrettyNameInternal(Type type)
{
var sb = new StringBuilder();
if (type.IsNested)
{
sb.Append(type.DeclaringType.PrettyName());
sb.Append(".");
}
if (type.IsArray)
{
sb.Append(type.GetElementType().PrettyName());
sb.Append("[]");
}
else
{
var name = GetCSharpTypeName(type.Name);
if (type.IsGenericType())
{
var quoteIndex = name.IndexOf('`');
if (quoteIndex != -1)
{
sb.Append(name.Substring(0, name.IndexOf('`')));
}
else
{
sb.Append(name);
}
sb.Append("<");
if (type.IsGenericTypeDefinition())
{
var numArgs = type.GenericArguments().Count();
if (numArgs > 0)
{
sb.Append(new String(',', numArgs - 1));
}
}
else
{
sb.Append(string.Join(", ", type.GenericArguments().Select(t => t.PrettyName()).ToArray()));
}
sb.Append(">");
}
else
{
sb.Append(name);
}
}
return sb.ToString();
}
static string GetCSharpTypeName(string typeName)
{
switch (typeName)
{
case "String":
case "Object":
case "Void":
case "Byte":
case "Double":
case "Decimal":
return typeName.ToLower();
case "Int16":
return "short";
case "Int32":
return "int";
case "Int64":
return "long";
case "Single":
return "float";
case "Boolean":
return "bool";
default:
return typeName;
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 94a0a9a58e17e3d438c169678c9795f7
timeCreated: 1538018650
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
namespace ModestTree.Util
{
public class ValuePair<T1, T2>
{
public readonly T1 First;
public readonly T2 Second;
public ValuePair()
{
First = default(T1);
Second = default(T2);
}
public ValuePair(T1 first, T2 second)
{
First = first;
Second = second;
}
public override bool Equals(Object obj)
{
var that = obj as ValuePair<T1, T2>;
if (that == null)
{
return false;
}
return Equals(that);
}
public bool Equals(ValuePair<T1, T2> that)
{
if (that == null)
{
return false;
}
return object.Equals(First, that.First) && object.Equals(Second, that.Second);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 29 + (First == null ? 0 : First.GetHashCode());
hash = hash * 29 + (Second == null ? 0 : Second.GetHashCode());
return hash;
}
}
}
public class ValuePair<T1, T2, T3>
{
public readonly T1 First;
public readonly T2 Second;
public readonly T3 Third;
public ValuePair()
{
First = default(T1);
Second = default(T2);
Third = default(T3);
}
public ValuePair(T1 first, T2 second, T3 third)
{
First = first;
Second = second;
Third = third;
}
public override bool Equals(Object obj)
{
var that = obj as ValuePair<T1, T2, T3>;
if (that == null)
{
return false;
}
return Equals(that);
}
public bool Equals(ValuePair<T1, T2, T3> that)
{
if (that == null)
{
return false;
}
return object.Equals(First, that.First) && object.Equals(Second, that.Second) && object.Equals(Third, that.Third);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 29 + (First == null ? 0 : First.GetHashCode());
hash = hash * 29 + (Second == null ? 0 : Second.GetHashCode());
hash = hash * 29 + (Third == null ? 0 : Third.GetHashCode());
return hash;
}
}
}
public class ValuePair<T1, T2, T3, T4>
{
public readonly T1 First;
public readonly T2 Second;
public readonly T3 Third;
public readonly T4 Fourth;
public ValuePair()
{
First = default(T1);
Second = default(T2);
Third = default(T3);
Fourth = default(T4);
}
public ValuePair(T1 first, T2 second, T3 third, T4 fourth)
{
First = first;
Second = second;
Third = third;
Fourth = fourth;
}
public override bool Equals(Object obj)
{
var that = obj as ValuePair<T1, T2, T3, T4>;
if (that == null)
{
return false;
}
return Equals(that);
}
public bool Equals(ValuePair<T1, T2, T3, T4> that)
{
if (that == null)
{
return false;
}
return object.Equals(First, that.First) && object.Equals(Second, that.Second)
&& object.Equals(Third, that.Third) && object.Equals(Fourth, that.Fourth);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 29 + (First == null ? 0 : First.GetHashCode());
hash = hash * 29 + (Second == null ? 0 : Second.GetHashCode());
hash = hash * 29 + (Third == null ? 0 : Third.GetHashCode());
hash = hash * 29 + (Fourth == null ? 0 : Fourth.GetHashCode());
return hash;
}
}
}
public static class ValuePair
{
public static ValuePair<T1, T2> New<T1, T2>(T1 first, T2 second)
{
return new ValuePair<T1, T2>(first, second);
}
public static ValuePair<T1, T2, T3> New<T1, T2, T3>(T1 first, T2 second, T3 third)
{
return new ValuePair<T1, T2, T3>(first, second, third);
}
public static ValuePair<T1, T2, T3, T4> New<T1, T2, T3, T4>(T1 first, T2 second, T3 third, T4 fourth)
{
return new ValuePair<T1, T2, T3, T4>(first, second, third, fourth);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a3c968adce0a9a24e949dc4eedb496e8
timeCreated: 1478449513
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: