mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-24 21:48:35 +01:00
Compare commits
3 commits
6ff2c1c1cc
...
e40d97c45e
Author | SHA1 | Date | |
---|---|---|---|
e40d97c45e | |||
2be39a740e | |||
d05262e8a6 |
9 changed files with 62 additions and 11 deletions
|
@ -15,6 +15,7 @@ Additions
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Exposed Camera's RoundPosition
|
- Exposed Camera's RoundPosition
|
||||||
|
- Exposed the epsilon value used by Camera
|
||||||
|
|
||||||
### MLEM.Ui
|
### MLEM.Ui
|
||||||
Additions
|
Additions
|
||||||
|
@ -23,6 +24,7 @@ Additions
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Cache TokenizedString inner offsets for non-Left text alignments to improve performance
|
- Cache TokenizedString inner offsets for non-Left text alignments to improve performance
|
||||||
|
- Exposed the epsilon value used by Element calculations
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed VerticalSpace height parameter being an integer
|
- Fixed VerticalSpace height parameter being an integer
|
||||||
|
|
|
@ -100,8 +100,7 @@ namespace MLEM.Data.Content {
|
||||||
continue;
|
continue;
|
||||||
if (!type.IsSubclassOf(typeof(RawContentReader)))
|
if (!type.IsSubclassOf(typeof(RawContentReader)))
|
||||||
continue;
|
continue;
|
||||||
var inst = type.GetConstructor(Type.EmptyTypes).Invoke(null);
|
ret.Add((RawContentReader) Activator.CreateInstance(type));
|
||||||
ret.Add((RawContentReader) inst);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new NotSupportedException($"The type {type} cannot be constructed by a RawContentManager. Does it have a visible parameterless constructor?", e);
|
throw new NotSupportedException($"The type {type} cannot be constructed by a RawContentManager. Does it have a visible parameterless constructor?", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -322,8 +323,7 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DynamicEnum Construct(Type type, string name, BigInteger value) {
|
private static DynamicEnum Construct(Type type, string name, BigInteger value) {
|
||||||
var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new[] {typeof(string), typeof(BigInteger)}, null);
|
return (DynamicEnum) Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] {name, value}, CultureInfo.InvariantCulture);
|
||||||
return (DynamicEnum) constructor.Invoke(new object[] {name, value});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Storage {
|
private class Storage {
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace MLEM.Data.Json {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly JsonConverter[] Converters = typeof(JsonConverters).Assembly.GetExportedTypes()
|
public static readonly JsonConverter[] Converters = typeof(JsonConverters).Assembly.GetExportedTypes()
|
||||||
.Where(t => t.IsSubclassOf(typeof(JsonConverter)) && !t.IsGenericType)
|
.Where(t => t.IsSubclassOf(typeof(JsonConverter)) && !t.IsGenericType)
|
||||||
.Select(t => t.GetConstructor(Type.EmptyTypes).Invoke(null)).Cast<JsonConverter>().ToArray();
|
.Select(Activator.CreateInstance).Cast<JsonConverter>().ToArray();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds all of the <see cref="JsonConverter"/> objects that are part of MLEM.Data to the given <see cref="JsonSerializer"/>
|
/// Adds all of the <see cref="JsonConverter"/> objects that are part of MLEM.Data to the given <see cref="JsonSerializer"/>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Logo.png</PackageIcon>
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -18,6 +18,12 @@ namespace MLEM.Ui.Elements {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Element : GenericDataHolder, IDisposable {
|
public abstract class Element : GenericDataHolder, IDisposable {
|
||||||
|
|
||||||
|
/// <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.
|
||||||
|
/// If ui elements used are extremely small or extremely large, this value can be reduced or increased.
|
||||||
|
/// </summary>
|
||||||
|
public static float Epsilon = 0.01F;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of all of this element's direct children.
|
/// A list of all of this element's direct children.
|
||||||
/// Use <see cref="AddChild{T}"/> or <see cref="RemoveChild"/> to manipulate this list while calling all of the necessary callbacks.
|
/// Use <see cref="AddChild{T}"/> or <see cref="RemoveChild"/> to manipulate this list while calling all of the necessary callbacks.
|
||||||
|
@ -607,9 +613,9 @@ namespace MLEM.Ui.Elements {
|
||||||
break;
|
break;
|
||||||
case Anchor.AutoInline:
|
case Anchor.AutoInline:
|
||||||
var newX = prevArea.Right + this.ScaledOffset.X;
|
var newX = prevArea.Right + this.ScaledOffset.X;
|
||||||
// with awkward ui scale values, floating point rounding can cause an element that would usually be
|
// with awkward ui scale values, floating point rounding can cause an element that would usually
|
||||||
// positioned correctly to be pushed into the next line due to a very small deviation, so we add 0.01 here
|
// be positioned correctly to be pushed into the next line due to a very small deviation
|
||||||
if (newX + newSize.X <= parentArea.Right + 0.01F) {
|
if (newX + newSize.X <= parentArea.Right + Epsilon) {
|
||||||
pos.X = newX;
|
pos.X = newX;
|
||||||
pos.Y = prevArea.Y + this.ScaledOffset.Y;
|
pos.Y = prevArea.Y + this.ScaledOffset.Y;
|
||||||
} else {
|
} else {
|
||||||
|
@ -676,7 +682,7 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to leave some leeway to prevent float rounding causing an infinite loop
|
// we want to leave some leeway to prevent float rounding causing an infinite loop
|
||||||
if (!autoSize.Equals(this.UnscrolledArea.Size, 0.01F)) {
|
if (!autoSize.Equals(this.UnscrolledArea.Size, Epsilon)) {
|
||||||
recursion++;
|
recursion++;
|
||||||
if (recursion >= 16) {
|
if (recursion >= 16) {
|
||||||
throw new ArithmeticException($"The area of {this} with root {this.Root.Name} has recursively updated too often. Does its child {foundChild} contain any conflicting auto-sizing settings?");
|
throw new ArithmeticException($"The area of {this} with root {this.Root.Name} has recursively updated too often. Does its child {foundChild} contain any conflicting auto-sizing settings?");
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace MLEM.Ui.Elements {
|
||||||
// force current value to be clamped
|
// force current value to be clamped
|
||||||
this.CurrentValue = this.CurrentValue;
|
this.CurrentValue = this.CurrentValue;
|
||||||
// auto-hide if necessary
|
// auto-hide if necessary
|
||||||
var shouldHide = this.maxValue <= 0.01F;
|
var shouldHide = this.maxValue <= Epsilon;
|
||||||
if (this.AutoHideWhenEmpty && this.IsHidden != shouldHide) {
|
if (this.AutoHideWhenEmpty && this.IsHidden != shouldHide) {
|
||||||
this.IsHidden = shouldHide;
|
this.IsHidden = shouldHide;
|
||||||
this.OnAutoHide?.Invoke(this);
|
this.OnAutoHide?.Invoke(this);
|
||||||
|
|
|
@ -11,6 +11,12 @@ namespace MLEM.Cameras {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Camera {
|
public class Camera {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This field holds an epsilon value used in some camera calculations to mitigate floating point rounding inaccuracies.
|
||||||
|
/// If camera <see cref="Position"/> or <see cref="Viewport"/> size are extremely small or extremely big, this value can be reduced or increased.
|
||||||
|
/// </summary>
|
||||||
|
public static float Epsilon = 0.01F;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The top-left corner of the camera's viewport.
|
/// The top-left corner of the camera's viewport.
|
||||||
/// <seealso cref="LookingPosition"/>
|
/// <seealso cref="LookingPosition"/>
|
||||||
|
@ -158,7 +164,7 @@ namespace MLEM.Cameras {
|
||||||
if (this.Max.Y > max.Y)
|
if (this.Max.Y > max.Y)
|
||||||
this.Max = new Vector2(this.Max.X, max.Y);
|
this.Max = new Vector2(this.Max.X, max.Y);
|
||||||
}
|
}
|
||||||
return !this.Position.Equals(lastPos, 0.001F);
|
return !this.Position.Equals(lastPos, Epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Numerics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using MLEM.Data;
|
using MLEM.Data;
|
||||||
using MLEM.Data.Json;
|
using MLEM.Data.Json;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using static MLEM.Data.DynamicEnum;
|
||||||
|
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||||
|
|
||||||
namespace Tests {
|
namespace Tests {
|
||||||
public class DataTests {
|
public class DataTests {
|
||||||
|
@ -62,6 +65,33 @@ namespace Tests {
|
||||||
TestContext.WriteLine($"DeepCopy took {stopwatch.Elapsed.TotalMilliseconds / count * 1000000}ns on average");
|
TestContext.WriteLine($"DeepCopy took {stopwatch.Elapsed.TotalMilliseconds / count * 1000000}ns on average");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDynamicEnum() {
|
||||||
|
var flags = new TestEnum[100];
|
||||||
|
for (var i = 0; i < flags.Length; i++)
|
||||||
|
flags[i] = AddFlag<TestEnum>("Flag" + i);
|
||||||
|
|
||||||
|
Assert.AreEqual(GetValue(flags[7]), BigInteger.One << 7);
|
||||||
|
Assert.AreEqual(GetEnumValue<TestEnum>(BigInteger.One << 75), flags[75]);
|
||||||
|
|
||||||
|
Assert.AreEqual(GetValue(Or(flags[2], flags[17])), (BigInteger.One << 2) | (BigInteger.One << 17));
|
||||||
|
Assert.AreEqual(GetValue(And(flags[2], flags[3])), BigInteger.Zero);
|
||||||
|
Assert.AreEqual(And(Or(flags[24], flags[52]), Or(flags[52], flags[75])), flags[52]);
|
||||||
|
Assert.AreEqual(Xor(Or(flags[85], flags[73]), flags[73]), flags[85]);
|
||||||
|
Assert.AreEqual(Xor(Or(flags[85], Or(flags[73], flags[12])), flags[73]), Or(flags[85], flags[12]));
|
||||||
|
Assert.AreEqual(GetValue(Neg(flags[74])), ~(BigInteger.One << 74));
|
||||||
|
|
||||||
|
Assert.AreEqual(Or(flags[24], flags[52]).HasFlag(flags[24]), true);
|
||||||
|
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(flags[24]), true);
|
||||||
|
Assert.AreEqual(Or(flags[24], flags[52]).HasFlag(Or(flags[24], flags[26])), false);
|
||||||
|
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(Or(flags[24], flags[26])), true);
|
||||||
|
|
||||||
|
Assert.AreEqual(Parse<TestEnum>("Flag24"), flags[24]);
|
||||||
|
Assert.AreEqual(Parse<TestEnum>("Flag24 | Flag43"), Or(flags[24], flags[43]));
|
||||||
|
Assert.AreEqual(flags[24].ToString(), "Flag24");
|
||||||
|
Assert.AreEqual(Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43");
|
||||||
|
}
|
||||||
|
|
||||||
private class TestObject {
|
private class TestObject {
|
||||||
|
|
||||||
public Vector2 Vec;
|
public Vector2 Vec;
|
||||||
|
@ -86,5 +116,12 @@ namespace Tests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestEnum : DynamicEnum {
|
||||||
|
|
||||||
|
public TestEnum(string name, BigInteger value) : base(name, value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue