1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-12-24 01:09:23 +01:00

removed all non-recent obsolete methods, properties and types

This commit is contained in:
Ell 2024-07-17 18:21:13 +02:00
parent b4f45ba6b5
commit b0c6067555
22 changed files with 27 additions and 1543 deletions

View file

@ -29,6 +29,7 @@ Improvements
Removals
- Marked SpriteAnimation.ByName obsolete in favor of the new indexer
- **Removed obsolete methods and types CharExtensions, GenericFont.OneEmSpace, Code.GetReplacementString, TokenizedString.Measure, Keybind.GetDownTime, Keybind.GetUpTime, Keybind.GetTimeSincePress, EnumHelper, non-generic GenericDataHolder methods, as well as InputHandler key, gamepad and mouse-specific methods**
### MLEM.Ui
Additions
@ -49,11 +50,18 @@ Fixes
- Fixed auto-sized elements sometimes updating their location based on outdated parent positions
- Fixed Panel.ScrollToElement not scrolling correctly when the panel's area is dirty
Removals
- **Removed obsolete methods and properties Element.BeginImpl, Element.OnDisposed, parameter-heavy versions of Element.DrawTransformed and Element.Draw, Element.DrawEarly, Element.Dispose, Element.BeginDelegate, Tooltip.Paragraph, UiSystem.BlendState, UiSystem.SamplerState, UiSystem.DepthStencilState, UiSystem.Effect, as well as the StyleProp equality members**
### MLEM.Extended
Improvements
- **Added compatibility for MonoGame.Extended 4.0.0**
- Added compatibility for FNA.Extended
### MLEM.Data
Removals
- **Removed obsolete types DynamicEnumConverter, CopyExtensions, DynamicEnum, NetBufferSerializer, and NetExtensions**
## 6.3.1
No code changes

View file

@ -1,126 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if NET6_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
namespace MLEM.Data {
/// <summary>
/// A set of extensions for dealing with copying objects.
/// </summary>
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
#if NET6_0_OR_GREATER
[UnconditionalSuppressMessage("Aot", "IL3050"), UnconditionalSuppressMessage("Aot", "IL2070"), UnconditionalSuppressMessage("Aot", "IL2090")]
#endif
public static class CopyExtensions {
private const BindingFlags DefaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly Dictionary<Type, ConstructorInfo> ConstructorCache = new Dictionary<Type, ConstructorInfo>();
/// <summary>
/// Creates a shallow copy of the object and returns it.
/// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary>
/// <param name="obj">The object to create a shallow copy of</param>
/// <param name="flags">The binding flags for field searching</param>
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
/// <typeparam name="T">The type of the object to copy</typeparam>
/// <returns>A shallow copy of the object</returns>
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
public static T Copy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
obj.CopyInto(copy, flags, fieldInclusion);
return copy;
}
/// <summary>
/// Creates a deep copy of the object and returns it.
/// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary>
/// <param name="obj">The object to create a deep copy of</param>
/// <param name="flags">The binding flags for field searching</param>
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
/// <typeparam name="T">The type of the object to copy</typeparam>
/// <returns>A deep copy of the object</returns>
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
public static T DeepCopy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
obj.DeepCopyInto(copy, flags, fieldInclusion);
return copy;
}
/// <summary>
/// Copies the given object <paramref name="obj"/> into the given object <paramref name="otherObj"/> in a shallow manner.
/// </summary>
/// <param name="obj">The object to create a shallow copy of</param>
/// <param name="otherObj">The object to copy into</param>
/// <param name="flags">The binding flags for field searching</param>
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
/// <typeparam name="T">The type of the object to copy</typeparam>
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
public static void CopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
foreach (var field in typeof(T).GetFields(flags)) {
if (fieldInclusion == null || fieldInclusion(field))
field.SetValue(otherObj, field.GetValue(obj));
}
}
/// <summary>
/// Copies the given object <paramref name="obj"/> into the given object <paramref name="otherObj"/> in a deep manner.
/// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary>
/// <param name="obj">The object to create a deep copy of</param>
/// <param name="otherObj">The object to copy into</param>
/// <param name="flags">The binding flags for field searching</param>
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
/// <typeparam name="T">The type of the object to copy</typeparam>
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
public static void DeepCopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
foreach (var field in obj.GetType().GetFields(flags)) {
if (fieldInclusion != null && !fieldInclusion(field))
continue;
var val = field.GetValue(obj);
if (val == null || field.FieldType.IsValueType) {
// if we're a value type (struct or primitive) or null, we can just set the value
field.SetValue(otherObj, val);
} else {
var otherVal = field.GetValue(otherObj);
// if the object we want to copy into doesn't have a value yet, we create one
if (otherVal == null) {
otherVal = CopyExtensions.Construct(field.FieldType, flags);
field.SetValue(otherObj, otherVal);
}
val.DeepCopyInto(otherVal, flags);
}
}
}
private static object Construct(Type t, BindingFlags flags) {
if (!CopyExtensions.ConstructorCache.TryGetValue(t, out var constructor)) {
var constructors = t.GetConstructors(flags);
// find a contructor with the correct attribute
constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
// find a parameterless construcotr
if (constructor == null)
constructor = t.GetConstructor(flags, null, Type.EmptyTypes, null);
// fall back to the first constructor
if (constructor == null)
constructor = constructors.FirstOrDefault();
if (constructor == null)
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
CopyExtensions.ConstructorCache.Add(t, constructor);
}
return constructor.Invoke(new object[constructor.GetParameters().Length]);
}
}
/// <summary>
/// An attribute that, when added to a constructor, will make that constructor the one used by <see cref="CopyExtensions.Copy{T}"/>, <see cref="CopyExtensions.DeepCopy{T}"/> and <see cref="CopyExtensions.DeepCopyInto{T}"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor), Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
public class CopyConstructorAttribute : Attribute {}
}

View file

@ -1,410 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
using MLEM.Data.Json;
using Newtonsoft.Json;
namespace MLEM.Data {
/// <summary>
/// A dynamic enum is a class that represents enum-like single-instance value behavior with additional capabilities, including dynamic addition of new arbitrary values.
/// A dynamic enum uses <see cref="BigInteger"/> as its underlying type, allowing for an arbitrary number of enum values to be created, even when a <see cref="FlagsAttribute"/>-like structure is used that would only allow for up to 64 values in a regular enum.
/// All enum operations including <see cref="And{T}"/>, <see cref="Or{T}"/>, <see cref="Xor{T}"/> and <see cref="Neg{T}"/> are supported and can be implemented in derived classes using operator overloads.
/// To create a custom dynamic enum, simply create a class that extends <see cref="DynamicEnum"/>. New values can then be added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
/// </summary>
/// <remarks>
/// To include enum-like operator overloads in a dynamic enum named MyEnum, the following code can be used:
/// <code>
/// public static implicit operator BigInteger(MyEnum value) => GetValue(value);
/// public static implicit operator MyEnum(BigInteger value) => GetEnumValue&lt;MyEnum&gt;(value);
/// public static MyEnum operator |(MyEnum left, MyEnum right) => Or(left, right);
/// public static MyEnum operator &amp;(MyEnum left, MyEnum right) => And(left, right);
/// public static MyEnum operator ^(MyEnum left, MyEnum right) => Xor(left, right);
/// public static MyEnum operator ~(MyEnum value) => Neg(value);
/// </code>
/// </remarks>
[Obsolete("DynamicEnum has been moved into the DynamicEnums library: https://www.nuget.org/packages/DynamicEnums"), JsonConverter(typeof(DynamicEnumConverter))]
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Aot", "IL2067")]
#endif
public abstract class DynamicEnum {
private static readonly Dictionary<Type, Storage> Storages = new Dictionary<Type, Storage>();
private readonly BigInteger value;
private Dictionary<DynamicEnum, bool> allFlagsCache;
private Dictionary<DynamicEnum, bool> anyFlagsCache;
private string name;
/// <summary>
/// Creates a new dynamic enum instance.
/// This constructor is protected as it is only invoked via reflection.
/// </summary>
/// <param name="name">The name of the enum value</param>
/// <param name="value">The value</param>
protected DynamicEnum(string name, BigInteger value) {
this.value = value;
this.name = name;
}
/// <summary>
/// Returns true if this enum value has ALL of the given <see cref="DynamicEnum"/> flags on it.
/// This operation is equivalent to <see cref="Enum.HasFlag"/>.
/// </summary>
/// <seealso cref="HasAnyFlag"/>
/// <param name="flags">The flags to query</param>
/// <returns>True if all of the flags are present, false otherwise</returns>
public bool HasFlag(DynamicEnum flags) {
if (this.allFlagsCache == null)
this.allFlagsCache = new Dictionary<DynamicEnum, bool>();
if (!this.allFlagsCache.TryGetValue(flags, out var ret)) {
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) == DynamicEnum.GetValue(flags);
this.allFlagsCache.Add(flags, ret);
}
return ret;
}
/// <summary>
/// Returns true if this enum value has ANY of the given <see cref="DynamicEnum"/> flags on it
/// </summary>
/// <seealso cref="HasFlag"/>
/// <param name="flags">The flags to query</param>
/// <returns>True if one of the flags is present, false otherwise</returns>
public bool HasAnyFlag(DynamicEnum flags) {
if (this.anyFlagsCache == null)
this.anyFlagsCache = new Dictionary<DynamicEnum, bool>();
if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) {
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) != 0;
this.anyFlagsCache.Add(flags, ret);
}
return ret;
}
/// <summary>Returns a string that represents the current object.</summary>
/// <returns>A string that represents the current object.</returns>
public override string ToString() {
if (this.name == null) {
var included = new List<DynamicEnum>();
if (DynamicEnum.GetValue(this) != 0) {
foreach (var v in DynamicEnum.GetValues(this.GetType())) {
if (this.HasFlag(v) && DynamicEnum.GetValue(v) != 0)
included.Add(v);
}
}
this.name = included.Count > 0 ? string.Join(" | ", included) : DynamicEnum.GetValue(this).ToString();
}
return this.name;
}
/// <summary>
/// Adds a new enum value to the given enum type <typeparamref name="T"/>
/// </summary>
/// <param name="name">The name of the enum value to add</param>
/// <param name="value">The value to add</param>
/// <typeparam name="T">The type to add this value to</typeparam>
/// <returns>The newly created enum value</returns>
/// <exception cref="ArgumentException">Thrown if the name or value passed are already present</exception>
public static T Add<T>(string name, BigInteger value) where T : DynamicEnum {
var storage = DynamicEnum.GetStorage(typeof(T));
// cached parsed values and names might be incomplete with new values
storage.ClearCaches();
if (storage.Values.ContainsKey(value))
throw new ArgumentException($"Duplicate value {value}", nameof(value));
foreach (var v in storage.Values.Values) {
if (v.name == name)
throw new ArgumentException($"Duplicate name {name}", nameof(name));
}
var ret = DynamicEnum.Construct(typeof(T), name, value);
storage.Values.Add(value, ret);
return (T) ret;
}
/// <summary>
/// Adds a new enum value to the given enum type <typeparamref name="T"/>.
/// This method differs from <see cref="Add{T}"/> in that it automatically determines a value.
/// The value determined will be the next free number in a sequence, which represents the default behavior in an enum if enum values are not explicitly numbered.
/// </summary>
/// <param name="name">The name of the enum value to add</param>
/// <typeparam name="T">The type to add this value to</typeparam>
/// <returns>The newly created enum value</returns>
public static T AddValue<T>(string name) where T : DynamicEnum {
BigInteger value = 0;
while (DynamicEnum.IsDefined(typeof(T), value))
value++;
return DynamicEnum.Add<T>(name, value);
}
/// <summary>
/// Adds a new flag enum value to the given enum type <typeparamref name="T"/>.
/// This method differs from <see cref="Add{T}"/> in that it automatically determines a value.
/// The value determined will be the next free power of two, allowing enum values to be combined using bitwise operations to create <see cref="FlagsAttribute"/>-like behavior.
/// </summary>
/// <param name="name">The name of the enum value to add</param>
/// <typeparam name="T">The type to add this value to</typeparam>
/// <returns>The newly created enum value</returns>
public static T AddFlag<T>(string name) where T : DynamicEnum {
BigInteger value = 1;
while (DynamicEnum.IsDefined(typeof(T), value))
value <<= 1;
return DynamicEnum.Add<T>(name, value);
}
/// <summary>
/// Returns a collection of all of the enum values that are explicitly defined for the given dynamic enum type <typeparamref name="T"/>.
/// A value counts as explicitly defined if it has been added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
/// </summary>
/// <typeparam name="T">The type whose values to get</typeparam>
/// <returns>The defined values for the given type</returns>
public static IEnumerable<T> GetValues<T>() where T : DynamicEnum {
return DynamicEnum.GetValues(typeof(T)).Cast<T>();
}
/// <summary>
/// Returns a collection of all of the enum values that are explicitly defined for the given dynamic enum type <paramref name="type"/>.
/// A value counts as explicitly defined if it has been added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
/// </summary>
/// <param name="type">The type whose values to get</param>
/// <returns>The defined values for the given type</returns>
public static IEnumerable<DynamicEnum> GetValues(Type type) {
return DynamicEnum.GetStorage(type).Values.Values;
}
/// <summary>
/// Returns all of the defined values from the given dynamic enum type <typeparamref name="T"/> which are contained in <paramref name="combinedFlag"/>.
/// Note that, if combined flags are defined in <typeparamref name="T"/>, and <paramref name="combinedFlag"/> contains them, they will also be returned.
/// </summary>
/// <param name="combinedFlag">The combined flags whose individual flags to return.</param>
/// <param name="includeZero">Whether the enum value 0 should also be returned, if <typeparamref name="T"/> contains one.</param>
/// <typeparam name="T">The type of enum.</typeparam>
/// <returns>All of the flags that make up <paramref name="combinedFlag"/>.</returns>
public static IEnumerable<T> GetFlags<T>(T combinedFlag, bool includeZero = true) where T : DynamicEnum {
foreach (var flag in DynamicEnum.GetValues<T>()) {
if (combinedFlag.HasFlag(flag) && (includeZero || DynamicEnum.GetValue(flag) != BigInteger.Zero))
yield return flag;
}
}
/// <summary>
/// Returns all of the defined unique flags from the given dynamic enum type <typeparamref name="T"/> which are contained in <paramref name="combinedFlag"/>.
/// Any combined flags (flags that aren't powers of two) which are defined in <typeparamref name="T"/> will not be returned.
/// </summary>
/// <param name="combinedFlag">The combined flags whose individual flags to return.</param>
/// <typeparam name="T">The type of enum.</typeparam>
/// <returns>All of the unique flags that make up <paramref name="combinedFlag"/>.</returns>
public static IEnumerable<T> GetUniqueFlags<T>(T combinedFlag) where T : DynamicEnum {
// we can't use the same method here as EnumHelper.GetUniqueFlags since DynamicEnum doesn't guarantee sorted values
var max = DynamicEnum.GetValues<T>().Max(DynamicEnum.GetValue);
var uniqueFlag = BigInteger.One;
while (uniqueFlag <= max) {
if (DynamicEnum.IsDefined(typeof(T), uniqueFlag)) {
var uniqueFlagValue = DynamicEnum.GetEnumValue<T>(uniqueFlag);
if (combinedFlag.HasFlag(uniqueFlagValue))
yield return uniqueFlagValue;
}
uniqueFlag <<= 1;
}
}
/// <summary>
/// Returns the bitwise OR (|) combination of the two dynamic enum values
/// </summary>
/// <param name="left">The left value</param>
/// <param name="right">The right value</param>
/// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise OR (|) combination</returns>
public static T Or<T>(T left, T right) where T : DynamicEnum {
var cache = DynamicEnum.GetStorage(typeof(T)).OrCache;
if (!cache.TryGetValue((left, right), out var ret)) {
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) | DynamicEnum.GetValue(right));
cache.Add((left, right), ret);
}
return (T) ret;
}
/// <summary>
/// Returns the bitwise AND (&amp;) combination of the two dynamic enum values
/// </summary>
/// <param name="left">The left value</param>
/// <param name="right">The right value</param>
/// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise AND (&amp;) combination</returns>
public static T And<T>(T left, T right) where T : DynamicEnum {
var cache = DynamicEnum.GetStorage(typeof(T)).AndCache;
if (!cache.TryGetValue((left, right), out var ret)) {
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) & DynamicEnum.GetValue(right));
cache.Add((left, right), ret);
}
return (T) ret;
}
/// <summary>
/// Returns the bitwise XOR (^) combination of the two dynamic enum values
/// </summary>
/// <param name="left">The left value</param>
/// <param name="right">The right value</param>
/// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise XOR (^) combination</returns>
public static T Xor<T>(T left, T right) where T : DynamicEnum {
var cache = DynamicEnum.GetStorage(typeof(T)).XorCache;
if (!cache.TryGetValue((left, right), out var ret)) {
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) ^ DynamicEnum.GetValue(right));
cache.Add((left, right), ret);
}
return (T) ret;
}
/// <summary>
/// Returns the bitwise NEG (~) combination of the dynamic enum value
/// </summary>
/// <param name="value">The value</param>
/// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise NEG (~) value</returns>
public static T Neg<T>(T value) where T : DynamicEnum {
var cache = DynamicEnum.GetStorage(typeof(T)).NegCache;
if (!cache.TryGetValue(value, out var ret)) {
ret = DynamicEnum.GetEnumValue<T>(~DynamicEnum.GetValue(value));
cache.Add(value, ret);
}
return (T) ret;
}
/// <summary>
/// Returns the <see cref="BigInteger"/> representation of the given dynamic enum value
/// </summary>
/// <param name="value">The value whose number representation to get</param>
/// <returns>The value's number representation</returns>
public static BigInteger GetValue(DynamicEnum value) {
return value?.value ?? 0;
}
/// <summary>
/// Returns the defined or combined dynamic enum value for the given <see cref="BigInteger"/> representation
/// </summary>
/// <param name="value">The value whose dynamic enum value to get</param>
/// <typeparam name="T">The type that the returned dynamic enum should have</typeparam>
/// <returns>The defined or combined dynamic enum value</returns>
public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum {
return (T) DynamicEnum.GetEnumValue(typeof(T), value);
}
/// <summary>
/// Returns the defined or combined dynamic enum value for the given <see cref="BigInteger"/> representation
/// </summary>
/// <param name="type">The type that the returned dynamic enum should have</param>
/// <param name="value">The value whose dynamic enum value to get</param>
/// <returns>The defined or combined dynamic enum value</returns>
public static DynamicEnum GetEnumValue(Type type, BigInteger value) {
var storage = DynamicEnum.GetStorage(type);
// get the defined value if it exists
if (storage.Values.TryGetValue(value, out var defined))
return defined;
// otherwise, cache the combined value
if (!storage.FlagCache.TryGetValue(value, out var combined)) {
combined = DynamicEnum.Construct(type, null, value);
storage.FlagCache.Add(value, combined);
}
return combined;
}
/// <summary>
/// Parses the given <see cref="string"/> into a dynamic enum value and returns the result.
/// This method supports defined enum values as well as values combined using the pipe (|) character and any number of spaces.
/// If no enum value can be parsed, null is returned.
/// </summary>
/// <param name="strg">The string to parse into a dynamic enum value</param>
/// <typeparam name="T">The type of the dynamic enum value to parse</typeparam>
/// <returns>The parsed enum value, or null if parsing fails</returns>
public static T Parse<T>(string strg) where T : DynamicEnum {
return (T) DynamicEnum.Parse(typeof(T), strg);
}
/// <summary>
/// Parses the given <see cref="string"/> into a dynamic enum value and returns the result.
/// This method supports defined enum values as well as values combined using the pipe (|) character and any number of spaces.
/// If no enum value can be parsed, null is returned.
/// </summary>
/// <param name="type">The type of the dynamic enum value to parse</param>
/// <param name="strg">The string to parse into a dynamic enum value</param>
/// <returns>The parsed enum value, or null if parsing fails</returns>
public static DynamicEnum Parse(Type type, string strg) {
var cache = DynamicEnum.GetStorage(type).ParseCache;
if (!cache.TryGetValue(strg, out var cached)) {
BigInteger? accum = null;
foreach (var val in strg.Split('|')) {
foreach (var defined in DynamicEnum.GetValues(type)) {
if (defined.name == val.Trim()) {
accum = (accum ?? 0) | DynamicEnum.GetValue(defined);
break;
}
}
}
if (accum != null)
cached = DynamicEnum.GetEnumValue(type, accum.Value);
cache.Add(strg, cached);
}
return cached;
}
/// <summary>
/// Returns whether the given <paramref name="value"/> is defined in the given dynamic enum <paramref name="type"/>.
/// A value counts as explicitly defined if it has been added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
/// </summary>
/// <param name="type">The dynamic enum type to query.</param>
/// <param name="value">The value to query.</param>
/// <returns>Whether the <paramref name="value"/> is defined.</returns>
public static bool IsDefined(Type type, BigInteger value) {
return DynamicEnum.GetStorage(type).Values.ContainsKey(value);
}
/// <summary>
/// Returns whether the given <paramref name="value"/> is defined in its dynamic enum type.
/// A value counts as explicitly defined if it has been added using <see cref="Add{T}"/>, <see cref="AddValue{T}"/> or <see cref="AddFlag{T}"/>.
/// </summary>
/// <param name="value">The value to query.</param>
/// <returns>Whether the <paramref name="value"/> is defined.</returns>
public static bool IsDefined(DynamicEnum value) {
return value != null && DynamicEnum.IsDefined(value.GetType(), DynamicEnum.GetValue(value));
}
private static Storage GetStorage(Type type) {
if (!DynamicEnum.Storages.TryGetValue(type, out var storage)) {
storage = new Storage();
DynamicEnum.Storages.Add(type, storage);
}
return storage;
}
private static DynamicEnum Construct(Type type, string name, BigInteger value) {
return (DynamicEnum) Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] {name, value}, CultureInfo.InvariantCulture);
}
private class Storage {
public readonly Dictionary<BigInteger, DynamicEnum> Values = new Dictionary<BigInteger, DynamicEnum>();
public readonly Dictionary<BigInteger, DynamicEnum> FlagCache = new Dictionary<BigInteger, DynamicEnum>();
public readonly Dictionary<string, DynamicEnum> ParseCache = new Dictionary<string, DynamicEnum>();
public readonly Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum> OrCache = new Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum>();
public readonly Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum> AndCache = new Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum>();
public readonly Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum> XorCache = new Dictionary<(DynamicEnum, DynamicEnum), DynamicEnum>();
public readonly Dictionary<DynamicEnum, DynamicEnum> NegCache = new Dictionary<DynamicEnum, DynamicEnum>();
public void ClearCaches() {
this.FlagCache.Clear();
this.ParseCache.Clear();
this.OrCache.Clear();
this.AndCache.Clear();
this.XorCache.Clear();
this.NegCache.Clear();
}
}
}
}

View file

@ -1,31 +0,0 @@
using System;
using Newtonsoft.Json;
namespace MLEM.Data.Json {
/// <summary>
/// Converts a <see cref="DynamicEnum"/> to and from JSON
/// </summary>
[Obsolete("DynamicEnum has been moved into the DynamicEnums library: https://www.nuget.org/packages/DynamicEnums"), JsonConverter(typeof(DynamicEnumConverter))]
public class DynamicEnumConverter : JsonConverter<DynamicEnum> {
/// <summary>Writes the JSON representation of the object.</summary>
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, DynamicEnum value, JsonSerializer serializer) {
writer.WriteValue(value.ToString());
}
/// <summary>Reads the JSON representation of the object.</summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read. If there is no existing value then <c>null</c> will be used.</param>
/// <param name="hasExistingValue">The existing value has a value.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns>
public override DynamicEnum ReadJson(JsonReader reader, Type objectType, DynamicEnum existingValue, bool hasExistingValue, JsonSerializer serializer) {
return DynamicEnum.Parse(objectType, reader.Value.ToString());
}
}
}

View file

@ -13,9 +13,6 @@ namespace MLEM.Data.Json {
/// </summary>
public static readonly JsonConverter[] Converters = {
new Direction2Converter(),
#pragma warning disable CS0618
new DynamicEnumConverter(),
#pragma warning restore CS0618
new PointConverter(),
new RectangleConverter(),
new RectangleFConverter(),

View file

@ -19,12 +19,6 @@ namespace MLEM.Data.Json {
[JsonProperty]
private Dictionary<string, JsonTypeSafeWrapper> data;
/// <inheritdoc />
[Obsolete("This method will be removed in a future update in favor of the generic SetData<T>.")]
public void SetData(string key, object data) {
this.SetData<object>(key, data);
}
/// <inheritdoc />
public void SetData<T>(string key, T data) {
if (EqualityComparer<T>.Default.Equals(data, default)) {

View file

@ -1,106 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Lidgren.Network;
using Newtonsoft.Json;
namespace MLEM.Data {
/// <summary>
/// A net buffer serializer allows easily writing generic objects into a Lidgren.Network <see cref="NetBuffer"/>.
/// It can be used both for serialization of outgoing packets, and deserialization of incoming packets.
/// Before serializing and deserializing an object, each of the object's fields has to have a handler. New handlers can be added using <see cref="AddHandler{T}(System.Action{Lidgren.Network.NetBuffer,T},System.Func{Lidgren.Network.NetBuffer,T})"/> or <see cref="AddHandler{T}(Newtonsoft.Json.JsonSerializer)"/>.
/// </summary>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
#if NET6_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Aot", "IL2070")]
#endif
public class NetBufferSerializer {
private readonly Dictionary<Type, Action<NetBuffer, object>> writeFunctions = new Dictionary<Type, Action<NetBuffer, object>>();
private readonly Dictionary<Type, Func<NetBuffer, object>> readFunctions = new Dictionary<Type, Func<NetBuffer, object>>();
private readonly Dictionary<Type, FieldInfo[]> fieldCache = new Dictionary<Type, FieldInfo[]>();
/// <summary>
/// Create a new net buffer serializer with some default serialization and deserialization implementations for various types.
/// </summary>
public NetBufferSerializer() {
foreach (var method in typeof(NetBuffer).GetMethods(BindingFlags.Instance | BindingFlags.Public)) {
if (method.GetParameters().Length == 0 && method.Name.StartsWith("Read", StringComparison.Ordinal) && method.Name.Substring(4) == method.ReturnType.Name)
this.readFunctions[method.ReturnType] = buffer => method.Invoke(buffer, null);
}
foreach (var method in typeof(NetBuffer).GetMethods(BindingFlags.Instance | BindingFlags.Public)) {
if (method.Name.Equals("Write", StringComparison.InvariantCulture)) {
var parameters = method.GetParameters();
if (parameters.Length == 1)
this.writeFunctions[parameters[0].ParameterType] = (buffer, o) => method.Invoke(buffer, new[] {o});
}
}
this.AddHandler((buffer, o) => buffer.Write(o), buffer => buffer.ReadVector2());
this.AddHandler((buffer, o) => buffer.Write(o), buffer => buffer.ReadGuid());
this.AddHandler((buffer, o) => buffer.Write(o), buffer => buffer.ReadDirection());
}
/// <summary>
/// Serializes the given object into the given net buffer.
/// Note that each field in the object has to have a handler (<see cref="AddHandler{T}(System.Action{Lidgren.Network.NetBuffer,T},System.Func{Lidgren.Network.NetBuffer,T})"/>)
/// </summary>
/// <param name="buffer">The buffer to serialize into</param>
/// <param name="o">The object to serialize</param>
/// <param name="flags">The binding flags to search for fields in the object by</param>
/// <exception cref="ArgumentException">If any of the object's fields has no writer</exception>
public void Serialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
foreach (var field in this.GetFields(o.GetType(), flags)) {
if (!this.writeFunctions.TryGetValue(field.FieldType, out var func))
throw new ArgumentException($"The type {field.FieldType} doesn't have a writer");
func(buffer, field.GetValue(o));
}
}
/// <summary>
/// Deserializes the net buffer's content into the given object.
/// If this is used for packet serialization, a new instance of the required type has to be created before this method is called.
/// </summary>
/// <param name="buffer">The buffer to read the data from</param>
/// <param name="o">The object to serialize into</param>
/// <param name="flags">The binding flags to search for fields in the object by</param>
/// <exception cref="ArgumentException">If any of the object's fields has no reader</exception>
public void Deserialize(NetBuffer buffer, object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) {
foreach (var field in this.GetFields(o.GetType(), flags)) {
if (!this.readFunctions.TryGetValue(field.FieldType, out var func))
throw new ArgumentException($"The type {field.FieldType} doesn't have a reader");
field.SetValue(o, func(buffer));
}
}
private IEnumerable<FieldInfo> GetFields(Type type, BindingFlags flags) {
if (!this.fieldCache.TryGetValue(type, out var fields)) {
fields = type.GetFields(flags);
Array.Sort(fields, (f1, f2) => string.Compare(f1.Name, f2.Name, StringComparison.Ordinal));
this.fieldCache.Add(type, fields);
}
return fields;
}
/// <summary>
/// Adds a manually created deserialization and serialization handler to this net buffer serializer.
/// </summary>
/// <param name="write">The function to write the given object into the net buffer</param>
/// <param name="read">The function to read the given object out of the net buffer</param>
/// <typeparam name="T">The type that will be serialized and deserialized</typeparam>
public void AddHandler<T>(Action<NetBuffer, T> write, Func<NetBuffer, T> read) {
this.writeFunctions.Add(typeof(T), (buffer, o) => write(buffer, (T) o));
this.readFunctions.Add(typeof(T), buffer => read(buffer));
}
/// <summary>
/// Adds a JSON-based deserialization and serialization handler to this net buffer serializer.
/// Objects that are serialized in this way are converted to JSON, and the resulting JSON is compressed.
/// </summary>
/// <param name="serializer">The JSON serializer to use</param>
/// <typeparam name="T">The type that will be serialized and deserialized</typeparam>
public void AddHandler<T>(JsonSerializer serializer) {
this.AddHandler((buffer, o) => buffer.WriteObject(o, serializer), buffer => buffer.ReadObject<T>(serializer));
}
}
}

View file

@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using MLEM.Misc;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
namespace MLEM.Data {
/// <summary>
/// A set of extensions for dealing with <see cref="NetBuffer"/>.
/// </summary>
public static class NetExtensions {
/// <summary>
/// Writes a <see cref="Vector2"/> to the given net buffer
/// </summary>
/// <param name="buffer">The buffer to write to</param>
/// <param name="vector">The vector to write</param>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static void Write(this NetBuffer buffer, Vector2 vector) {
buffer.Write(vector.X);
buffer.Write(vector.Y);
}
/// <summary>
/// Reads a <see cref="Vector2"/> from the given net buffer
/// </summary>
/// <param name="buffer">The buffer to read from</param>
/// <returns>The read vector</returns>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static Vector2 ReadVector2(this NetBuffer buffer) {
return new Vector2(buffer.ReadFloat(), buffer.ReadFloat());
}
/// <summary>
/// Writes a <see cref="Guid"/> to the given net buffer
/// </summary>
/// <param name="buffer">The buffer to write to</param>
/// <param name="guid">The guid to write</param>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static void Write(this NetBuffer buffer, Guid guid) {
buffer.Write(guid.ToByteArray());
}
/// <summary>
/// Reads a <see cref="Guid"/> from the given net buffer
/// </summary>
/// <param name="buffer">The buffer to read from</param>
/// <returns>The read guid</returns>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static Guid ReadGuid(this NetBuffer buffer) {
return new Guid(buffer.ReadBytes(16));
}
/// <summary>
/// Writes a <see cref="Direction2"/> to the given net buffer
/// </summary>
/// <param name="buffer">The buffer to write to</param>
/// <param name="direction">The direction to write</param>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static void Write(this NetBuffer buffer, Direction2 direction) {
buffer.Write((short) direction);
}
/// <summary>
/// Reads a <see cref="Direction2"/> from the given net buffer
/// </summary>
/// <param name="buffer">The buffer to read from</param>
/// <returns>The read direction</returns>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static Direction2 ReadDirection(this NetBuffer buffer) {
return (Direction2) buffer.ReadInt16();
}
/// <summary>
/// Writes a generic object to the given net buffer using a <see cref="JsonSerializer"/>.
/// </summary>
/// <param name="buffer">The buffer to write to</param>
/// <param name="obj">The object to write</param>
/// <param name="serializer">The JSON serializer to use</param>
/// <typeparam name="T">The type of object written</typeparam>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static void WriteObject<T>(this NetBuffer buffer, T obj, JsonSerializer serializer) {
if (EqualityComparer<T>.Default.Equals(obj, default)) {
buffer.Write(0);
return;
}
using (var memory = new MemoryStream()) {
using (var stream = new DeflateStream(memory, CompressionLevel.Fastest, true))
serializer.Serialize(new BsonDataWriter(stream), obj, typeof(T));
var arr = memory.ToArray();
buffer.Write(arr.Length);
buffer.Write(arr);
}
}
/// <summary>
/// Reads a generic object from the given buffer using a <see cref="JsonSerializer"/>.
/// </summary>
/// <param name="buffer">The buffer to read from</param>
/// <param name="serializer">The JSON serializer to use</param>
/// <typeparam name="T">The type of object read</typeparam>
/// <returns>The read object</returns>
[Obsolete("Lidgren.Network support is deprecated. Consider using LiteNetLib or a custom implementation instead.")]
public static T ReadObject<T>(this NetBuffer buffer, JsonSerializer serializer) {
var length = buffer.ReadInt32();
if (length <= 0)
return default;
var arr = buffer.ReadBytes(length);
using (var memory = new MemoryStream(arr)) {
using (var stream = new DeflateStream(memory, CompressionMode.Decompress, true))
return serializer.Deserialize<T>(new BsonDataReader(stream));
}
}
}
}

View file

@ -116,9 +116,6 @@ namespace MLEM.Startup {
this.PreDraw?.Invoke(this, gameTime);
CoroutineHandler.RaiseEvent(CoroutineEvents.PreDraw);
#pragma warning disable CS0618
this.UiSystem.DrawEarly(gameTime, this.SpriteBatch);
#pragma warning restore CS0618
this.DoDraw(gameTime);
this.UiSystem.Draw(gameTime, this.SpriteBatch);

View file

@ -18,7 +18,7 @@ namespace MLEM.Ui.Elements {
/// <summary>
/// This class represents a generic base class for ui elements of a <see cref="UiSystem"/>.
/// </summary>
public abstract class Element : GenericDataHolder, IDisposable {
public abstract class Element : GenericDataHolder {
/// <summary>
/// This field holds an epsilon value used in element <see cref="Size"/>, position and resulting <see cref="Area"/> calculations to mitigate floating point rounding inaccuracies.
@ -202,14 +202,6 @@ namespace MLEM.Ui.Elements {
/// Note that, when this is non-null, a new <c>SpriteBatch.Begin</c> call is used for this element.
/// </summary>
public Matrix Transform = Matrix.Identity;
/// <summary>
/// The call that this element should make to <see cref="SpriteBatch"/> to begin drawing.
/// Note that, when this is non-null, a new <c>SpriteBatch.Begin</c> call is used for this element.
/// </summary>
#pragma warning disable CS0618
[Obsolete("BeginImpl is deprecated. You can create a custom element class and override Draw instead.")]
public BeginDelegate BeginImpl;
#pragma warning restore CS0618
/// <summary>
/// Set this field to false to disallow the element from being selected.
/// An unselectable element is skipped by automatic navigation and its <see cref="OnSelected"/> callback will never be called.
@ -486,12 +478,6 @@ namespace MLEM.Ui.Elements {
/// Event that is called when this element is removed from a <see cref="UiSystem"/>, that is, when this element's <see cref="System"/> is set to <see langword="null"/>.
/// </summary>
public GenericCallback OnRemovedFromUi;
/// <summary>
/// Event that is called when this element's <see cref="Dispose"/> method is called.
/// This event is useful for unregistering global event handlers when this object should be destroyed.
/// </summary>
[Obsolete("OnDisposed will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
public GenericCallback OnDisposed;
/// <summary>
/// A list of all of this element's direct children.
@ -570,12 +556,6 @@ namespace MLEM.Ui.Elements {
this.SetSortedChildrenDirty();
}
/// <inheritdoc />
[Obsolete("Dispose will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
~Element() {
this.Dispose();
}
/// <summary>
/// Adds a child to this element.
/// </summary>
@ -1077,32 +1057,14 @@ namespace MLEM.Ui.Elements {
/// <summary>
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <c>SpriteBatch.Begin</c> call is also started.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="blendState">The blend state that is used for drawing</param>
/// <param name="samplerState">The sampler state that is used for drawing</param>
/// <param name="effect">The effect that is used for drawing</param>
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
/// <param name="matrix">The transformation matrix that is used for drawing</param>
[Obsolete("Use DrawTransformed that takes a SpriteBatchContext instead")]
public void DrawTransformed(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
this.DrawTransformed(time, batch, alpha, new SpriteBatchContext(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix));
}
/// <summary>
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <c>SpriteBatch.Begin</c> call is also started.
/// If <see cref="Transform"/> is set, a new <c>SpriteBatch.Begin</c> call is also started.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="context">The sprite batch context to use for drawing</param>
public void DrawTransformed(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
#pragma warning disable CS0618
var customDraw = this.BeginImpl != null || this.Transform != Matrix.Identity;
var customDraw = this.Transform != Matrix.Identity;
var transformed = context;
transformed.TransformMatrix = this.Transform * transformed.TransformMatrix;
// TODO ending and beginning again when the matrix changes isn't ideal (https://github.com/MonoGame/MonoGame/issues/3156)
@ -1112,12 +1074,9 @@ namespace MLEM.Ui.Elements {
// begin our own draw call
batch.Begin(transformed);
}
#pragma warning restore CS0618
// draw content in custom begin call
#pragma warning disable CS0618
this.Draw(time, batch, alpha, transformed.BlendState, transformed.SamplerState, transformed.DepthStencilState, transformed.Effect, transformed.TransformMatrix);
#pragma warning restore CS0618
this.Draw(time, batch, alpha, transformed);
if (this.System != null)
this.System.Metrics.Draws++;
@ -1129,23 +1088,6 @@ namespace MLEM.Ui.Elements {
}
}
/// <summary>
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has already been called with custom <see cref="Transform"/> etc. applied.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="blendState">The blend state that is used for drawing</param>
/// <param name="samplerState">The sampler state that is used for drawing</param>
/// <param name="effect">The effect that is used for drawing</param>
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
/// <param name="matrix">The transformation matrix that is used for drawing</param>
[Obsolete("Use Draw that takes a SpriteBatchContext instead")]
public virtual void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
this.Draw(time, batch, alpha, new SpriteBatchContext(SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, null, effect, matrix));
}
/// <summary>
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has already been called with custom <see cref="Transform"/> etc. applied.
@ -1159,33 +1101,9 @@ namespace MLEM.Ui.Elements {
if (this.IsSelected)
this.System.InvokeOnSelectedElementDrawn(this, time, batch, alpha, context);
foreach (var child in this.GetRelevantChildren()) {
if (!child.IsHidden) {
#pragma warning disable CS0618
child.DrawTransformed(time, batch, alpha * child.DrawAlpha, context.BlendState, context.SamplerState, context.DepthStencilState, context.Effect, context.TransformMatrix);
#pragma warning restore CS0618
}
}
}
/// <summary>
/// Draws this element and all of its <see cref="GetRelevantChildren"/> early.
/// Drawing early involves drawing onto <see cref="RenderTarget2D"/> instances rather than onto the screen.
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has not yet been called.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
/// <param name="alpha">The alpha to draw this element and its children with</param>
/// <param name="blendState">The blend state that is used for drawing</param>
/// <param name="samplerState">The sampler state that is used for drawing</param>
/// <param name="effect">The effect that is used for drawing</param>
/// <param name="depthStencilState">The depth stencil state that is used for drawing</param>
/// <param name="matrix">The transformation matrix that is used for drawing</param>
[Obsolete("DrawEarly is deprecated. For custom implementations, see Panel.Draw for how to replace this method.")]
public virtual void DrawEarly(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix) {
foreach (var child in this.GetRelevantChildren()) {
if (!child.IsHidden)
child.DrawEarly(time, batch, alpha * child.DrawAlpha, blendState, samplerState, depthStencilState, effect, matrix);
child.DrawTransformed(time, batch, alpha * child.DrawAlpha, context);
}
}
@ -1234,13 +1152,6 @@ namespace MLEM.Ui.Elements {
return false;
}
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
[Obsolete("Dispose will be removed in a future update. To unregister custom event handlers, use OnRemovedFromUi instead.")]
public virtual void Dispose() {
this.OnDisposed?.Invoke(this);
GC.SuppressFinalize(this);
}
/// <inheritdoc />
public override string ToString() {
var ret = this.GetType().Name;
@ -1418,20 +1329,5 @@ namespace MLEM.Ui.Elements {
/// <param name="usualNext">The element that is considered to be the next element by default</param>
public delegate Element GamepadNextElementCallback(Direction2 dir, Element usualNext);
/// <summary>
/// A delegate method used for <see cref="BeginImpl"/>
/// </summary>
/// <param name="element">The custom draw group</param>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch used for drawing</param>
/// <param name="alpha">This element's draw alpha</param>
/// <param name="blendState">The blend state used for drawing</param>
/// <param name="samplerState">The sampler state used for drawing</param>
/// <param name="effect">The effect used for drawing</param>
/// <param name="depthStencilState">The depth stencil state used for drawing</param>
/// <param name="matrix">The transform matrix used for drawing</param>
[Obsolete("BeginDelegate is deprecated. You can create a custom element class and override Draw instead.")]
public delegate void BeginDelegate(Element element, GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, Effect effect, Matrix matrix);
}
}

View file

@ -80,11 +80,6 @@ namespace MLEM.Ui.Elements {
}
}
/// <summary>
/// The paragraph of text that this tooltip displays
/// </summary>
[Obsolete("Use Paragraphs instead, which allows for multiple paragraphs to be managed by one tooltip")]
public Paragraph Paragraph;
/// <summary>
/// Determines whether this tooltip should display when <see cref="UiControls.IsAutoNavMode"/> is true, which is when the UI is being controlled using a keyboard or gamepad.
/// If this tooltip is displayed in auto-nav mode, it will display below the selected element with the <see cref="AutoNavOffset"/> applied.
@ -115,11 +110,8 @@ namespace MLEM.Ui.Elements {
/// <param name="elementToHover">The element that should automatically cause the tooltip to appear and disappear when hovered and not hovered, respectively</param>
public Tooltip(string text = null, Element elementToHover = null) :
base(Anchor.TopLeft, Vector2.One, Vector2.Zero) {
if (text != null) {
#pragma warning disable CS0618
this.Paragraph = this.AddParagraph(text);
#pragma warning restore CS0618
}
if (text != null)
this.AddParagraph(text);
this.Init(elementToHover);
}
@ -130,9 +122,7 @@ namespace MLEM.Ui.Elements {
/// <param name="elementToHover">The element that should automatically cause the tooltip to appear and disappear when hovered and not hovered, respectively</param>
public Tooltip(Paragraph.TextCallback textCallback, Element elementToHover = null) :
base(Anchor.TopLeft, Vector2.One, Vector2.Zero) {
#pragma warning disable CS0618
this.Paragraph = this.AddParagraph(textCallback);
#pragma warning restore CS0618
this.AddParagraph(textCallback);
this.Init(elementToHover);
}
@ -326,12 +316,6 @@ namespace MLEM.Ui.Elements {
private void UpdateParagraphsStyles() {
foreach (var paragraph in this.Paragraphs)
this.UpdateParagraphStyle(paragraph);
#pragma warning disable CS0618
// still set style here in case someone changed the paragraph field manually
if (this.Paragraph != null)
this.UpdateParagraphStyle(this.Paragraph);
#pragma warning restore CS0618
}
private void UpdateParagraphStyle(Paragraph paragraph) {

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using MLEM.Ui.Elements;
@ -9,7 +8,7 @@ namespace MLEM.Ui.Style {
/// Note that <c>T</c> implicitly converts to <c>StyleProp{T}</c> and vice versa.
/// </summary>
/// <typeparam name="T">The type of style setting that this property stores</typeparam>
public readonly struct StyleProp<T> : IEquatable<StyleProp<T>> {
public readonly struct StyleProp<T> {
/// <summary>
/// The empty style property, with no <see cref="Value"/> and a priority of 0.
@ -72,31 +71,6 @@ namespace MLEM.Ui.Style {
return !EqualityComparer<T>.Default.Equals(this.Value, default);
}
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other">other</paramref> parameter; otherwise, false.</returns>
[Obsolete("StyleProp equality is ambiguous as it is not clear whether priority is taken into account. Compare Values instead.")]
public bool Equals(StyleProp<T> other) {
return EqualityComparer<T>.Default.Equals(this.Value, other.Value);
}
/// <summary>Indicates whether this instance and a specified object are equal.</summary>
/// <param name="obj">The object to compare with the current instance.</param>
/// <returns>true if <paramref name="obj">obj</paramref> and this instance are the same type and represent the same value; otherwise, false.</returns>
[Obsolete("StyleProp equality is ambiguous as it is not clear whether priority is taken into account. Compare Values instead.")]
#pragma warning disable CS0809
public override bool Equals(object obj) {
return obj is StyleProp<T> other && this.Equals(other);
}
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
[Obsolete("StyleProp equality is ambiguous as it is not clear whether priority is taken into account. Compare Values instead.")]
public override int GetHashCode() {
return EqualityComparer<T>.Default.GetHashCode(this.Value);
}
#pragma warning restore CS0809
/// <summary>Returns the fully qualified type name of this instance.</summary>
/// <returns>The fully qualified type name.</returns>
public override string ToString() {
@ -121,27 +95,5 @@ namespace MLEM.Ui.Style {
return new StyleProp<T>(prop);
}
/// <summary>
/// Compares the two style properties and returns whether they are equal using <see cref="Equals(MLEM.Ui.Style.StyleProp{T})"/>.
/// </summary>
/// <param name="left">The left style property.</param>
/// <param name="right">The right style property.</param>
/// <returns>Whether the two style properties are equal.</returns>
[Obsolete("StyleProp equality is ambiguous as it is not clear whether priority is taken into account. Compare Values instead.")]
public static bool operator ==(StyleProp<T> left, StyleProp<T> right) {
return left.Equals(right);
}
/// <summary>
/// Compares the two style properties and returns whether they are not equal using <see cref="Equals(MLEM.Ui.Style.StyleProp{T})"/>.
/// </summary>
/// <param name="left">The left style property.</param>
/// <param name="right">The right style property.</param>
/// <returns>Whether the two style properties are not equal.</returns>
[Obsolete("StyleProp equality is ambiguous as it is not clear whether priority is taken into account. Compare Values instead.")]
public static bool operator !=(StyleProp<T> left, StyleProp<T> right) {
return !left.Equals(right);
}
}
}

View file

@ -76,29 +76,6 @@ namespace MLEM.Ui {
/// </summary>
public float DrawAlpha = 1;
/// <summary>
/// The blend state that this ui system and all of its elements draw with
/// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public BlendState BlendState;
/// <summary>
/// The sampler state that this ui system and all of its elements draw with.
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp"/>, as that is the one that works best with pixel graphics.
/// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public SamplerState SamplerState;
/// <summary>
/// The depth stencil state that this ui system and all of its elements draw with.
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.DepthStencilState.None"/>, which is also the default for <c>SpriteBatch.Begin</c>.
/// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public DepthStencilState DepthStencilState;
/// <summary>
/// The effect that this ui system and all of its elements draw with.
/// The default is null, which means that no custom effect will be used.
/// </summary>
[Obsolete("Set this through SpriteBatchContext instead")]
public Effect Effect;
/// <summary>
/// The spriteb atch context that this ui system and all of its elements should draw with.
/// The default <see cref="MLEM.Graphics.SpriteBatchContext.SamplerState"/> is <see cref="Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp"/>, as that is the one that works best with pixel graphics.
/// </summary>
@ -279,27 +256,6 @@ namespace MLEM.Ui {
this.Metrics.UpdateTime += this.stopwatch.Elapsed;
}
/// <summary>
/// Draws any <see cref="Panel"/> and other elements that draw onto <see cref="RenderTarget2D"/> rather than directly onto the screen.
/// For drawing in this manner to work correctly, this method has to be called before your <see cref="GraphicsDevice"/> is cleared, and before everything else in your game is drawn.
/// </summary>
/// <param name="time">The game's time</param>
/// <param name="batch">The sprite batch to use for drawing</param>
[Obsolete("DrawEarly is deprecated. Calling it is not required anymore, and there is no replacement.")]
public void DrawEarly(GameTime time, SpriteBatch batch) {
this.Metrics.ResetDraws();
this.stopwatch.Restart();
foreach (var root in this.rootElements) {
if (!root.Element.IsHidden)
root.Element.DrawEarly(time, batch, this.DrawAlpha * root.Element.DrawAlpha, this.BlendState, this.SamplerState, this.DepthStencilState, this.Effect, root.Transform);
}
this.stopwatch.Stop();
this.Metrics.DrawTime += this.stopwatch.Elapsed;
this.drewEarly = true;
}
/// <summary>
/// Draws any <see cref="Element"/>s onto the screen.
/// </summary>
@ -316,21 +272,8 @@ namespace MLEM.Ui {
var context = this.SpriteBatchContext;
context.TransformMatrix = root.Transform * context.TransformMatrix;
#pragma warning disable CS0618
if (this.BlendState != null)
context.BlendState = this.BlendState;
if (this.SamplerState != null)
context.SamplerState = this.SamplerState;
if (this.DepthStencilState != null)
context.DepthStencilState = this.DepthStencilState;
if (this.Effect != null)
context.Effect = this.Effect;
#pragma warning restore CS0618
batch.Begin(context);
#pragma warning disable CS0618
root.Element.DrawTransformed(time, batch, this.DrawAlpha * root.Element.DrawAlpha, context.BlendState, context.SamplerState, context.DepthStencilState, context.Effect, context.TransformMatrix);
#pragma warning restore CS0618
root.Element.DrawTransformed(time, batch, this.DrawAlpha * root.Element.DrawAlpha, context);
batch.End();
}

View file

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
namespace MLEM.Extensions {
/// <summary>
/// A set of extensions for dealing with <see cref="char"/>
/// </summary>
[Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching, or CodePointSource.ToString for UTF-32 caching.")]
public static class CharExtensions {
private static readonly Dictionary<char, string> Cache = new Dictionary<char, string>();
/// <summary>
/// Returns the string representation of this character which will be stored and retrieved from a dictionary cache.
/// This method reduces string allocations, making it trade in processor efficiency for memory efficiency.
/// </summary>
/// <param name="c">The character to turn into a string</param>
/// <returns>A string representing the character</returns>
[Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching, or CodePointSource.ToString for UTF-32 caching.")]
public static string ToCachedString(this char c) {
if (!CharExtensions.Cache.TryGetValue(c, out var ret)) {
ret = c.ToString();
CharExtensions.Cache.Add(c, ret);
}
return ret;
}
}
}

View file

@ -21,9 +21,6 @@ namespace MLEM.Font {
/// Whereas a regular <see cref="SpriteFont"/> would have to explicitly support this character for width calculations, generic fonts implicitly support it in <see cref="MeasureString(string,bool)"/>.
/// </summary>
public const char Emsp = '\u2003';
/// <inheritdoc cref="Emsp"/>
[Obsolete("Use the Emsp field instead.")]
public const char OneEmSpace = GenericFont.Emsp;
/// <summary>
/// This field holds the unicode representation of a non-breaking space.
/// Whereas a regular <see cref="SpriteFont"/> would have to explicitly support this character for width calculations, generic fonts implicitly support it in <see cref="MeasureString(string,bool)"/>.

View file

@ -80,17 +80,6 @@ namespace MLEM.Formatting.Codes {
/// <param name="time">The game's time</param>
public virtual void Update(GameTime time) {}
/// <summary>
/// Returns the string that this formatting code should be replaced with.
/// Usually, you'll just want an empty string here, but some formatting codes (like <see cref="ImageCode"/>) require their space to be filled by spaces.
/// </summary>
/// <param name="font">The font that is used</param>
/// <returns>The replacement string for this formatting code</returns>
[Obsolete("This method is deprecated. Use GetSelfWidth to add additional width to this code and DrawSelf or DrawCharacter to draw additional items.")]
public virtual string GetReplacementString(GenericFont font) {
return string.Empty;
}
/// <inheritdoc cref="Formatting.Token.DrawCharacter"/>
public virtual bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) {
return false;

View file

@ -169,14 +169,14 @@ namespace MLEM.Formatting {
// if we've reached the end of the string
if (next == null) {
var sub = s.Substring(rawIndex, s.Length - rawIndex);
tokens.Add(new Token(applied.ToArray(), index, rawIndex, TextFormatter.StripFormatting(font, sub, applied), sub));
tokens.Add(new Token(applied.ToArray(), index, rawIndex, TextFormatter.StripFormatting(sub, applied.Select(c => c.Regex)), sub));
break;
}
allCodes.Add(next);
// create a new token for the content up to the next code
var ret = s.Substring(rawIndex, next.Match.Index - rawIndex);
var strippedRet = TextFormatter.StripFormatting(font, ret, applied);
var strippedRet = TextFormatter.StripFormatting(ret, applied.Select(c => c.Regex));
tokens.Add(new Token(applied.ToArray(), index, rawIndex, strippedRet, ret));
// move to the start of the next code
@ -187,7 +187,7 @@ namespace MLEM.Formatting {
applied.RemoveAll(c => c.EndsHere(next) || next.EndsOther(c));
applied.Add(next);
}
return new TokenizedString(font, alignment, s, TextFormatter.StripFormatting(font, s, allCodes), tokens.ToArray(), allCodes.ToArray());
return new TokenizedString(font, alignment, s, TextFormatter.StripFormatting(s, allCodes.Select(c => c.Regex)), tokens.ToArray(), allCodes.ToArray());
}
/// <summary>
@ -224,9 +224,7 @@ namespace MLEM.Formatting {
/// <param name="s">The string to strip formatting codes from.</param>
/// <returns>The stripped string.</returns>
public string StripAllFormatting(string s) {
foreach (var regex in this.Codes.Keys)
s = regex.Replace(s, string.Empty);
return s;
return TextFormatter.StripFormatting(s, this.Codes.Keys);
}
private Code GetNextCode(string s, int index, int maxIndex = int.MaxValue) {
@ -238,14 +236,9 @@ namespace MLEM.Formatting {
return constructor?.Invoke(this, match, regex);
}
private static string StripFormatting(GenericFont font, string s, IEnumerable<Code> codes) {
foreach (var code in codes) {
#pragma warning disable CS0618
// this can be combined with StripAllFormatting (which was added after GetReplacementString was deprecated) once GetReplacementString is removed
// (just make this method accept a set of regular expressions, and then call it with all code keys in StripAllFormatting, and the applied codes' regexes in Tokenize)
s = code.Regex.Replace(s, code.GetReplacementString(font));
#pragma warning restore CS0618
}
private static string StripFormatting(string s, IEnumerable<Regex> codes) {
foreach (var code in codes)
s = code.Replace(s, string.Empty);
return s;
}

View file

@ -137,12 +137,6 @@ namespace MLEM.Formatting {
}
}
/// <inheritdoc cref="GenericFont.MeasureString(string,bool)"/>
[Obsolete("Measure is deprecated. Use GetArea, which returns the string's total size measurement, instead.")]
public Vector2 Measure(GenericFont font) {
return this.GetArea().Size;
}
/// <summary>
/// Measures the area that this entire tokenized string and all of its <see cref="Tokens"/> take up and returns it as a <see cref="RectangleF"/>.
/// </summary>

View file

@ -84,12 +84,12 @@ namespace MLEM.Input {
public bool HandleGamepadRepeats = true;
/// <summary>
/// This field represents the deadzone that gamepad <see cref="Buttons"/> have when input is queried for them using this input handler.
/// A deadzone is the percentage (between 0 and 1) that an analog value has to exceed for it to be considered down (<see cref="IsGamepadButtonDown"/>) or pressed (<see cref="IsGamepadButtonPressed"/>).
/// A deadzone is the percentage (between 0 and 1) that an analog value has to exceed for it to be considered down (<see cref="IsDown"/>) or pressed (<see cref="IsPressed"/>).
/// Querying of analog values is done using <see cref="GamepadExtensions.GetAnalogValue"/>.
/// </summary>
public float GamepadButtonDeadzone;
/// <summary>
/// Set this field to true to invert the press behavior of <see cref="IsKeyPressed"/>, <see cref="IsMouseButtonPressed"/>, <see cref="IsGamepadButtonPressed"/> and <see cref="IsPressed"/>.
/// Set this field to true to invert the press behavior of <see cref="IsPressed"/>.
/// Inverted behavior means that, instead of an input counting as pressed when it was up in the last frame and is now down, it will be counted as pressed when it was down in the last frame and is now up.
/// </summary>
public bool InvertPressBehavior;
@ -414,287 +414,6 @@ namespace MLEM.Input {
}
return false;
}
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyDown"/>
[Obsolete("This method is deprecated. Use the GenericInput version IsDown instead.")]
public bool IsKeyDown(Keys key) {
return this.KeyboardState.IsKeyDown(key);
}
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyUp"/>
[Obsolete("This method is deprecated. Use the GenericInput version IsUp instead.")]
public bool IsKeyUp(Keys key) {
return this.KeyboardState.IsKeyUp(key);
}
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyDown"/>
[Obsolete("This method is deprecated. Use the GenericInput version WasDown instead.")]
public bool WasKeyDown(Keys key) {
return this.LastKeyboardState.IsKeyDown(key);
}
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyUp"/>
[Obsolete("This method is deprecated. Use the GenericInput version WasUp instead.")]
public bool WasKeyUp(Keys key) {
return this.LastKeyboardState.IsKeyUp(key);
}
/// <summary>
/// Returns whether the given key is considered pressed.
/// A key is considered pressed if it was not down the last update call, but is down the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
/// If <see cref="HandleKeyboardRepeats"/> is true, this method will also return true to signify a key repeat.
/// </summary>
/// <param name="key">The key to query</param>
/// <returns>If the key is pressed</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressed instead.")]
public bool IsKeyPressed(Keys key) {
// if the queried key is the held key and a repeat should be triggered, return true
if (this.HandleKeyboardRepeats && key == this.heldKey && this.triggerKeyRepeat)
return true;
return this.IsKeyPressedIgnoreRepeats(key);
}
/// <summary>
/// Returns whether the given key is considered pressed.
/// A key is considered pressed if it was not down the last update call, but is down the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
/// This has the same behavior as <see cref="IsKeyPressed"/>, but ignores keyboard repeat events.
/// If <see cref="HandleKeyboardRepeats"/> is false, this method does the same as <see cref="IsKeyPressed"/>.
/// </summary>
/// <param name="key">The key to query</param>
/// <returns>If the key is pressed</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressedIgnoreRepeats instead.")]
public bool IsKeyPressedIgnoreRepeats(Keys key) {
if (this.InvertPressBehavior)
return this.WasKeyDown(key) && this.IsKeyUp(key);
return this.WasKeyUp(key) && this.IsKeyDown(key);
}
/// <summary>
/// Returns if the given key is considered pressed, and if the press has not been consumed yet using <see cref="TryConsumeKeyPressed"/>.
/// </summary>
/// <param name="key">The key to query.</param>
/// <returns>If the key is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressedAvailable instead.")]
public bool IsKeyPressedAvailable(Keys key) {
return this.IsKeyPressed(key) && !this.IsPressConsumed(key);
}
/// <summary>
/// Returns whether the given key is considered pressed, and marks the press as consumed if it is.
/// A key is considered pressed if it was not down the last update call, but is down the current update call.
/// A key press is considered consumed if this method has already returned true previously since the last <see cref="Update()"/> call.
/// If <see cref="HandleKeyboardRepeats"/> is true, this method will also return true to signify a key repeat.
/// </summary>
/// <param name="key">The key to query.</param>
/// <returns>If the key is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version TryConsumePressed instead.")]
public bool TryConsumeKeyPressed(Keys key) {
if (this.IsKeyPressedAvailable(key)) {
this.consumedPresses.Add((key, -1));
return true;
}
return false;
}
/// <summary>
/// Returns whether the given mouse button is currently down.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button is down</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsDown instead.")]
public bool IsMouseButtonDown(MouseButton button) {
return this.MouseState.GetState(button) == ButtonState.Pressed;
}
/// <summary>
/// Returns whether the given mouse button is currently up.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button is up</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsUp instead.")]
public bool IsMouseButtonUp(MouseButton button) {
return this.MouseState.GetState(button) == ButtonState.Released;
}
/// <summary>
/// Returns whether the given mouse button was down the last update call.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button was down</returns>
[Obsolete("This method is deprecated. Use the GenericInput version WasDown instead.")]
public bool WasMouseButtonDown(MouseButton button) {
return this.LastMouseState.GetState(button) == ButtonState.Pressed;
}
/// <summary>
/// Returns whether the given mouse button was up the last update call.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button was up</returns>
[Obsolete("This method is deprecated. Use the GenericInput version WasUp instead.")]
public bool WasMouseButtonUp(MouseButton button) {
return this.LastMouseState.GetState(button) == ButtonState.Released;
}
/// <summary>
/// Returns whether the given mouse button is considered pressed.
/// A mouse button is considered pressed if it was up the last update call, and is down the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether the button is pressed</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressed instead.")]
public bool IsMouseButtonPressed(MouseButton button) {
if (this.InvertPressBehavior)
return this.WasMouseButtonDown(button) && this.IsMouseButtonUp(button);
return this.WasMouseButtonUp(button) && this.IsMouseButtonDown(button);
}
/// <summary>
/// Returns if the given mouse button is considered pressed, and if the press has not been consumed yet using <see cref="TryConsumeMouseButtonPressed"/>.
/// </summary>
/// <param name="button">The button to query.</param>
/// <returns>If the button is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressedAvailable instead.")]
public bool IsMouseButtonPressedAvailable(MouseButton button) {
return this.IsMouseButtonPressed(button) && !this.IsPressConsumed(button);
}
/// <summary>
/// Returns whether the given mouse button is considered pressed, and marks the press as consumed if it is.
/// A mouse button is considered pressed if it was up the last update call, and is down the current update call.
/// A mouse button press is considered consumed if this method has already returned true previously since the last <see cref="Update()"/> call.
/// </summary>
/// <param name="button">The button to query.</param>
/// <returns>If the button is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version TryConsumePressed instead.")]
public bool TryConsumeMouseButtonPressed(MouseButton button) {
if (this.IsMouseButtonPressedAvailable(button)) {
this.consumedPresses.Add((button, -1));
return true;
}
return false;
}
/// <inheritdoc cref="GamePadState.IsButtonDown"/>
[Obsolete("This method is deprecated. Use the GenericInput version IsDown instead.")]
public bool IsGamepadButtonDown(Buttons button, int index = -1) {
if (index < 0) {
for (var i = 0; i < this.ConnectedGamepads; i++) {
if (this.GetGamepadState(i).GetAnalogValue(button) > this.GamepadButtonDeadzone)
return true;
}
return false;
}
return this.GetGamepadState(index).GetAnalogValue(button) > this.GamepadButtonDeadzone;
}
/// <inheritdoc cref="GamePadState.IsButtonUp"/>
[Obsolete("This method is deprecated. Use the GenericInput version IsUp instead.")]
public bool IsGamepadButtonUp(Buttons button, int index = -1) {
if (index < 0) {
for (var i = 0; i < this.ConnectedGamepads; i++) {
if (this.GetGamepadState(i).GetAnalogValue(button) <= this.GamepadButtonDeadzone)
return true;
}
return false;
}
return this.GetGamepadState(index).GetAnalogValue(button) <= this.GamepadButtonDeadzone;
}
/// <inheritdoc cref="GamePadState.IsButtonDown"/>
[Obsolete("This method is deprecated. Use the GenericInput version WasDown instead.")]
public bool WasGamepadButtonDown(Buttons button, int index = -1) {
if (index < 0) {
for (var i = 0; i < this.ConnectedGamepads; i++) {
if (this.GetLastGamepadState(i).GetAnalogValue(button) > this.GamepadButtonDeadzone)
return true;
}
return false;
}
return this.GetLastGamepadState(index).GetAnalogValue(button) > this.GamepadButtonDeadzone;
}
/// <inheritdoc cref="GamePadState.IsButtonUp"/>
[Obsolete("This method is deprecated. Use the GenericInput version WasUp instead.")]
public bool WasGamepadButtonUp(Buttons button, int index = -1) {
if (index < 0) {
for (var i = 0; i < this.ConnectedGamepads; i++) {
if (this.GetLastGamepadState(i).GetAnalogValue(button) <= this.GamepadButtonDeadzone)
return true;
}
return false;
}
return this.GetLastGamepadState(index).GetAnalogValue(button) <= this.GamepadButtonDeadzone;
}
/// <summary>
/// Returns whether the given gamepad button on the given index is considered pressed.
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
/// If <see cref="HandleGamepadRepeats"/> is true, this method will also return true to signify a gamepad button repeat.
/// </summary>
/// <param name="button">The button to query</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad</param>
/// <returns>Whether the given button is pressed</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressed instead.")]
public bool IsGamepadButtonPressed(Buttons button, int index = -1) {
if (this.HandleGamepadRepeats) {
if (index < 0) {
for (var i = 0; i < this.ConnectedGamepads; i++) {
if (this.heldGamepadButtons[i] == button && this.triggerGamepadButtonRepeat[i])
return true;
}
} else if (this.heldGamepadButtons[index] == button && this.triggerGamepadButtonRepeat[index]) {
return true;
}
}
return this.IsGamepadButtonPressedIgnoreRepeats(button, index);
}
/// <summary>
/// Returns whether the given key is considered pressed.
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
/// This has the same behavior as <see cref="IsGamepadButtonPressed"/>, but ignores gamepad repeat events.
/// If <see cref="HandleGamepadRepeats"/> is false, this method does the same as <see cref="IsGamepadButtonPressed"/>.
/// </summary>
/// <param name="button">The button to query</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad</param>
/// <returns>Whether the given button is pressed</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressedIgnoreRepeats instead.")]
public bool IsGamepadButtonPressedIgnoreRepeats(Buttons button, int index = -1) {
if (this.InvertPressBehavior)
return this.WasGamepadButtonDown(button, index) && this.IsGamepadButtonUp(button, index);
return this.WasGamepadButtonUp(button, index) && this.IsGamepadButtonDown(button, index);
}
/// <summary>
/// Returns if the given gamepad button is considered pressed, and if the press has not been consumed yet using <see cref="TryConsumeMouseButtonPressed"/>.
/// </summary>
/// <param name="button">The button to query.</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad.</param>
/// <returns>Whether the given button is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version IsPressedAvailable instead.")]
public bool IsGamepadButtonPressedAvailable(Buttons button, int index = -1) {
return this.IsGamepadButtonPressed(button) && !this.IsPressConsumed(button, index) && (index < 0 || !this.IsPressConsumed(button));
}
/// <summary>
/// Returns whether the given gamepad button on the given index is considered pressed, and marks the press as consumed if it is.
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call.
/// A gamepad button press is considered consumed if this method has already returned true previously since the last <see cref="Update()"/> call.
/// If <see cref="HandleGamepadRepeats"/> is true, this method will also return true to signify a gamepad button repeat.
/// </summary>
/// <param name="button">The button to query.</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad.</param>
/// <returns>Whether the given button is pressed and the press is not consumed yet.</returns>
[Obsolete("This method is deprecated. Use the GenericInput version TryConsumePressed instead.")]
public bool TryConsumeGamepadButtonPressed(Buttons button, int index = -1) {
if (this.IsGamepadButtonPressedAvailable(button, index)) {
this.consumedPresses.Add((button, index));
return true;
}
return false;
}
/// <summary>
/// Queries for a gesture of a given type that finished during the current update call.
/// </summary>

View file

@ -245,42 +245,6 @@ namespace MLEM.Input {
return false;
}
/// <summary>
/// Returns the amount of time that this keybind has been held down for.
/// If this input isn't currently down, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting down time, or <see cref="TimeSpan.Zero"/> if the input is not being held.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetDownTime or custom handling instead.")]
public TimeSpan GetDownTime(InputHandler handler, int gamepadIndex = -1) {
return this.Combinations.Max(c => c.GetDownTime(handler, gamepadIndex));
}
/// <summary>
/// Returns the amount of time that this keybind has been up for since the last time it was down.
/// If this input isn't currently up, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting up time, or <see cref="TimeSpan.Zero"/> if the input is being held.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetUpTime or custom handling instead.")]
public TimeSpan GetUpTime(InputHandler handler, int gamepadIndex = -1) {
return this.Combinations.Min(c => c.GetUpTime(handler, gamepadIndex));
}
/// <summary>
/// Returns the amount of time that has passed since this keybind last counted as pressed.
/// If this input hasn't been pressed previously, or is currently pressed, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting up time, or <see cref="TimeSpan.Zero"/> if the input has never been pressed, or is currently pressed.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetTimeSincePress or custom handling instead.")]
public TimeSpan GetTimeSincePress(InputHandler handler, int gamepadIndex = -1) {
return this.Combinations.Min(c => c.GetTimeSincePress(handler, gamepadIndex));
}
/// <summary>
/// Returns an enumerable of all of the combinations that this keybind currently contains
/// </summary>
@ -502,41 +466,6 @@ namespace MLEM.Input {
return true;
}
/// <summary>
/// Returns the amount of time that this combination has been held down for.
/// If this input isn't currently down, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting down time, or <see cref="TimeSpan.Zero"/> if the input is not being held.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetDownTime or custom handling instead.")]
public TimeSpan GetDownTime(InputHandler handler, int gamepadIndex = -1) {
return handler.GetDownTime(this.Key, gamepadIndex);
}
/// <summary>
/// Returns the amount of time that this combination has been up for since the last time it was down.
/// If this input isn't currently up, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting up time, or <see cref="TimeSpan.Zero"/> if the input is being held.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetUpTime or custom handling instead.")]
public TimeSpan GetUpTime(InputHandler handler, int gamepadIndex = -1) {
return handler.GetUpTime(this.Key, gamepadIndex);
}
/// <summary>
/// Returns the amount of time that has passed since this combination last counted as pressed.
/// If this input hasn't been pressed previously, or is currently pressed, this method returns <see cref="TimeSpan.Zero"/>.
/// </summary>
/// <param name="handler">The input handler to query the keys with</param>
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
/// <returns>The resulting up time, or <see cref="TimeSpan.Zero"/> if the input has never been pressed, or is currently pressed.</returns>
[Obsolete("This method is deprecated, as it does not query Modifiers or InverseModifiers. Use InputHandler.GetTimeSincePress or custom handling instead.")]
public TimeSpan GetTimeSincePress(InputHandler handler, int gamepadIndex = -1) {
return handler.GetTimeSincePress(this.Key, gamepadIndex);
}
/// <summary>
/// Converts this combination into an easily human-readable string.

View file

@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;
namespace MLEM.Misc {
/// <summary>
/// A helper class that allows easier usage of <see cref="Enum"/> values.
/// </summary>
[Obsolete("EnumHelper has been moved into the DynamicEnums library: https://www.nuget.org/packages/DynamicEnums")]
public static class EnumHelper {
/// <summary>
/// All values of the <see cref="Buttons"/> enum.
/// </summary>
[Obsolete("This field has been moved to InputHandler.AllButtons")]
public static readonly Buttons[] Buttons = EnumHelper.GetValues<Buttons>();
/// <summary>
/// All values of the <see cref="Keys"/> enum.
/// </summary>
[Obsolete("This field has been moved to InputHandler.AllKeys")]
public static readonly Keys[] Keys = EnumHelper.GetValues<Keys>();
/// <summary>
/// Returns an array containing all of the values of the given enum type.
/// Note that this method is a version-independent equivalent of .NET 5's <c>Enum.GetValues&lt;TEnum&gt;</c>.
/// </summary>
/// <typeparam name="T">The type whose enum to get</typeparam>
/// <returns>An enumerable of the values of the enum, in declaration order.</returns>
public static T[] GetValues<T>() where T : struct, Enum {
#if NET6_0_OR_GREATER
return Enum.GetValues<T>();
#else
return (T[]) Enum.GetValues(typeof(T));
#endif
}
/// <summary>
/// Returns all of the defined values from the given enum type <typeparamref name="T"/> which are contained in <paramref name="combinedFlag"/>.
/// Note that, if combined flags are defined in <typeparamref name="T"/>, and <paramref name="combinedFlag"/> contains them, they will also be returned.
/// </summary>
/// <param name="combinedFlag">The combined flags whose individual flags to return.</param>
/// <param name="includeZero">Whether the enum value 0 should also be returned, if <typeparamref name="T"/> contains one.</param>
/// <typeparam name="T">The type of enum.</typeparam>
/// <returns>All of the flags that make up <paramref name="combinedFlag"/>.</returns>
public static IEnumerable<T> GetFlags<T>(T combinedFlag, bool includeZero = true) where T : struct, Enum {
foreach (var flag in EnumHelper.GetValues<T>()) {
if (combinedFlag.HasFlag(flag) && (includeZero || Convert.ToInt64(flag) != 0))
yield return flag;
}
}
/// <summary>
/// Returns all of the defined unique flags from the given enum type <typeparamref name="T"/> which are contained in <paramref name="combinedFlag"/>.
/// Any combined flags (flags that aren't powers of two) which are defined in <typeparamref name="T"/> will not be returned.
/// </summary>
/// <param name="combinedFlag">The combined flags whose individual flags to return.</param>
/// <typeparam name="T">The type of enum.</typeparam>
/// <returns>All of the unique flags that make up <paramref name="combinedFlag"/>.</returns>
public static IEnumerable<T> GetUniqueFlags<T>(T combinedFlag) where T : struct, Enum {
var uniqueFlag = 1;
foreach (var flag in EnumHelper.GetValues<T>()) {
var flagValue = Convert.ToInt64(flag);
// GetValues is always ordered by binary value, so we can be sure that the next flag is bigger than the last
while (uniqueFlag < flagValue)
uniqueFlag <<= 1;
if (flagValue == uniqueFlag && combinedFlag.HasFlag(flag))
yield return flag;
}
}
}
}

View file

@ -12,12 +12,6 @@ namespace MLEM.Misc {
private static readonly string[] EmptyStrings = new string[0];
private Dictionary<string, object> data;
/// <inheritdoc />
[Obsolete("This method will be removed in a future update in favor of the generic SetData<T>.")]
public void SetData(string key, object data) {
this.SetData<object>(key, data);
}
/// <inheritdoc />
public void SetData<T>(string key, T data) {
if (EqualityComparer<T>.Default.Equals(data, default)) {
@ -52,14 +46,6 @@ namespace MLEM.Misc {
/// </summary>
public interface IGenericDataHolder {
/// <summary>
/// Store a piece of generic data on this object.
/// </summary>
/// <param name="key">The key to store the data by</param>
/// <param name="data">The data to store in the object</param>
[Obsolete("This method will be removed in a future update in favor of the generic SetData<T>.")]
void SetData(string key, object data);
/// <summary>
/// Store a piece of generic data on this object.
/// </summary>