1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-06-13 09:33:50 +02:00

Code cleanup, and marked AStar.InfiniteCost as obsolete

This commit is contained in:
Ell 2022-06-15 11:38:11 +02:00
parent d0ece92550
commit 59af00c89a
65 changed files with 584 additions and 580 deletions

View file

@ -22,6 +22,9 @@ Improvements
- Allow comparing Keybind and Combination based on the amount of modifiers they have - Allow comparing Keybind and Combination based on the amount of modifiers they have
- Allow using multiple textures in a StaticSpriteBatch - Allow using multiple textures in a StaticSpriteBatch
Removals
- Marked AStar.InfiniteCost as obsolete
### MLEM.Ui ### MLEM.Ui
Additions Additions
- Added Element.AutoNavGroup which allows forming groups for auto-navigation - Added Element.AutoNavGroup which allows forming groups for auto-navigation

View file

@ -8,7 +8,6 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Misc; using MLEM.Misc;
using static Android.Views.SystemUiFlags;
namespace Demos.Android { namespace Demos.Android {
[Activity( [Activity(
@ -48,7 +47,7 @@ namespace Demos.Android {
base.OnWindowFocusChanged(hasFocus); base.OnWindowFocusChanged(hasFocus);
// hide the status bar // hide the status bar
if (hasFocus) if (hasFocus)
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (ImmersiveSticky | LayoutStable | LayoutHideNavigation | LayoutFullscreen | HideNavigation | Fullscreen); this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.ImmersiveSticky | SystemUiFlags.LayoutStable | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen);
} }
} }

View file

@ -27,7 +27,7 @@ namespace Demos {
// using it having wrong coordinates and/or sizes // using it having wrong coordinates and/or sizes
// the regions that are part of the atlas are then referenced by region coordinates rather than texture coordinates // the regions that are part of the atlas are then referenced by region coordinates rather than texture coordinates
// (as seen below) // (as seen below)
var atlas = new UniformTextureAtlas(LoadContent<Texture2D>("Textures/Anim"), 4, 4); var atlas = new UniformTextureAtlas(Demo.LoadContent<Texture2D>("Textures/Anim"), 4, 4);
// create the four animations by supplying the time per frame, and the four regions used // create the four animations by supplying the time per frame, and the four regions used
// note that you don't need to use a texture atlas for this, you can also simply supply the texture and the regions manually here // note that you don't need to use a texture atlas for this, you can also simply supply the texture and the regions manually here

View file

@ -20,7 +20,7 @@ namespace Demos {
public override void LoadContent() { public override void LoadContent() {
base.LoadContent(); base.LoadContent();
// The layout of the texture is important for auto tiling to work correctly, and is explained in the XML docs for the methods used // The layout of the texture is important for auto tiling to work correctly, and is explained in the XML docs for the methods used
this.texture = LoadContent<Texture2D>("Textures/AutoTiling"); this.texture = Demo.LoadContent<Texture2D>("Textures/AutoTiling");
// in this example, a simple string array is used for layout purposes. As the AutoTiling method allows any kind of // in this example, a simple string array is used for layout purposes. As the AutoTiling method allows any kind of
// comparison, the actual implementation can vary (for instance, based on a more in-depth tile map) // comparison, the actual implementation can vary (for instance, based on a more in-depth tile map)
@ -59,12 +59,12 @@ namespace Demos {
} }
// the texture region supplied to the AutoTiling method should only encompass the first filler tile's location and size // the texture region supplied to the AutoTiling method should only encompass the first filler tile's location and size
AutoTiling.DrawAutoTile(this.SpriteBatch, new Vector2(x + 1, y + 1) * TileSize, new TextureRegion(this.texture, 0, 0, TileSize, TileSize), ConnectsTo, Color.White); AutoTiling.DrawAutoTile(this.SpriteBatch, new Vector2(x + 1, y + 1) * AutoTilingDemo.TileSize, new TextureRegion(this.texture, 0, 0, AutoTilingDemo.TileSize, AutoTilingDemo.TileSize), ConnectsTo, Color.White);
// when drawing extended auto-tiles, the same rules apply, but the source texture layout is different // when drawing extended auto-tiles, the same rules apply, but the source texture layout is different
var background = new TextureRegion(this.texture, 0, TileSize * 2, TileSize, TileSize); var background = new TextureRegion(this.texture, 0, AutoTilingDemo.TileSize * 2, AutoTilingDemo.TileSize, AutoTilingDemo.TileSize);
var overlay = new TextureRegion(this.texture, background.Area.OffsetCopy(new Point(TileSize, 0))); var overlay = new TextureRegion(this.texture, background.Area.OffsetCopy(new Point(AutoTilingDemo.TileSize, 0)));
AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * TileSize, background, overlay, ConnectsTo, Color.White, Color.White); AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * AutoTilingDemo.TileSize, background, overlay, ConnectsTo, Color.White, Color.White);
} }
} }
this.SpriteBatch.End(); this.SpriteBatch.End();

View file

@ -13,7 +13,7 @@ namespace Demos {
private static readonly FieldInfo[] EasingFields = typeof(Easings) private static readonly FieldInfo[] EasingFields = typeof(Easings)
.GetFields(BindingFlags.Public | BindingFlags.Static).ToArray(); .GetFields(BindingFlags.Public | BindingFlags.Static).ToArray();
private static readonly Easings.Easing[] Easings = EasingFields private static readonly Easings.Easing[] Easings = EasingsDemo.EasingFields
.Select(f => (Easings.Easing) f.GetValue(null)).ToArray(); .Select(f => (Easings.Easing) f.GetValue(null)).ToArray();
private Group group; private Group group;
private int current; private int current;
@ -27,11 +27,11 @@ namespace Demos {
this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false}; this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false};
this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") { this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") {
OnPressed = e => { OnPressed = e => {
this.current = (this.current + 1) % Easings.Length; this.current = (this.current + 1) % EasingsDemo.Easings.Length;
this.progress = 0; this.progress = 0;
} }
}); });
this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingFields[this.current].Name, true)); this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingsDemo.EasingFields[this.current].Name, true));
this.UiRoot.AddChild(this.group); this.UiRoot.AddChild(this.group);
} }
@ -47,7 +47,7 @@ namespace Demos {
var view = this.GraphicsDevice.Viewport; var view = this.GraphicsDevice.Viewport;
// graph the easing function // graph the easing function
var graphEase = Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3); var graphEase = EasingsDemo.Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3);
for (var x = 0; x < view.Width; x++) { for (var x = 0; x < view.Width; x++) {
var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4); var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4);
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Green); this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Green);
@ -55,7 +55,7 @@ namespace Demos {
// draw a little dot to show what it would look like // draw a little dot to show what it would look like
this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1; this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1;
var dotEase = Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4); var dotEase = EasingsDemo.Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4);
var pos = new RectangleF(view.Width / 2 - 4, view.Height - 20 - dotEase(this.progress), 8, 8); var pos = new RectangleF(view.Width / 2 - 4, view.Height - 20 - dotEase(this.progress), 8, 8);
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red); this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red);

View file

@ -23,11 +23,11 @@ namespace Demos {
private TimeSpan secondCounter; private TimeSpan secondCounter;
static GameImpl() { static GameImpl() {
Demos.Add("Ui", ("An in-depth demonstration of the MLEM.Ui package and its abilities", game => new UiDemo(game))); GameImpl.Demos.Add("Ui", ("An in-depth demonstration of the MLEM.Ui package and its abilities", game => new UiDemo(game)));
Demos.Add("Easings", ("An example of MLEM's Easings class, an adaptation of easings.net", game => new EasingsDemo(game))); GameImpl.Demos.Add("Easings", ("An example of MLEM's Easings class, an adaptation of easings.net", game => new EasingsDemo(game)));
Demos.Add("Pathfinding", ("An example of MLEM's A* pathfinding implementation in 2D", game => new PathfindingDemo(game))); GameImpl.Demos.Add("Pathfinding", ("An example of MLEM's A* pathfinding implementation in 2D", game => new PathfindingDemo(game)));
Demos.Add("Animation and Texture Atlas", ("An example of UniformTextureAtlases, SpriteAnimations and SpriteAnimationGroups", game => new AnimationDemo(game))); GameImpl.Demos.Add("Animation and Texture Atlas", ("An example of UniformTextureAtlases, SpriteAnimations and SpriteAnimationGroups", game => new AnimationDemo(game)));
Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game))); GameImpl.Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game)));
} }
public GameImpl() { public GameImpl() {
@ -74,7 +74,7 @@ namespace Demos {
selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' <l https://github.com/Ellpeck/MLEM/tree/main/Demos>source code</l> for more in-depth explanations of their functionality or the <l https://mlem.ellpeck.de/>website</l> for tutorials and API documentation.")); selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' <l https://github.com/Ellpeck/MLEM/tree/main/Demos>source code</l> for more in-depth explanations of their functionality or the <l https://mlem.ellpeck.de/>website</l> for tutorials and API documentation."));
selection.AddChild(new VerticalSpace(5)); selection.AddChild(new VerticalSpace(5));
foreach (var demo in Demos) { foreach (var demo in GameImpl.Demos) {
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) { selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
OnPressed = e => { OnPressed = e => {
selection.IsHidden = true; selection.IsHidden = true;
@ -92,9 +92,9 @@ namespace Demos {
} }
protected override UiStyle InitializeDefaultUiStyle(SpriteBatch batch) { protected override UiStyle InitializeDefaultUiStyle(SpriteBatch batch) {
var tex = LoadContent<Texture2D>("Textures/Test"); var tex = MlemGame.LoadContent<Texture2D>("Textures/Test");
return new UntexturedStyle(this.SpriteBatch) { return new UntexturedStyle(this.SpriteBatch) {
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")), Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/TestFont")),
TextScale = 0.1F, TextScale = 0.1F,
PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8), PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8),
ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4), ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),

View file

@ -41,8 +41,8 @@ namespace Demos {
// pathfinder's constructor // pathfinder's constructor
float Cost(Point pos, Point nextPos) { float Cost(Point pos, Point nextPos) {
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50) if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
return AStar2.InfiniteCost; return float.PositiveInfinity;
return this.world[nextPos.X, nextPos.Y] ? 1 : AStar2.InfiniteCost; return this.world[nextPos.X, nextPos.Y] ? 1 : float.PositiveInfinity;
} }
// Actually initialize the pathfinder with the cost function, as well as specify if moving diagonally between tiles should be // Actually initialize the pathfinder with the cost function, as well as specify if moving diagonally between tiles should be

View file

@ -28,7 +28,7 @@ namespace Demos {
public UiDemo(MlemGame game) : base(game) {} public UiDemo(MlemGame game) : base(game) {}
public override void LoadContent() { public override void LoadContent() {
this.testTexture = LoadContent<Texture2D>("Textures/Test"); this.testTexture = Demo.LoadContent<Texture2D>("Textures/Test");
this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8); this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8);
base.LoadContent(); base.LoadContent();
@ -38,7 +38,10 @@ namespace Demos {
// when using a SpriteFont, use GenericSpriteFont. When using a MonoGame.Extended BitmapFont, use GenericBitmapFont. // when using a SpriteFont, use GenericSpriteFont. When using a MonoGame.Extended BitmapFont, use GenericBitmapFont.
// Wrapping fonts like this allows for both types to be usable within MLEM.Ui easily // Wrapping fonts like this allows for both types to be usable within MLEM.Ui easily
// Supplying a bold and an italic version is optional // Supplying a bold and an italic version is optional
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"), LoadContent<SpriteFont>("Fonts/TestFontBold"), LoadContent<SpriteFont>("Fonts/TestFontItalic")), Font = new GenericSpriteFont(
Demo.LoadContent<SpriteFont>("Fonts/TestFont"),
Demo.LoadContent<SpriteFont>("Fonts/TestFontBold"),
Demo.LoadContent<SpriteFont>("Fonts/TestFontItalic")),
TextScale = 0.1F, TextScale = 0.1F,
PanelTexture = this.testPatch, PanelTexture = this.testPatch,
ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4), ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
@ -49,7 +52,7 @@ namespace Demos {
CheckboxCheckmark = new TextureRegion(this.testTexture, 24, 0, 8, 8), CheckboxCheckmark = new TextureRegion(this.testTexture, 24, 0, 8, 8),
RadioTexture = new NinePatch(new TextureRegion(this.testTexture, 16, 0, 8, 8), 3), RadioTexture = new NinePatch(new TextureRegion(this.testTexture, 16, 0, 8, 8), 3),
RadioCheckmark = new TextureRegion(this.testTexture, 32, 0, 8, 8), RadioCheckmark = new TextureRegion(this.testTexture, 32, 0, 8, 8),
AdditionalFonts = {{"Monospaced", new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/MonospacedFont"))}}, AdditionalFonts = {{"Monospaced", new GenericSpriteFont(Demo.LoadContent<SpriteFont>("Fonts/MonospacedFont"))}},
LinkColor = Color.CornflowerBlue LinkColor = Color.CornflowerBlue
}; };
var untexturedStyle = new UntexturedStyle(this.SpriteBatch) { var untexturedStyle = new UntexturedStyle(this.SpriteBatch) {
@ -158,7 +161,7 @@ namespace Demos {
// Check the WobbleButton method for an explanation of how this button works // Check the WobbleButton method for an explanation of how this button works
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") { this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
OnPressed = element => CoroutineHandler.Start(WobbleButton(element)), OnPressed = element => CoroutineHandler.Start(UiDemo.WobbleButton(element)),
PositionOffset = new Vector2(0, 1) PositionOffset = new Vector2(0, 1)
}); });
// Another button that shows animations! // Another button that shows animations!
@ -191,13 +194,13 @@ namespace Demos {
this.root.AddChild(new VerticalSpace(3)); this.root.AddChild(new VerticalSpace(3));
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Progress bars!")); this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Progress bars!"));
var bar1 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Right, 10) {PositionOffset = new Vector2(0, 1)}); var bar1 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Right, 10) {PositionOffset = new Vector2(0, 1)});
CoroutineHandler.Start(WobbleProgressBar(bar1)); CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar1));
var bar2 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)}); var bar2 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)});
CoroutineHandler.Start(WobbleProgressBar(bar2)); CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar2));
var bar3 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)}); var bar3 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)});
CoroutineHandler.Start(WobbleProgressBar(bar3)); CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar3));
var bar4 = this.root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 0)}); var bar4 = this.root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 0)});
CoroutineHandler.Start(WobbleProgressBar(bar4)); CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar4));
this.root.AddChild(new VerticalSpace(3)); this.root.AddChild(new VerticalSpace(3));
var dropdown = this.root.AddChild(new Dropdown(Anchor.AutoLeft, new Vector2(1, 10), "Dropdown Menu")); var dropdown = this.root.AddChild(new Dropdown(Anchor.AutoLeft, new Vector2(1, 10), "Dropdown Menu"));

View file

@ -56,9 +56,9 @@ namespace MLEM.Data.Content {
private T Read<T>(string assetName, T existing) { private T Read<T>(string assetName, T existing) {
var triedFiles = new List<string>(); var triedFiles = new List<string>();
if (readers == null) if (RawContentManager.readers == null)
readers = CollectContentReaders(); RawContentManager.readers = RawContentManager.CollectContentReaders();
foreach (var reader in readers) { foreach (var reader in RawContentManager.readers) {
if (!reader.CanRead(typeof(T))) if (!reader.CanRead(typeof(T)))
continue; continue;
foreach (var ext in reader.GetFileExtensions()) { foreach (var ext in reader.GetFileExtensions()) {

View file

@ -21,7 +21,7 @@ namespace MLEM.Data {
/// <param name="content">The content manager to add the json serializer to</param> /// <param name="content">The content manager to add the json serializer to</param>
/// <param name="serializer">The json serializer to add</param> /// <param name="serializer">The json serializer to add</param>
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) { public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
Serializers[content] = serializer; ContentExtensions.Serializers[content] = serializer;
} }
/// <summary> /// <summary>
@ -31,7 +31,7 @@ namespace MLEM.Data {
/// <param name="content">The content manager whose serializer to get</param> /// <param name="content">The content manager whose serializer to get</param>
/// <returns>The content manager's serializer</returns> /// <returns>The content manager's serializer</returns>
public static JsonSerializer GetJsonSerializer(this ContentManager content) { public static JsonSerializer GetJsonSerializer(this ContentManager content) {
if (!Serializers.TryGetValue(content, out var serializer)) { if (!ContentExtensions.Serializers.TryGetValue(content, out var serializer)) {
serializer = JsonConverters.AddAll(new JsonSerializer()); serializer = JsonConverters.AddAll(new JsonSerializer());
content.SetJsonSerializer(serializer); content.SetJsonSerializer(serializer);
} }
@ -44,7 +44,7 @@ namespace MLEM.Data {
/// <param name="content">The content manager to add the converter to</param> /// <param name="content">The content manager to add the converter to</param>
/// <param name="converter">The converter to add</param> /// <param name="converter">The converter to add</param>
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) { public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
var serializer = GetJsonSerializer(content); var serializer = content.GetJsonSerializer();
serializer.Converters.Add(converter); serializer.Converters.Add(converter);
} }
@ -60,7 +60,7 @@ namespace MLEM.Data {
public static T LoadJson<T>(this ContentManager content, string name, string[] extensions = null, JsonSerializer serializer = null) { public static T LoadJson<T>(this ContentManager content, string name, string[] extensions = null, JsonSerializer serializer = null) {
var triedFiles = new List<string>(); var triedFiles = new List<string>();
var serializerToUse = serializer ?? content.GetJsonSerializer(); var serializerToUse = serializer ?? content.GetJsonSerializer();
foreach (var extension in extensions ?? JsonExtensions) { foreach (var extension in extensions ?? ContentExtensions.JsonExtensions) {
var file = Path.Combine(content.RootDirectory, name + extension); var file = Path.Combine(content.RootDirectory, name + extension);
triedFiles.Add(file); triedFiles.Add(file);
try { try {

View file

@ -23,8 +23,8 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the object to copy</typeparam> /// <typeparam name="T">The type of the object to copy</typeparam>
/// <returns>A shallow copy of the object</returns> /// <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.")] [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 = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) { public static T Copy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
var copy = (T) Construct(typeof(T), flags); var copy = (T) CopyExtensions.Construct(typeof(T), flags);
obj.CopyInto(copy, flags, fieldInclusion); obj.CopyInto(copy, flags, fieldInclusion);
return copy; return copy;
} }
@ -39,8 +39,8 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the object to copy</typeparam> /// <typeparam name="T">The type of the object to copy</typeparam>
/// <returns>A deep copy of the object</returns> /// <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.")] [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 = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) { public static T DeepCopy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
var copy = (T) Construct(typeof(T), flags); var copy = (T) CopyExtensions.Construct(typeof(T), flags);
obj.DeepCopyInto(copy, flags, fieldInclusion); obj.DeepCopyInto(copy, flags, fieldInclusion);
return copy; return copy;
} }
@ -54,7 +54,7 @@ namespace MLEM.Data {
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</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> /// <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.")] [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 = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) { 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)) { foreach (var field in typeof(T).GetFields(flags)) {
if (fieldInclusion == null || fieldInclusion(field)) if (fieldInclusion == null || fieldInclusion(field))
field.SetValue(otherObj, field.GetValue(obj)); field.SetValue(otherObj, field.GetValue(obj));
@ -71,7 +71,7 @@ namespace MLEM.Data {
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</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> /// <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.")] [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 = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) { 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)) { foreach (var field in obj.GetType().GetFields(flags)) {
if (fieldInclusion != null && !fieldInclusion(field)) if (fieldInclusion != null && !fieldInclusion(field))
continue; continue;
@ -83,7 +83,7 @@ namespace MLEM.Data {
var otherVal = field.GetValue(otherObj); var otherVal = field.GetValue(otherObj);
// if the object we want to copy into doesn't have a value yet, we create one // if the object we want to copy into doesn't have a value yet, we create one
if (otherVal == null) { if (otherVal == null) {
otherVal = Construct(field.FieldType, flags); otherVal = CopyExtensions.Construct(field.FieldType, flags);
field.SetValue(otherObj, otherVal); field.SetValue(otherObj, otherVal);
} }
val.DeepCopyInto(otherVal, flags); val.DeepCopyInto(otherVal, flags);
@ -92,7 +92,7 @@ namespace MLEM.Data {
} }
private static object Construct(Type t, BindingFlags flags) { private static object Construct(Type t, BindingFlags flags) {
if (!ConstructorCache.TryGetValue(t, out var constructor)) { if (!CopyExtensions.ConstructorCache.TryGetValue(t, out var constructor)) {
var constructors = t.GetConstructors(flags); var constructors = t.GetConstructors(flags);
// find a contructor with the correct attribute // find a contructor with the correct attribute
constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null); constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
@ -104,7 +104,7 @@ namespace MLEM.Data {
constructor = constructors.FirstOrDefault(); constructor = constructors.FirstOrDefault();
if (constructor == null) if (constructor == null)
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility"); throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
ConstructorCache.Add(t, constructor); CopyExtensions.ConstructorCache.Add(t, constructor);
} }
return constructor.Invoke(new object[constructor.GetParameters().Length]); return constructor.Invoke(new object[constructor.GetParameters().Length]);
} }

View file

@ -60,7 +60,7 @@ namespace MLEM.Data {
if (this.allFlagsCache == null) if (this.allFlagsCache == null)
this.allFlagsCache = new Dictionary<DynamicEnum, bool>(); this.allFlagsCache = new Dictionary<DynamicEnum, bool>();
if (!this.allFlagsCache.TryGetValue(flags, out var ret)) { if (!this.allFlagsCache.TryGetValue(flags, out var ret)) {
ret = (GetValue(this) & GetValue(flags)) == GetValue(flags); ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) == DynamicEnum.GetValue(flags);
this.allFlagsCache.Add(flags, ret); this.allFlagsCache.Add(flags, ret);
} }
return ret; return ret;
@ -76,7 +76,7 @@ namespace MLEM.Data {
if (this.anyFlagsCache == null) if (this.anyFlagsCache == null)
this.anyFlagsCache = new Dictionary<DynamicEnum, bool>(); this.anyFlagsCache = new Dictionary<DynamicEnum, bool>();
if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) { if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) {
ret = (GetValue(this) & GetValue(flags)) != 0; ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) != 0;
this.anyFlagsCache.Add(flags, ret); this.anyFlagsCache.Add(flags, ret);
} }
return ret; return ret;
@ -87,13 +87,13 @@ namespace MLEM.Data {
public override string ToString() { public override string ToString() {
if (this.name == null) { if (this.name == null) {
var included = new List<DynamicEnum>(); var included = new List<DynamicEnum>();
if (GetValue(this) != 0) { if (DynamicEnum.GetValue(this) != 0) {
foreach (var v in GetValues(this.GetType())) { foreach (var v in DynamicEnum.GetValues(this.GetType())) {
if (this.HasFlag(v) && GetValue(v) != 0) if (this.HasFlag(v) && DynamicEnum.GetValue(v) != 0)
included.Add(v); included.Add(v);
} }
} }
this.name = included.Count > 0 ? string.Join(" | ", included) : GetValue(this).ToString(); this.name = included.Count > 0 ? string.Join(" | ", included) : DynamicEnum.GetValue(this).ToString();
} }
return this.name; return this.name;
} }
@ -107,7 +107,7 @@ namespace MLEM.Data {
/// <returns>The newly created enum value</returns> /// <returns>The newly created enum value</returns>
/// <exception cref="ArgumentException">Thrown if the name or value passed are already present</exception> /// <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 { public static T Add<T>(string name, BigInteger value) where T : DynamicEnum {
var storage = GetStorage(typeof(T)); var storage = DynamicEnum.GetStorage(typeof(T));
// cached parsed values and names might be incomplete with new values // cached parsed values and names might be incomplete with new values
storage.ClearCaches(); storage.ClearCaches();
@ -119,7 +119,7 @@ namespace MLEM.Data {
throw new ArgumentException($"Duplicate name {name}", nameof(name)); throw new ArgumentException($"Duplicate name {name}", nameof(name));
} }
var ret = Construct(typeof(T), name, value); var ret = DynamicEnum.Construct(typeof(T), name, value);
storage.Values.Add(value, ret); storage.Values.Add(value, ret);
return (T) ret; return (T) ret;
} }
@ -134,9 +134,9 @@ namespace MLEM.Data {
/// <returns>The newly created enum value</returns> /// <returns>The newly created enum value</returns>
public static T AddValue<T>(string name) where T : DynamicEnum { public static T AddValue<T>(string name) where T : DynamicEnum {
BigInteger value = 0; BigInteger value = 0;
while (GetStorage(typeof(T)).Values.ContainsKey(value)) while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
value++; value++;
return Add<T>(name, value); return DynamicEnum.Add<T>(name, value);
} }
/// <summary> /// <summary>
@ -149,9 +149,9 @@ namespace MLEM.Data {
/// <returns>The newly created enum value</returns> /// <returns>The newly created enum value</returns>
public static T AddFlag<T>(string name) where T : DynamicEnum { public static T AddFlag<T>(string name) where T : DynamicEnum {
BigInteger value = 1; BigInteger value = 1;
while (GetStorage(typeof(T)).Values.ContainsKey(value)) while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
value <<= 1; value <<= 1;
return Add<T>(name, value); return DynamicEnum.Add<T>(name, value);
} }
/// <summary> /// <summary>
@ -161,7 +161,7 @@ namespace MLEM.Data {
/// <typeparam name="T">The type whose values to get</typeparam> /// <typeparam name="T">The type whose values to get</typeparam>
/// <returns>The defined values for the given type</returns> /// <returns>The defined values for the given type</returns>
public static IEnumerable<T> GetValues<T>() where T : DynamicEnum { public static IEnumerable<T> GetValues<T>() where T : DynamicEnum {
return GetValues(typeof(T)).Cast<T>(); return DynamicEnum.GetValues(typeof(T)).Cast<T>();
} }
/// <summary> /// <summary>
@ -171,7 +171,7 @@ namespace MLEM.Data {
/// <param name="type">The type whose values to get</param> /// <param name="type">The type whose values to get</param>
/// <returns>The defined values for the given type</returns> /// <returns>The defined values for the given type</returns>
public static IEnumerable<DynamicEnum> GetValues(Type type) { public static IEnumerable<DynamicEnum> GetValues(Type type) {
return GetStorage(type).Values.Values; return DynamicEnum.GetStorage(type).Values.Values;
} }
/// <summary> /// <summary>
@ -182,9 +182,9 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the values</typeparam> /// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise OR (|) combination</returns> /// <returns>The bitwise OR (|) combination</returns>
public static T Or<T>(T left, T right) where T : DynamicEnum { public static T Or<T>(T left, T right) where T : DynamicEnum {
var cache = GetStorage(typeof(T)).OrCache; var cache = DynamicEnum.GetStorage(typeof(T)).OrCache;
if (!cache.TryGetValue((left, right), out var ret)) { if (!cache.TryGetValue((left, right), out var ret)) {
ret = GetEnumValue<T>(GetValue(left) | GetValue(right)); ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) | DynamicEnum.GetValue(right));
cache.Add((left, right), ret); cache.Add((left, right), ret);
} }
return (T) ret; return (T) ret;
@ -198,9 +198,9 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the values</typeparam> /// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise AND (&amp;) combination</returns> /// <returns>The bitwise AND (&amp;) combination</returns>
public static T And<T>(T left, T right) where T : DynamicEnum { public static T And<T>(T left, T right) where T : DynamicEnum {
var cache = GetStorage(typeof(T)).AndCache; var cache = DynamicEnum.GetStorage(typeof(T)).AndCache;
if (!cache.TryGetValue((left, right), out var ret)) { if (!cache.TryGetValue((left, right), out var ret)) {
ret = GetEnumValue<T>(GetValue(left) & GetValue(right)); ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) & DynamicEnum.GetValue(right));
cache.Add((left, right), ret); cache.Add((left, right), ret);
} }
return (T) ret; return (T) ret;
@ -214,9 +214,9 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the values</typeparam> /// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise XOR (^) combination</returns> /// <returns>The bitwise XOR (^) combination</returns>
public static T Xor<T>(T left, T right) where T : DynamicEnum { public static T Xor<T>(T left, T right) where T : DynamicEnum {
var cache = GetStorage(typeof(T)).XorCache; var cache = DynamicEnum.GetStorage(typeof(T)).XorCache;
if (!cache.TryGetValue((left, right), out var ret)) { if (!cache.TryGetValue((left, right), out var ret)) {
ret = GetEnumValue<T>(GetValue(left) ^ GetValue(right)); ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) ^ DynamicEnum.GetValue(right));
cache.Add((left, right), ret); cache.Add((left, right), ret);
} }
return (T) ret; return (T) ret;
@ -229,9 +229,9 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the values</typeparam> /// <typeparam name="T">The type of the values</typeparam>
/// <returns>The bitwise NEG (~) value</returns> /// <returns>The bitwise NEG (~) value</returns>
public static T Neg<T>(T value) where T : DynamicEnum { public static T Neg<T>(T value) where T : DynamicEnum {
var cache = GetStorage(typeof(T)).NegCache; var cache = DynamicEnum.GetStorage(typeof(T)).NegCache;
if (!cache.TryGetValue(value, out var ret)) { if (!cache.TryGetValue(value, out var ret)) {
ret = GetEnumValue<T>(~GetValue(value)); ret = DynamicEnum.GetEnumValue<T>(~DynamicEnum.GetValue(value));
cache.Add(value, ret); cache.Add(value, ret);
} }
return (T) ret; return (T) ret;
@ -253,7 +253,7 @@ namespace MLEM.Data {
/// <typeparam name="T">The type that the returned dynamic enum should have</typeparam> /// <typeparam name="T">The type that the returned dynamic enum should have</typeparam>
/// <returns>The defined or combined dynamic enum value</returns> /// <returns>The defined or combined dynamic enum value</returns>
public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum { public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum {
return (T) GetEnumValue(typeof(T), value); return (T) DynamicEnum.GetEnumValue(typeof(T), value);
} }
/// <summary> /// <summary>
@ -263,7 +263,7 @@ namespace MLEM.Data {
/// <param name="value">The value whose dynamic enum value to get</param> /// <param name="value">The value whose dynamic enum value to get</param>
/// <returns>The defined or combined dynamic enum value</returns> /// <returns>The defined or combined dynamic enum value</returns>
public static DynamicEnum GetEnumValue(Type type, BigInteger value) { public static DynamicEnum GetEnumValue(Type type, BigInteger value) {
var storage = GetStorage(type); var storage = DynamicEnum.GetStorage(type);
// get the defined value if it exists // get the defined value if it exists
if (storage.Values.TryGetValue(value, out var defined)) if (storage.Values.TryGetValue(value, out var defined))
@ -271,7 +271,7 @@ namespace MLEM.Data {
// otherwise, cache the combined value // otherwise, cache the combined value
if (!storage.FlagCache.TryGetValue(value, out var combined)) { if (!storage.FlagCache.TryGetValue(value, out var combined)) {
combined = Construct(type, null, value); combined = DynamicEnum.Construct(type, null, value);
storage.FlagCache.Add(value, combined); storage.FlagCache.Add(value, combined);
} }
return combined; return combined;
@ -286,7 +286,7 @@ namespace MLEM.Data {
/// <typeparam name="T">The type of the dynamic enum value to parse</typeparam> /// <typeparam name="T">The type of the dynamic enum value to parse</typeparam>
/// <returns>The parsed enum value, or null if parsing fails</returns> /// <returns>The parsed enum value, or null if parsing fails</returns>
public static T Parse<T>(string strg) where T : DynamicEnum { public static T Parse<T>(string strg) where T : DynamicEnum {
return (T) Parse(typeof(T), strg); return (T) DynamicEnum.Parse(typeof(T), strg);
} }
/// <summary> /// <summary>
@ -297,28 +297,28 @@ namespace MLEM.Data {
/// <param name="strg">The string to parse into a dynamic enum value</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> /// <returns>The parsed enum value, or null if parsing fails</returns>
public static DynamicEnum Parse(Type type, string strg) { public static DynamicEnum Parse(Type type, string strg) {
var cache = GetStorage(type).ParseCache; var cache = DynamicEnum.GetStorage(type).ParseCache;
if (!cache.TryGetValue(strg, out var cached)) { if (!cache.TryGetValue(strg, out var cached)) {
BigInteger? accum = null; BigInteger? accum = null;
foreach (var val in strg.Split('|')) { foreach (var val in strg.Split('|')) {
foreach (var defined in GetValues(type)) { foreach (var defined in DynamicEnum.GetValues(type)) {
if (defined.name == val.Trim()) { if (defined.name == val.Trim()) {
accum = (accum ?? 0) | GetValue(defined); accum = (accum ?? 0) | DynamicEnum.GetValue(defined);
break; break;
} }
} }
} }
if (accum != null) if (accum != null)
cached = GetEnumValue(type, accum.Value); cached = DynamicEnum.GetEnumValue(type, accum.Value);
cache.Add(strg, cached); cache.Add(strg, cached);
} }
return cached; return cached;
} }
private static Storage GetStorage(Type type) { private static Storage GetStorage(Type type) {
if (!Storages.TryGetValue(type, out var storage)) { if (!DynamicEnum.Storages.TryGetValue(type, out var storage)) {
storage = new Storage(); storage = new Storage();
Storages.Add(type, storage); DynamicEnum.Storages.Add(type, storage);
} }
return storage; return storage;
} }

View file

@ -21,7 +21,7 @@ namespace MLEM.Data.Json {
/// <param name="serializer">The serializer to add the converters to</param> /// <param name="serializer">The serializer to add the converters to</param>
/// <returns>The given serializer, for chaining</returns> /// <returns>The given serializer, for chaining</returns>
public static JsonSerializer AddAll(JsonSerializer serializer) { public static JsonSerializer AddAll(JsonSerializer serializer) {
foreach (var converter in Converters) foreach (var converter in JsonConverters.Converters)
serializer.Converters.Add(converter); serializer.Converters.Add(converter);
return serializer; return serializer;
} }

View file

@ -29,7 +29,7 @@ namespace MLEM.Data.Json {
/// </summary> /// </summary>
/// <param name="type">The type that the dictionary is declared in</param> /// <param name="type">The type that the dictionary is declared in</param>
/// <param name="memberName">The name of the dictionary itself</param> /// <param name="memberName">The name of the dictionary itself</param>
public StaticJsonConverter(Type type, string memberName) : this(GetEntries(type, memberName)) {} public StaticJsonConverter(Type type, string memberName) : this(StaticJsonConverter<T>.GetEntries(type, memberName)) {}
/// <summary>Writes the JSON representation of the object.</summary> /// <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="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>

View file

@ -81,7 +81,7 @@ namespace MLEM.Data {
var region = atlas[pos]; var region = atlas[pos];
if (ignoreTransparent) { if (ignoreTransparent) {
if (IsTransparent(region)) if (this.IsTransparent(region))
continue; continue;
} }
@ -180,8 +180,8 @@ namespace MLEM.Data {
var width = this.alreadyPackedTextures.Max(t => t.PackedArea.Right); var width = this.alreadyPackedTextures.Max(t => t.PackedArea.Right);
var height = this.alreadyPackedTextures.Max(t => t.PackedArea.Bottom); var height = this.alreadyPackedTextures.Max(t => t.PackedArea.Bottom);
if (this.forcePowerOfTwo) { if (this.forcePowerOfTwo) {
width = ToPowerOfTwo(width); width = RuntimeTexturePacker.ToPowerOfTwo(width);
height = ToPowerOfTwo(height); height = RuntimeTexturePacker.ToPowerOfTwo(height);
} }
if (this.forceSquare) if (this.forceSquare)
width = height = Math.Max(width, height); width = height = Math.Max(width, height);

View file

@ -116,7 +116,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="frustum">The area that is visible, in pixel space.</param> /// <param name="frustum">The area that is visible, in pixel space.</param>
/// <param name="drawFunction">The draw function to use, or null to use <see cref="DefaultDraw"/></param> /// <param name="drawFunction">The draw function to use, or null to use <see cref="DefaultDraw"/></param>
public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) { public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
var draw = drawFunction ?? DefaultDraw; var draw = drawFunction ?? IndividualTiledMapRenderer.DefaultDraw;
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum); var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
for (var x = minX; x < maxX; x++) { for (var x = minX; x < maxX; x++) {
for (var y = minY; y < maxY; y++) { for (var y = minY; y < maxY; y++) {
@ -136,7 +136,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="frustum">The area that is visible, in pixel space.</param> /// <param name="frustum">The area that is visible, in pixel space.</param>
/// <param name="addFunction">The add function to use, or null to use <see cref="DefaultAdd"/>.</param> /// <param name="addFunction">The add function to use, or null to use <see cref="DefaultAdd"/>.</param>
public void AddLayer(StaticSpriteBatch batch, int layerIndex, RectangleF? frustum = null, AddDelegate addFunction = null) { public void AddLayer(StaticSpriteBatch batch, int layerIndex, RectangleF? frustum = null, AddDelegate addFunction = null) {
var add = addFunction ?? DefaultAdd; var add = addFunction ?? IndividualTiledMapRenderer.DefaultAdd;
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum); var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
for (var x = minX; x < maxX; x++) { for (var x = minX; x < maxX; x++) {
for (var y = minY; y < maxY; y++) { for (var y = minY; y < maxY; y++) {

View file

@ -54,8 +54,8 @@ namespace MLEM.Extended.Tiled {
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns> /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode() { public override int GetHashCode() {
var hashCode = this.Layer.GetHashCode(); var hashCode = this.Layer.GetHashCode();
hashCode = (hashCode * 397) ^ this.X; hashCode = hashCode * 397 ^ this.X;
hashCode = (hashCode * 397) ^ this.Y; hashCode = hashCode * 397 ^ this.Y;
return hashCode; return hashCode;
} }
@ -105,7 +105,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="right">The right position.</param> /// <param name="right">The right position.</param>
/// <returns>The sum of the positions.</returns> /// <returns>The sum of the positions.</returns>
public static LayerPosition operator +(LayerPosition left, LayerPosition right) { public static LayerPosition operator +(LayerPosition left, LayerPosition right) {
return Add(left, right); return LayerPosition.Add(left, right);
} }
/// <summary> /// <summary>
@ -115,7 +115,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="right">The right position.</param> /// <param name="right">The right position.</param>
/// <returns>The difference of the positions.</returns> /// <returns>The difference of the positions.</returns>
public static LayerPosition operator -(LayerPosition left, LayerPosition right) { public static LayerPosition operator -(LayerPosition left, LayerPosition right) {
return Add(left, -right); return LayerPosition.Add(left, -right);
} }
/// <summary> /// <summary>

View file

@ -54,8 +54,8 @@ namespace MLEM.Extended.Tiled {
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns> /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode() { public override int GetHashCode() {
var hashCode = this.Layer.GetHashCode(); var hashCode = this.Layer.GetHashCode();
hashCode = (hashCode * 397) ^ this.X.GetHashCode(); hashCode = hashCode * 397 ^ this.X.GetHashCode();
hashCode = (hashCode * 397) ^ this.Y.GetHashCode(); hashCode = hashCode * 397 ^ this.Y.GetHashCode();
return hashCode; return hashCode;
} }
@ -105,7 +105,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="right">The right position.</param> /// <param name="right">The right position.</param>
/// <returns>The sum of the positions.</returns> /// <returns>The sum of the positions.</returns>
public static LayerPositionF operator +(LayerPositionF left, LayerPositionF right) { public static LayerPositionF operator +(LayerPositionF left, LayerPositionF right) {
return Add(left, right); return LayerPositionF.Add(left, right);
} }
/// <summary> /// <summary>
@ -115,7 +115,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="right">The right position.</param> /// <param name="right">The right position.</param>
/// <returns>The difference of the positions.</returns> /// <returns>The difference of the positions.</returns>
public static LayerPositionF operator -(LayerPositionF left, LayerPositionF right) { public static LayerPositionF operator -(LayerPositionF left, LayerPositionF right) {
return Add(left, -right); return LayerPositionF.Add(left, -right);
} }
/// <summary> /// <summary>

View file

@ -5,7 +5,6 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended; using MonoGame.Extended;
using MonoGame.Extended.Tiled; using MonoGame.Extended.Tiled;
using static MonoGame.Extended.Tiled.TiledMapTileFlipFlags;
using ColorHelper = MLEM.Extensions.ColorHelper; using ColorHelper = MLEM.Extensions.ColorHelper;
namespace MLEM.Extended.Tiled { namespace MLEM.Extended.Tiled {
@ -144,9 +143,9 @@ namespace MLEM.Extended.Tiled {
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, int localId, bool createStub = true) { public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, int localId, bool createStub = true) {
var tilesetTile = tileset.Tiles.FirstOrDefault(t => t.LocalTileIdentifier == localId); var tilesetTile = tileset.Tiles.FirstOrDefault(t => t.LocalTileIdentifier == localId);
if (tilesetTile == null && createStub) { if (tilesetTile == null && createStub) {
if (!StubTilesetTiles.TryGetValue(localId, out tilesetTile)) { if (!TiledExtensions.StubTilesetTiles.TryGetValue(localId, out tilesetTile)) {
tilesetTile = new TiledMapTilesetTile(localId); tilesetTile = new TiledMapTilesetTile(localId);
StubTilesetTiles.Add(localId, tilesetTile); TiledExtensions.StubTilesetTiles.Add(localId, tilesetTile);
} }
} }
return tilesetTile; return tilesetTile;
@ -271,12 +270,12 @@ namespace MLEM.Extended.Tiled {
/// <param name="position">The position to add to the object's position</param> /// <param name="position">The position to add to the object's position</param>
/// <param name="flipFlags">The flipping of the tile that this object belongs to. If set, the returned area will be "flipped" in the tile's space so that it matches the flip flags.</param> /// <param name="flipFlags">The flipping of the tile that this object belongs to. If set, the returned area will be "flipped" in the tile's space so that it matches the flip flags.</param>
/// <returns>The area that the tile covers</returns> /// <returns>The area that the tile covers</returns>
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = None) { public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = TiledMapTileFlipFlags.None) {
var tileSize = map.GetTileSize(); var tileSize = map.GetTileSize();
var area = new RectangleF(obj.Position / tileSize, obj.Size / tileSize); var area = new RectangleF(obj.Position / tileSize, obj.Size / tileSize);
if (flipFlags.HasFlag(FlipHorizontally)) if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipHorizontally))
area.X = 1 - area.X - area.Width; area.X = 1 - area.X - area.Width;
if (flipFlags.HasFlag(FlipVertically)) if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipVertically))
area.Y = 1 - area.Y - area.Height; area.Y = 1 - area.Y - area.Height;
if (position != null) if (position != null)
area.Offset(position.Value); area.Offset(position.Value);

View file

@ -36,7 +36,7 @@ namespace MLEM.Extended.Tiled {
/// <param name="collisionFunction">The function used to collect the collision info of a tile, or null to use <see cref="DefaultCollectCollisions"/></param> /// <param name="collisionFunction">The function used to collect the collision info of a tile, or null to use <see cref="DefaultCollectCollisions"/></param>
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) { public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
this.map = map; this.map = map;
this.collisionFunction = collisionFunction ?? DefaultCollectCollisions; this.collisionFunction = collisionFunction ?? TiledMapCollisions.DefaultCollectCollisions;
this.collisionInfos = new TileCollisionInfo[map.Layers.Count, map.Width, map.Height]; this.collisionInfos = new TileCollisionInfo[map.Layers.Count, map.Width, map.Height];
for (var i = 0; i < map.TileLayers.Count; i++) { for (var i = 0; i < map.TileLayers.Count; i++) {
for (var x = 0; x < map.Width; x++) { for (var x = 0; x < map.Width; x++) {

View file

@ -18,7 +18,7 @@ namespace MLEM.Startup {
/// <summary> /// <summary>
/// The static game instance's input handler /// The static game instance's input handler
/// </summary> /// </summary>
public static InputHandler Input => instance.InputHandler; public static InputHandler Input => MlemGame.instance.InputHandler;
/// <summary> /// <summary>
/// This game's graphics device manager, initialized in the constructor /// This game's graphics device manager, initialized in the constructor
@ -64,7 +64,7 @@ namespace MLEM.Startup {
/// <param name="windowWidth">The default window width</param> /// <param name="windowWidth">The default window width</param>
/// <param name="windowHeight">The default window height</param> /// <param name="windowHeight">The default window height</param>
public MlemGame(int windowWidth = 1280, int windowHeight = 720) { public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
instance = this; MlemGame.instance = this;
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) { this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
PreferredBackBufferWidth = windowWidth, PreferredBackBufferWidth = windowWidth,
@ -160,7 +160,7 @@ namespace MLEM.Startup {
/// <typeparam name="T">The type of content to load</typeparam> /// <typeparam name="T">The type of content to load</typeparam>
/// <returns>The loaded content</returns> /// <returns>The loaded content</returns>
public static T LoadContent<T>(string name) { public static T LoadContent<T>(string name) {
return instance.Content.Load<T>(name); return MlemGame.instance.Content.Load<T>(name);
} }
/// <summary> /// <summary>

View file

@ -652,7 +652,7 @@ namespace MLEM.Ui.Elements {
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 // with awkward ui scale values, floating point rounding can cause an element that would usually
// be positioned correctly to be pushed into the next line due to a very small deviation // be positioned correctly to be pushed into the next line due to a very small deviation
if (newX + newSize.X <= parentArea.Right + Epsilon) { if (newX + newSize.X <= parentArea.Right + Element.Epsilon) {
pos.X = newX; pos.X = newX;
pos.Y = prevArea.Y + this.ScaledOffset.Y; pos.Y = prevArea.Y + this.ScaledOffset.Y;
} else { } else {
@ -715,7 +715,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, Epsilon)) { if (!autoSize.Equals(this.UnscrolledArea.Size, Element.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?");

View file

@ -118,7 +118,7 @@ namespace MLEM.Ui.Elements {
/// <inheritdoc cref="KeybindButton(MLEM.Ui.Anchor,Microsoft.Xna.Framework.Vector2,MLEM.Input.Keybind,MLEM.Input.InputHandler,string,MLEM.Input.Keybind,string,System.Func{MLEM.Input.GenericInput,string},int,System.Func{MLEM.Input.GenericInput,System.Collections.Generic.IEnumerable{MLEM.Input.GenericInput},bool})"/> /// <inheritdoc cref="KeybindButton(MLEM.Ui.Anchor,Microsoft.Xna.Framework.Vector2,MLEM.Input.Keybind,MLEM.Input.InputHandler,string,MLEM.Input.Keybind,string,System.Func{MLEM.Input.GenericInput,string},int,System.Func{MLEM.Input.GenericInput,System.Collections.Generic.IEnumerable{MLEM.Input.GenericInput},bool})"/>
public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, GenericInput unbindKey = default, string unboundPlaceholder = "", Func<GenericInput, string> inputName = null, int index = 0, Func<GenericInput, IEnumerable<GenericInput>, bool> isKeybindAllowed = null) { public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, GenericInput unbindKey = default, string unboundPlaceholder = "", Func<GenericInput, string> inputName = null, int index = 0, Func<GenericInput, IEnumerable<GenericInput>, bool> isKeybindAllowed = null) {
return KeybindButton(anchor, size, keybind, inputHandler, activePlaceholder, new Keybind(unbindKey), unboundPlaceholder, inputName, index, isKeybindAllowed); return ElementHelper.KeybindButton(anchor, size, keybind, inputHandler, activePlaceholder, new Keybind(unbindKey), unboundPlaceholder, inputName, index, isKeybindAllowed);
} }
/// <summary> /// <summary>
@ -139,7 +139,9 @@ namespace MLEM.Ui.Elements {
/// <param name="isKeybindAllowed">A function that can optionally determine whether a given input and modifier combination is allowed. If this is null, all combinations are allowed.</param> /// <param name="isKeybindAllowed">A function that can optionally determine whether a given input and modifier combination is allowed. If this is null, all combinations are allowed.</param>
/// <returns>A keybind button with the given settings</returns> /// <returns>A keybind button with the given settings</returns>
public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, Keybind unbind = default, string unboundPlaceholder = "", Func<GenericInput, string> inputName = null, int index = 0, Func<GenericInput, IEnumerable<GenericInput>, bool> isKeybindAllowed = null) { public static Button KeybindButton(Anchor anchor, Vector2 size, Keybind keybind, InputHandler inputHandler, string activePlaceholder, Keybind unbind = default, string unboundPlaceholder = "", Func<GenericInput, string> inputName = null, int index = 0, Func<GenericInput, IEnumerable<GenericInput>, bool> isKeybindAllowed = null) {
string GetCurrentName() => keybind.TryGetCombination(index, out var combination) ? combination.ToString(" + ", inputName) : unboundPlaceholder; string GetCurrentName() {
return keybind.TryGetCombination(index, out var combination) ? combination.ToString(" + ", inputName) : unboundPlaceholder;
}
var button = new Button(anchor, size, GetCurrentName()); var button = new Button(anchor, size, GetCurrentName());
var activeNext = false; var activeNext = false;

View file

@ -121,7 +121,7 @@ namespace MLEM.Ui.Elements {
var offset = new Vector2(0, -this.ScrollBar.CurrentValue); var offset = new Vector2(0, -this.ScrollBar.CurrentValue);
// we ignore false grandchildren so that the children of the scroll bar stay in place // we ignore false grandchildren so that the children of the scroll bar stay in place
foreach (var child in this.GetChildren(c => c != this.ScrollBar, true, true)) { foreach (var child in this.GetChildren(c => c != this.ScrollBar, true, true)) {
if (!child.ScrollOffset.Equals(offset, Epsilon)) { if (!child.ScrollOffset.Equals(offset, Element.Epsilon)) {
child.ScrollOffset = offset; child.ScrollOffset = offset;
this.relevantChildrenDirty = true; this.relevantChildrenDirty = true;
} }
@ -246,13 +246,13 @@ namespace MLEM.Ui.Elements {
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components // the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
var scrollBarMax = (childrenHeight - this.ChildPaddedArea.Height) / this.Scale; var scrollBarMax = (childrenHeight - this.ChildPaddedArea.Height) / this.Scale;
if (!this.ScrollBar.MaxValue.Equals(scrollBarMax, Epsilon)) { if (!this.ScrollBar.MaxValue.Equals(scrollBarMax, Element.Epsilon)) {
this.ScrollBar.MaxValue = scrollBarMax; this.ScrollBar.MaxValue = scrollBarMax;
this.relevantChildrenDirty = true; this.relevantChildrenDirty = true;
// update child padding based on whether the scroll bar is visible // update child padding based on whether the scroll bar is visible
var childOffset = this.ScrollBar.IsHidden ? 0 : this.ScrollerSize.Value.X + this.ScrollBarOffset; var childOffset = this.ScrollBar.IsHidden ? 0 : this.ScrollerSize.Value.X + this.ScrollBarOffset;
if (!this.scrollBarChildOffset.Equals(childOffset, Epsilon)) { if (!this.scrollBarChildOffset.Equals(childOffset, Element.Epsilon)) {
this.ChildPadding += new Padding(0, -this.scrollBarChildOffset + childOffset, 0, 0); this.ChildPadding += new Padding(0, -this.scrollBarChildOffset + childOffset, 0, 0);
this.scrollBarChildOffset = childOffset; this.scrollBarChildOffset = childOffset;
this.SetAreaDirty(); this.SetAreaDirty();

View file

@ -197,7 +197,7 @@ namespace MLEM.Ui.Elements {
protected void SetTextDirty() { protected void SetTextDirty() {
this.TokenizedText = null; this.TokenizedText = null;
// only set our area dirty if our size changed as a result of this action // only set our area dirty if our size changed as a result of this action
if (!this.AreaDirty && !this.CalcActualSize(this.ParentArea).Equals(this.DisplayArea.Size, Epsilon)) if (!this.AreaDirty && !this.CalcActualSize(this.ParentArea).Equals(this.DisplayArea.Size, Element.Epsilon))
this.SetAreaDirty(); this.SetAreaDirty();
} }

View file

@ -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 <= Epsilon; var shouldHide = this.maxValue <= Element.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);
@ -188,7 +188,7 @@ namespace MLEM.Ui.Elements {
if (this.SmoothScrolling && this.scrollAdded != 0) { if (this.SmoothScrolling && this.scrollAdded != 0) {
this.scrollAdded *= this.SmoothScrollFactor; this.scrollAdded *= this.SmoothScrollFactor;
if (Math.Abs(this.scrollAdded) <= Epsilon) if (Math.Abs(this.scrollAdded) <= Element.Epsilon)
this.scrollAdded = 0; this.scrollAdded = 0;
this.OnValueChanged?.Invoke(this, this.CurrentValue); this.OnValueChanged?.Invoke(this, this.CurrentValue);
} }

View file

@ -24,7 +24,7 @@ namespace MLEM.Ui.Elements {
// we squish children in order of priority, since auto-anchoring is based on addition order // we squish children in order of priority, since auto-anchoring is based on addition order
for (var i = 0; i < this.SortedChildren.Count; i++) { for (var i = 0; i < this.SortedChildren.Count; i++) {
var child = this.SortedChildren[i]; var child = this.SortedChildren[i];
if (SquishChild(child, out var squished)) if (SquishingGroup.SquishChild(child, out var squished))
child.SetAreaAndUpdateChildren(squished); child.SetAreaAndUpdateChildren(squished);
} }
} }
@ -66,7 +66,7 @@ namespace MLEM.Ui.Elements {
} }
} }
} }
if (!pos.Equals(element.Area.Location, Epsilon) || !size.Equals(element.Area.Size, Epsilon)) { if (!pos.Equals(element.Area.Location, Element.Epsilon) || !size.Equals(element.Area.Size, Element.Epsilon)) {
squishedArea = new RectangleF(pos, size); squishedArea = new RectangleF(pos, size);
return true; return true;
} }

View file

@ -209,7 +209,7 @@ namespace MLEM.Ui.Elements {
/// <param name="text">The text that the text field should contain by default</param> /// <param name="text">The text that the text field should contain by default</param>
/// <param name="multiline">Whether the text field should support multi-line editing</param> /// <param name="multiline">Whether the text field should support multi-line editing</param>
public TextField(Anchor anchor, Vector2 size, Rule rule = null, GenericFont font = null, string text = null, bool multiline = false) : base(anchor, size) { public TextField(Anchor anchor, Vector2 size, Rule rule = null, GenericFont font = null, string text = null, bool multiline = false) : base(anchor, size) {
this.InputRule = rule ?? DefaultRule; this.InputRule = rule ?? TextField.DefaultRule;
this.Multiline = multiline; this.Multiline = multiline;
if (font != null) if (font != null)
this.Font = font; this.Font = font;

View file

@ -62,7 +62,7 @@ namespace MLEM.Ui.Parsers {
this.Style<VerticalSpace>(ElementType.VerticalSpace, v => v.Size = new Vector2(1, 5)); this.Style<VerticalSpace>(ElementType.VerticalSpace, v => v.Size = new Vector2(1, 5));
for (var i = 0; i < 6; i++) { for (var i = 0; i < 6; i++) {
var level = i; var level = i;
this.Style<Paragraph>(ElementTypes[Array.IndexOf(ElementTypes, ElementType.Header1) + i], p => { this.Style<Paragraph>(UiMarkdownParser.ElementTypes[Array.IndexOf(UiMarkdownParser.ElementTypes, ElementType.Header1) + i], p => {
p.Alignment = TextAlignment.Center; p.Alignment = TextAlignment.Center;
p.TextScaleMultiplier = 2 - level * 0.15F; p.TextScaleMultiplier = 2 - level * 0.15F;
}); });
@ -107,7 +107,7 @@ namespace MLEM.Ui.Parsers {
/// <typeparam name="T">The type of elements that the given <see cref="ElementType"/> flags are expected to be.</typeparam> /// <typeparam name="T">The type of elements that the given <see cref="ElementType"/> flags are expected to be.</typeparam>
/// <returns>This parser, for chaining.</returns> /// <returns>This parser, for chaining.</returns>
public UiMarkdownParser Style<T>(ElementType types, Action<T> style, bool add = false) where T : Element { public UiMarkdownParser Style<T>(ElementType types, Action<T> style, bool add = false) where T : Element {
foreach (var type in ElementTypes) { foreach (var type in UiMarkdownParser.ElementTypes) {
if (types.HasFlag(type)) { if (types.HasFlag(type)) {
if (add && this.elementStyles.ContainsKey(type)) { if (add && this.elementStyles.ContainsKey(type)) {
this.elementStyles[type] += Action; this.elementStyles[type] += Action;
@ -193,7 +193,7 @@ namespace MLEM.Ui.Parsers {
var parsedHeader = false; var parsedHeader = false;
for (var h = 6; h >= 1; h--) { for (var h = 6; h >= 1; h--) {
if (line.StartsWith(new string('#', h))) { if (line.StartsWith(new string('#', h))) {
var type = ElementTypes[Array.IndexOf(ElementTypes, ElementType.Header1) + h - 1]; var type = UiMarkdownParser.ElementTypes[Array.IndexOf(UiMarkdownParser.ElementTypes, ElementType.Header1) + h - 1];
yield return (type, new Paragraph(Anchor.AutoLeft, 1, line.Substring(h).Trim())); yield return (type, new Paragraph(Anchor.AutoLeft, 1, line.Substring(h).Trim()));
parsedHeader = true; parsedHeader = true;
break; break;
@ -275,7 +275,7 @@ namespace MLEM.Ui.Parsers {
/// A combined flag that contains <see cref="Header1"/> through <see cref="Header6"/>. /// A combined flag that contains <see cref="Header1"/> through <see cref="Header6"/>.
/// This element type is a <see cref="Paragraph"/>. /// This element type is a <see cref="Paragraph"/>.
/// </summary> /// </summary>
Headers = Header1 | Header2 | Header3 | Header4 | Header5 | Header6, Headers = ElementType.Header1 | ElementType.Header2 | ElementType.Header3 | ElementType.Header4 | ElementType.Header5 | ElementType.Header6,
/// <summary> /// <summary>
/// A paragraph, which is one line of markdown text. /// A paragraph, which is one line of markdown text.
/// This element type is a <see cref="Paragraph"/>. /// This element type is a <see cref="Paragraph"/>.

View file

@ -164,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, Epsilon); return !this.Position.Equals(lastPos, Camera.Epsilon);
} }
/// <summary> /// <summary>

View file

@ -15,9 +15,9 @@ namespace MLEM.Extensions {
/// <param name="c">The character to turn into a string</param> /// <param name="c">The character to turn into a string</param>
/// <returns>A string representing the character</returns> /// <returns>A string representing the character</returns>
public static string ToCachedString(this char c) { public static string ToCachedString(this char c) {
if (!Cache.TryGetValue(c, out var ret)) { if (!CharExtensions.Cache.TryGetValue(c, out var ret)) {
ret = c.ToString(); ret = c.ToString();
Cache.Add(c, ret); CharExtensions.Cache.Add(c, ret);
} }
return ret; return ret;
} }

View file

@ -50,7 +50,7 @@ namespace MLEM.Extensions {
/// <param name="value">The number to parse.</param> /// <param name="value">The number to parse.</param>
/// <returns>The resulting color.</returns> /// <returns>The resulting color.</returns>
public static Color FromHexRgba(int value) { public static Color FromHexRgba(int value) {
return new Color((value >> 16) & 0xFF, (value >> 8) & 0xFF, (value >> 0) & 0xFF, (value >> 24) & 0xFF); return new Color(value >> 16 & 0xFF, value >> 8 & 0xFF, value >> 0 & 0xFF, value >> 24 & 0xFF);
} }
/// <summary> /// <summary>
@ -60,7 +60,7 @@ namespace MLEM.Extensions {
/// <param name="value">The number to parse.</param> /// <param name="value">The number to parse.</param>
/// <returns>The resulting color.</returns> /// <returns>The resulting color.</returns>
public static Color FromHexRgb(int value) { public static Color FromHexRgb(int value) {
return new Color((value >> 16) & 0xFF, (value >> 8) & 0xFF, (value >> 0) & 0xFF); return new Color(value >> 16 & 0xFF, value >> 8 & 0xFF, value >> 0 & 0xFF);
} }
/// <summary> /// <summary>
@ -73,7 +73,7 @@ namespace MLEM.Extensions {
if (value.StartsWith("#")) if (value.StartsWith("#"))
value = value.Substring(1); value = value.Substring(1);
var val = int.Parse(value, NumberStyles.HexNumber); var val = int.Parse(value, NumberStyles.HexNumber);
return value.Length > 6 ? FromHexRgba(val) : FromHexRgb(val); return value.Length > 6 ? ColorHelper.FromHexRgba(val) : ColorHelper.FromHexRgb(val);
} }
} }

View file

@ -21,18 +21,18 @@ namespace MLEM.Extensions {
manager.IsFullScreen = fullscreen; manager.IsFullScreen = fullscreen;
if (fullscreen) { if (fullscreen) {
var view = manager.GraphicsDevice.Viewport; var view = manager.GraphicsDevice.Viewport;
lastWidth = view.Width; GraphicsExtensions.lastWidth = view.Width;
lastHeight = view.Height; GraphicsExtensions.lastHeight = view.Height;
var curr = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode; var curr = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode;
manager.PreferredBackBufferWidth = curr.Width; manager.PreferredBackBufferWidth = curr.Width;
manager.PreferredBackBufferHeight = curr.Height; manager.PreferredBackBufferHeight = curr.Height;
} else { } else {
if (lastWidth <= 0 || lastHeight <= 0) if (GraphicsExtensions.lastWidth <= 0 || GraphicsExtensions.lastHeight <= 0)
throw new InvalidOperationException("Can't call SetFullscreen to change out of fullscreen mode without going into fullscreen mode first"); throw new InvalidOperationException("Can't call SetFullscreen to change out of fullscreen mode without going into fullscreen mode first");
manager.PreferredBackBufferWidth = lastWidth; manager.PreferredBackBufferWidth = GraphicsExtensions.lastWidth;
manager.PreferredBackBufferHeight = lastHeight; manager.PreferredBackBufferHeight = GraphicsExtensions.lastHeight;
} }
manager.ApplyChanges(); manager.ApplyChanges();
} }

View file

@ -19,12 +19,12 @@ namespace MLEM.Extensions {
/// <param name="batch">The sprite batch</param> /// <param name="batch">The sprite batch</param>
/// <returns>A 1x1 pixel white texture</returns> /// <returns>A 1x1 pixel white texture</returns>
public static Texture2D GetBlankTexture(this SpriteBatch batch) { public static Texture2D GetBlankTexture(this SpriteBatch batch) {
if (blankTexture == null) { if (SpriteBatchExtensions.blankTexture == null) {
blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1); SpriteBatchExtensions.blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1);
blankTexture.SetData(new[] {Color.White}); SpriteBatchExtensions.blankTexture.SetData(new[] {Color.White});
AutoDispose(batch, blankTexture); SpriteBatchExtensions.AutoDispose(batch, SpriteBatchExtensions.blankTexture);
} }
return blankTexture; return SpriteBatchExtensions.blankTexture;
} }
/// <summary> /// <summary>
@ -43,7 +43,7 @@ namespace MLEM.Extensions {
outli, color, outli, outli, color, outli,
outli, outli, outli outli, outli, outli
}); });
AutoDispose(batch, tex); SpriteBatchExtensions.AutoDispose(batch, tex);
return new NinePatch(tex, 1); return new NinePatch(tex, 1);
} }
@ -57,7 +57,7 @@ namespace MLEM.Extensions {
public static Texture2D GenerateSquareTexture(this SpriteBatch batch, Color color) { public static Texture2D GenerateSquareTexture(this SpriteBatch batch, Color color) {
var tex = new Texture2D(batch.GraphicsDevice, 1, 1); var tex = new Texture2D(batch.GraphicsDevice, 1, 1);
tex.SetData(new[] {color}); tex.SetData(new[] {color});
AutoDispose(batch, tex); SpriteBatchExtensions.AutoDispose(batch, tex);
return tex; return tex;
} }
@ -80,7 +80,7 @@ namespace MLEM.Extensions {
} }
} }
} }
AutoDispose(batch, tex); SpriteBatchExtensions.AutoDispose(batch, tex);
return tex; return tex;
} }
@ -107,7 +107,7 @@ namespace MLEM.Extensions {
data[x, y] = Color.Lerp(top, btm, y / (float) height); data[x, y] = Color.Lerp(top, btm, y / (float) height);
} }
} }
AutoDispose(batch, tex); SpriteBatchExtensions.AutoDispose(batch, tex);
return tex; return tex;
} }

View file

@ -21,7 +21,7 @@ namespace MLEM.Font {
public const char Emsp = '\u2003'; public const char Emsp = '\u2003';
/// <inheritdoc cref="Emsp"/> /// <inheritdoc cref="Emsp"/>
[Obsolete("Use the Emsp field instead.")] [Obsolete("Use the Emsp field instead.")]
public const char OneEmSpace = Emsp; public const char OneEmSpace = GenericFont.Emsp;
/// <summary> /// <summary>
/// This field holds the unicode representation of a non-breaking space. /// 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)"/>. /// 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)"/>.
@ -185,17 +185,17 @@ namespace MLEM.Font {
xOffset = 0; xOffset = 0;
size.Y += this.LineHeight; size.Y += this.LineHeight;
break; break;
case Emsp: case GenericFont.Emsp:
xOffset += this.LineHeight; xOffset += this.LineHeight;
break; break;
case Nbsp: case GenericFont.Nbsp:
xOffset += font.MeasureChar(' '); xOffset += font.MeasureChar(' ');
break; break;
case Zwsp: case GenericFont.Zwsp:
// don't add width for a zero-width space // don't add width for a zero-width space
break; break;
case ' ': case ' ':
if (ignoreTrailingSpaces && IsTrailingSpace(text, i)) { if (ignoreTrailingSpaces && GenericFont.IsTrailingSpace(text, i)) {
// if this is a trailing space, we can skip remaining spaces too // if this is a trailing space, we can skip remaining spaces too
i = text.Length - 1; i = text.Length - 1;
break; break;
@ -252,7 +252,7 @@ namespace MLEM.Font {
} else { } else {
var font = fontFunction?.Invoke(i) ?? this; var font = fontFunction?.Invoke(i) ?? this;
var cWidth = font.MeasureString(c.ToCachedString()).X * scale; var cWidth = font.MeasureString(c.ToCachedString()).X * scale;
if (c == ' ' || c == Emsp || c == Zwsp) { if (c == ' ' || c == GenericFont.Emsp || c == GenericFont.Zwsp) {
// remember the location of this (breaking!) space // remember the location of this (breaking!) space
lastSpaceIndex = curr.Length; lastSpaceIndex = curr.Length;
widthSinceLastSpace = 0; widthSinceLastSpace = 0;

View file

@ -26,9 +26,9 @@ namespace MLEM.Font {
/// <param name="bold">A bold version of the font</param> /// <param name="bold">A bold version of the font</param>
/// <param name="italic">An italic version of the font</param> /// <param name="italic">An italic version of the font</param>
public GenericSpriteFont(SpriteFont font, SpriteFont bold = null, SpriteFont italic = null) { public GenericSpriteFont(SpriteFont font, SpriteFont bold = null, SpriteFont italic = null) {
this.Font = SetDefaults(font); this.Font = GenericSpriteFont.SetDefaults(font);
this.Bold = bold != null ? new GenericSpriteFont(SetDefaults(bold)) : this; this.Bold = bold != null ? new GenericSpriteFont(GenericSpriteFont.SetDefaults(bold)) : this;
this.Italic = italic != null ? new GenericSpriteFont(SetDefaults(italic)) : this; this.Italic = italic != null ? new GenericSpriteFont(GenericSpriteFont.SetDefaults(italic)) : this;
} }
/// <inheritdoc /> /// <inheritdoc />

View file

@ -87,13 +87,13 @@ namespace MLEM.Formatting {
// if we've reached the end of the string // if we've reached the end of the string
if (next == null) { if (next == null) {
var sub = s.Substring(rawIndex, s.Length - rawIndex); var sub = s.Substring(rawIndex, s.Length - rawIndex);
tokens.Add(new Token(codes.ToArray(), index, rawIndex, StripFormatting(font, sub, codes), sub)); tokens.Add(new Token(codes.ToArray(), index, rawIndex, TextFormatter.StripFormatting(font, sub, codes), sub));
break; break;
} }
// create a new token for the content up to the next code // create a new token for the content up to the next code
var ret = s.Substring(rawIndex, next.Match.Index - rawIndex); var ret = s.Substring(rawIndex, next.Match.Index - rawIndex);
var strippedRet = StripFormatting(font, ret, codes); var strippedRet = TextFormatter.StripFormatting(font, ret, codes);
tokens.Add(new Token(codes.ToArray(), index, rawIndex, strippedRet, ret)); tokens.Add(new Token(codes.ToArray(), index, rawIndex, strippedRet, ret));
// move to the start of the next code // move to the start of the next code
@ -104,7 +104,7 @@ namespace MLEM.Formatting {
codes.RemoveAll(c => c.EndsHere(next)); codes.RemoveAll(c => c.EndsHere(next));
codes.Add(next); codes.Add(next);
} }
return new TokenizedString(font, alignment, s, StripFormatting(font, s, tokens.SelectMany(t => t.AppliedCodes)), tokens.ToArray()); return new TokenizedString(font, alignment, s, TextFormatter.StripFormatting(font, s, tokens.SelectMany(t => t.AppliedCodes)), tokens.ToArray());
} }
/// <summary> /// <summary>

View file

@ -35,7 +35,7 @@ namespace MLEM.Graphics {
public static void DrawAutoTile(SpriteBatch batch, Vector2 pos, TextureRegion texture, ConnectsTo connectsTo, Color color, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0) { public static void DrawAutoTile(SpriteBatch batch, Vector2 pos, TextureRegion texture, ConnectsTo connectsTo, Color color, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0) {
var orig = origin ?? Vector2.Zero; var orig = origin ?? Vector2.Zero;
var sc = scale ?? Vector2.One; var sc = scale ?? Vector2.One;
var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, texture.Area, connectsTo, sc); var (p1, r1, p2, r2, p3, r3, p4, r4) = AutoTiling.CalculateAutoTile(pos, texture.Area, connectsTo, sc);
batch.Draw(texture.Texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth); batch.Draw(texture.Texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth);
batch.Draw(texture.Texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth); batch.Draw(texture.Texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth);
batch.Draw(texture.Texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth); batch.Draw(texture.Texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth);
@ -46,7 +46,7 @@ namespace MLEM.Graphics {
public static void AddAutoTile(StaticSpriteBatch batch, Vector2 pos, TextureRegion texture, ConnectsTo connectsTo, Color color, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0, ICollection<StaticSpriteBatch.Item> items = null) { public static void AddAutoTile(StaticSpriteBatch batch, Vector2 pos, TextureRegion texture, ConnectsTo connectsTo, Color color, Vector2? origin = null, Vector2? scale = null, float layerDepth = 0, ICollection<StaticSpriteBatch.Item> items = null) {
var orig = origin ?? Vector2.Zero; var orig = origin ?? Vector2.Zero;
var sc = scale ?? Vector2.One; var sc = scale ?? Vector2.One;
var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, texture.Area, connectsTo, sc); var (p1, r1, p2, r2, p3, r3, p4, r4) = AutoTiling.CalculateAutoTile(pos, texture.Area, connectsTo, sc);
var a1 = batch.Add(texture.Texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth); var a1 = batch.Add(texture.Texture, p1, r1, color, 0, orig, sc, SpriteEffects.None, layerDepth);
var a2 = batch.Add(texture.Texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth); var a2 = batch.Add(texture.Texture, p2, r2, color, 0, orig, sc, SpriteEffects.None, layerDepth);
var a3 = batch.Add(texture.Texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth); var a3 = batch.Add(texture.Texture, p3, r3, color, 0, orig, sc, SpriteEffects.None, layerDepth);
@ -88,7 +88,7 @@ namespace MLEM.Graphics {
var orig = origin ?? Vector2.Zero; var orig = origin ?? Vector2.Zero;
var sc = scale ?? Vector2.One; var sc = scale ?? Vector2.One;
var od = layerDepth + overlayDepthOffset; var od = layerDepth + overlayDepthOffset;
var (r1, r2, r3, r4) = CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc); var (r1, r2, r3, r4) = AutoTiling.CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
if (backgroundTexture != null) if (backgroundTexture != null)
batch.Draw(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth); batch.Draw(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth);
if (r1 != Rectangle.Empty) if (r1 != Rectangle.Empty)
@ -106,7 +106,7 @@ namespace MLEM.Graphics {
var orig = origin ?? Vector2.Zero; var orig = origin ?? Vector2.Zero;
var sc = scale ?? Vector2.One; var sc = scale ?? Vector2.One;
var od = layerDepth + overlayDepthOffset; var od = layerDepth + overlayDepthOffset;
var (r1, r2, r3, r4) = CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc); var (r1, r2, r3, r4) = AutoTiling.CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
if (backgroundTexture != null) { if (backgroundTexture != null) {
var background = batch.Add(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth); var background = batch.Add(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth);
items?.Add(background); items?.Add(background);

View file

@ -14,7 +14,7 @@ namespace MLEM.Graphics {
// this maximum is limited by indices being a short // this maximum is limited by indices being a short
private const int MaxBatchItems = short.MaxValue / 6; private const int MaxBatchItems = short.MaxValue / 6;
private static readonly VertexPositionColorTexture[] Data = new VertexPositionColorTexture[MaxBatchItems * 4]; private static readonly VertexPositionColorTexture[] Data = new VertexPositionColorTexture[StaticSpriteBatch.MaxBatchItems * 4];
/// <summary> /// <summary>
/// The amount of vertices that are currently batched. /// The amount of vertices that are currently batched.
@ -106,21 +106,21 @@ namespace MLEM.Graphics {
Texture2D texture = null; Texture2D texture = null;
foreach (var item in ordered) { foreach (var item in ordered) {
// if the texture changes, we also have to start a new buffer! // if the texture changes, we also have to start a new buffer!
if (dataIndex > 0 && (item.Texture != texture || dataIndex >= Data.Length)) { if (dataIndex > 0 && (item.Texture != texture || dataIndex >= StaticSpriteBatch.Data.Length)) {
this.FillBuffer(this.FilledBuffers++, texture, Data); this.FillBuffer(this.FilledBuffers++, texture, StaticSpriteBatch.Data);
dataIndex = 0; dataIndex = 0;
} }
Data[dataIndex++] = item.TopLeft; StaticSpriteBatch.Data[dataIndex++] = item.TopLeft;
Data[dataIndex++] = item.TopRight; StaticSpriteBatch.Data[dataIndex++] = item.TopRight;
Data[dataIndex++] = item.BottomLeft; StaticSpriteBatch.Data[dataIndex++] = item.BottomLeft;
Data[dataIndex++] = item.BottomRight; StaticSpriteBatch.Data[dataIndex++] = item.BottomRight;
texture = item.Texture; texture = item.Texture;
} }
if (dataIndex > 0) if (dataIndex > 0)
this.FillBuffer(this.FilledBuffers++, texture, Data); this.FillBuffer(this.FilledBuffers++, texture, StaticSpriteBatch.Data);
// ensure we have enough indices // ensure we have enough indices
var maxItems = Math.Min(this.items.Count, MaxBatchItems); var maxItems = Math.Min(this.items.Count, StaticSpriteBatch.MaxBatchItems);
// each item has 2 triangles which each have 3 indices // each item has 2 triangles which each have 3 indices
if (this.indices == null || this.indices.IndexCount < 6 * maxItems) { if (this.indices == null || this.indices.IndexCount < 6 * maxItems) {
var newIndices = new short[6 * maxItems]; var newIndices = new short[6 * maxItems];
@ -434,7 +434,7 @@ namespace MLEM.Graphics {
private void FillBuffer(int index, Texture2D texture, VertexPositionColorTexture[] data) { private void FillBuffer(int index, Texture2D texture, VertexPositionColorTexture[] data) {
if (this.vertexBuffers.Count <= index) if (this.vertexBuffers.Count <= index)
this.vertexBuffers.Add(new VertexBuffer(this.graphicsDevice, VertexPositionColorTexture.VertexDeclaration, MaxBatchItems * 4, BufferUsage.WriteOnly)); this.vertexBuffers.Add(new VertexBuffer(this.graphicsDevice, VertexPositionColorTexture.VertexDeclaration, StaticSpriteBatch.MaxBatchItems * 4, BufferUsage.WriteOnly));
this.vertexBuffers[index].SetData(data); this.vertexBuffers[index].SetData(data);
this.textures.Insert(index, texture); this.textures.Insert(index, texture);
} }

View file

@ -107,7 +107,7 @@ namespace MLEM.Input {
/// <summary>Returns the hash code for this instance.</summary> /// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns> /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode() { public override int GetHashCode() {
return ((int) this.Type * 397) ^ this.value; return (int) this.Type * 397 ^ this.value;
} }
/// <summary> /// <summary>

View file

@ -829,9 +829,9 @@ namespace MLEM.Input {
/// <param name="gestures">The gestures to enable or disable</param> /// <param name="gestures">The gestures to enable or disable</param>
public static void SetGesturesEnabled(bool enabled, params GestureType[] gestures) { public static void SetGesturesEnabled(bool enabled, params GestureType[] gestures) {
if (enabled) { if (enabled) {
EnableGestures(gestures); InputHandler.EnableGestures(gestures);
} else { } else {
DisableGestures(gestures); InputHandler.DisableGestures(gestures);
} }
} }

View file

@ -231,9 +231,9 @@ namespace MLEM.Input {
/// ///
/// <list type="table"><listheader><term> Value</term><description> Meaning</description></listheader><item><term> Less than zero</term><description> This instance precedes <paramref name="obj" /> in the sort order.</description></item><item><term> Zero</term><description> This instance occurs in the same position in the sort order as <paramref name="obj" />.</description></item><item><term> Greater than zero</term><description> This instance follows <paramref name="obj" /> in the sort order.</description></item></list></returns> /// <list type="table"><listheader><term> Value</term><description> Meaning</description></listheader><item><term> Less than zero</term><description> This instance precedes <paramref name="obj" /> in the sort order.</description></item><item><term> Zero</term><description> This instance occurs in the same position in the sort order as <paramref name="obj" />.</description></item><item><term> Greater than zero</term><description> This instance follows <paramref name="obj" /> in the sort order.</description></item></list></returns>
public int CompareTo(object obj) { public int CompareTo(object obj) {
if (ReferenceEquals(null, obj)) if (object.ReferenceEquals(null, obj))
return 1; return 1;
if (ReferenceEquals(this, obj)) if (object.ReferenceEquals(this, obj))
return 0; return 0;
if (!(obj is Keybind other)) if (!(obj is Keybind other))
throw new ArgumentException($"Object must be of type {nameof(Keybind)}"); throw new ArgumentException($"Object must be of type {nameof(Keybind)}");
@ -369,9 +369,9 @@ namespace MLEM.Input {
/// ///
/// <list type="table"><listheader><term> Value</term><description> Meaning</description></listheader><item><term> Less than zero</term><description> This instance precedes <paramref name="obj" /> in the sort order.</description></item><item><term> Zero</term><description> This instance occurs in the same position in the sort order as <paramref name="obj" />.</description></item><item><term> Greater than zero</term><description> This instance follows <paramref name="obj" /> in the sort order.</description></item></list></returns> /// <list type="table"><listheader><term> Value</term><description> Meaning</description></listheader><item><term> Less than zero</term><description> This instance precedes <paramref name="obj" /> in the sort order.</description></item><item><term> Zero</term><description> This instance occurs in the same position in the sort order as <paramref name="obj" />.</description></item><item><term> Greater than zero</term><description> This instance follows <paramref name="obj" /> in the sort order.</description></item></list></returns>
public int CompareTo(object obj) { public int CompareTo(object obj) {
if (ReferenceEquals(null, obj)) if (object.ReferenceEquals(null, obj))
return 1; return 1;
if (ReferenceEquals(this, obj)) if (object.ReferenceEquals(this, obj))
return 0; return 0;
if (!(obj is Combination other)) if (!(obj is Combination other))
throw new ArgumentException($"Object must be of type {nameof(Combination)}"); throw new ArgumentException($"Object must be of type {nameof(Combination)}");

View file

@ -18,7 +18,7 @@ namespace MLEM.Input {
{ModifierKey.Control, new[] {Keys.LeftControl, Keys.RightControl}}, {ModifierKey.Control, new[] {Keys.LeftControl, Keys.RightControl}},
{ModifierKey.Alt, new[] {Keys.LeftAlt, Keys.RightAlt}} {ModifierKey.Alt, new[] {Keys.LeftAlt, Keys.RightAlt}}
}; };
private static readonly Dictionary<Keys, ModifierKey> ModifiersLookup = KeysLookup private static readonly Dictionary<Keys, ModifierKey> ModifiersLookup = KeysExtensions.KeysLookup
.SelectMany(kv => kv.Value.Select(v => (kv.Key, v))) .SelectMany(kv => kv.Value.Select(v => (kv.Key, v)))
.ToDictionary(kv => kv.Item2, kv => kv.Item1); .ToDictionary(kv => kv.Item2, kv => kv.Item1);
@ -28,7 +28,7 @@ namespace MLEM.Input {
/// <param name="modifier">The modifier key</param> /// <param name="modifier">The modifier key</param>
/// <returns>All of the keys the modifier key represents</returns> /// <returns>All of the keys the modifier key represents</returns>
public static IEnumerable<Keys> GetKeys(this ModifierKey modifier) { public static IEnumerable<Keys> GetKeys(this ModifierKey modifier) {
return KeysLookup.TryGetValue(modifier, out var keys) ? keys : Enumerable.Empty<Keys>(); return KeysExtensions.KeysLookup.TryGetValue(modifier, out var keys) ? keys : Enumerable.Empty<Keys>();
} }
/// <summary> /// <summary>
@ -38,12 +38,12 @@ namespace MLEM.Input {
/// <param name="key">The key to convert to a modifier key</param> /// <param name="key">The key to convert to a modifier key</param>
/// <returns>The modifier key, or <see cref="ModifierKey.None"/></returns> /// <returns>The modifier key, or <see cref="ModifierKey.None"/></returns>
public static ModifierKey GetModifier(this Keys key) { public static ModifierKey GetModifier(this Keys key) {
return ModifiersLookup.TryGetValue(key, out var mod) ? mod : ModifierKey.None; return KeysExtensions.ModifiersLookup.TryGetValue(key, out var mod) ? mod : ModifierKey.None;
} }
/// <inheritdoc cref="GetModifier(Microsoft.Xna.Framework.Input.Keys)"/> /// <inheritdoc cref="GetModifier(Microsoft.Xna.Framework.Input.Keys)"/>
public static ModifierKey GetModifier(this GenericInput input) { public static ModifierKey GetModifier(this GenericInput input) {
return input.Type == GenericInput.InputType.Keyboard ? GetModifier((Keys) input) : ModifierKey.None; return input.Type == GenericInput.InputType.Keyboard ? ((Keys) input).GetModifier() : ModifierKey.None;
} }
/// <summary> /// <summary>
@ -52,12 +52,12 @@ namespace MLEM.Input {
/// <param name="key">The key</param> /// <param name="key">The key</param>
/// <returns>If the key is a modifier key</returns> /// <returns>If the key is a modifier key</returns>
public static bool IsModifier(this Keys key) { public static bool IsModifier(this Keys key) {
return GetModifier(key) != ModifierKey.None; return key.GetModifier() != ModifierKey.None;
} }
/// <inheritdoc cref="IsModifier(Microsoft.Xna.Framework.Input.Keys)"/> /// <inheritdoc cref="IsModifier(Microsoft.Xna.Framework.Input.Keys)"/>
public static bool IsModifier(this GenericInput input) { public static bool IsModifier(this GenericInput input) {
return GetModifier(input) != ModifierKey.None; return input.GetModifier() != ModifierKey.None;
} }
} }

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using static MLEM.Misc.Direction2;
namespace MLEM.Misc { namespace MLEM.Misc {
/// <summary> /// <summary>
@ -45,22 +44,22 @@ namespace MLEM.Misc {
/// The up and right direction, or +x, -y. /// The up and right direction, or +x, -y.
/// </summary> /// </summary>
[EnumMember] [EnumMember]
UpRight = Up | Right, UpRight = Direction2.Up | Direction2.Right,
/// <summary> /// <summary>
/// The down and right direction, or +x, +y. /// The down and right direction, or +x, +y.
/// </summary> /// </summary>
[EnumMember] [EnumMember]
DownRight = Down | Right, DownRight = Direction2.Down | Direction2.Right,
/// <summary> /// <summary>
/// The up and left direction, or -x, -y. /// The up and left direction, or -x, -y.
/// </summary> /// </summary>
[EnumMember] [EnumMember]
UpLeft = Up | Left, UpLeft = Direction2.Up | Direction2.Left,
/// <summary> /// <summary>
/// The down and left direction, or -x, +y. /// The down and left direction, or -x, +y.
/// </summary> /// </summary>
[EnumMember] [EnumMember]
DownLeft = Down | Left DownLeft = Direction2.Down | Direction2.Left
} }
@ -76,18 +75,18 @@ namespace MLEM.Misc {
/// <summary> /// <summary>
/// The <see cref="Direction2.Up"/> through <see cref="Direction2.Left"/> directions /// The <see cref="Direction2.Up"/> through <see cref="Direction2.Left"/> directions
/// </summary> /// </summary>
public static readonly Direction2[] Adjacent = All.Where(IsAdjacent).ToArray(); public static readonly Direction2[] Adjacent = Direction2Helper.All.Where(Direction2Helper.IsAdjacent).ToArray();
/// <summary> /// <summary>
/// The <see cref="Direction2.UpRight"/> through <see cref="Direction2.UpLeft"/> directions /// The <see cref="Direction2.UpRight"/> through <see cref="Direction2.UpLeft"/> directions
/// </summary> /// </summary>
public static readonly Direction2[] Diagonals = All.Where(IsDiagonal).ToArray(); public static readonly Direction2[] Diagonals = Direction2Helper.All.Where(Direction2Helper.IsDiagonal).ToArray();
/// <summary> /// <summary>
/// All directions except <see cref="Direction2.None"/> /// All directions except <see cref="Direction2.None"/>
/// </summary> /// </summary>
public static readonly Direction2[] AllExceptNone = All.Where(dir => dir != None).ToArray(); public static readonly Direction2[] AllExceptNone = Direction2Helper.All.Where(dir => dir != Direction2.None).ToArray();
private static readonly Direction2[] Clockwise = {Up, UpRight, Right, DownRight, Down, DownLeft, Left, UpLeft}; private static readonly Direction2[] Clockwise = {Direction2.Up, Direction2.UpRight, Direction2.Right, Direction2.DownRight, Direction2.Down, Direction2.DownLeft, Direction2.Left, Direction2.UpLeft};
private static readonly Dictionary<Direction2, int> ClockwiseLookup = Clockwise.Select((d, i) => (d, i)).ToDictionary(kv => kv.d, kv => kv.i); private static readonly Dictionary<Direction2, int> ClockwiseLookup = Direction2Helper.Clockwise.Select((d, i) => (d, i)).ToDictionary(kv => kv.d, kv => kv.i);
/// <summary> /// <summary>
/// Returns if the given direction is considered an "adjacent" direction. /// Returns if the given direction is considered an "adjacent" direction.
@ -96,7 +95,7 @@ namespace MLEM.Misc {
/// <param name="dir">The direction to query</param> /// <param name="dir">The direction to query</param>
/// <returns>Whether the direction is adjacent</returns> /// <returns>Whether the direction is adjacent</returns>
public static bool IsAdjacent(this Direction2 dir) { public static bool IsAdjacent(this Direction2 dir) {
return dir == Up || dir == Right || dir == Down || dir == Left; return dir == Direction2.Up || dir == Direction2.Right || dir == Direction2.Down || dir == Direction2.Left;
} }
/// <summary> /// <summary>
@ -105,7 +104,7 @@ namespace MLEM.Misc {
/// <param name="dir">The direction to query</param> /// <param name="dir">The direction to query</param>
/// <returns>Whether the direction is diagonal</returns> /// <returns>Whether the direction is diagonal</returns>
public static bool IsDiagonal(this Direction2 dir) { public static bool IsDiagonal(this Direction2 dir) {
return dir == UpRight || dir == DownRight || dir == UpLeft || dir == DownLeft; return dir == Direction2.UpRight || dir == Direction2.DownRight || dir == Direction2.UpLeft || dir == Direction2.DownLeft;
} }
/// <summary> /// <summary>
@ -116,21 +115,21 @@ namespace MLEM.Misc {
/// <returns>The direction's offset</returns> /// <returns>The direction's offset</returns>
public static Point Offset(this Direction2 dir) { public static Point Offset(this Direction2 dir) {
switch (dir) { switch (dir) {
case Up: case Direction2.Up:
return new Point(0, -1); return new Point(0, -1);
case Right: case Direction2.Right:
return new Point(1, 0); return new Point(1, 0);
case Down: case Direction2.Down:
return new Point(0, 1); return new Point(0, 1);
case Left: case Direction2.Left:
return new Point(-1, 0); return new Point(-1, 0);
case UpRight: case Direction2.UpRight:
return new Point(1, -1); return new Point(1, -1);
case DownRight: case Direction2.DownRight:
return new Point(1, 1); return new Point(1, 1);
case DownLeft: case Direction2.DownLeft:
return new Point(-1, 1); return new Point(-1, 1);
case UpLeft: case Direction2.UpLeft:
return new Point(-1, -1); return new Point(-1, -1);
default: default:
return Point.Zero; return Point.Zero;
@ -156,24 +155,24 @@ namespace MLEM.Misc {
/// <returns>The opposite of the direction</returns> /// <returns>The opposite of the direction</returns>
public static Direction2 Opposite(this Direction2 dir) { public static Direction2 Opposite(this Direction2 dir) {
switch (dir) { switch (dir) {
case Up: case Direction2.Up:
return Down; return Direction2.Down;
case Right: case Direction2.Right:
return Left; return Direction2.Left;
case Down: case Direction2.Down:
return Up; return Direction2.Up;
case Left: case Direction2.Left:
return Right; return Direction2.Right;
case UpRight: case Direction2.UpRight:
return DownLeft; return Direction2.DownLeft;
case DownRight: case Direction2.DownRight:
return UpLeft; return Direction2.UpLeft;
case DownLeft: case Direction2.DownLeft:
return UpRight; return Direction2.UpRight;
case UpLeft: case Direction2.UpLeft:
return DownRight; return Direction2.DownRight;
default: default:
return None; return Direction2.None;
} }
} }
@ -194,9 +193,9 @@ namespace MLEM.Misc {
/// <param name="fortyFiveDegrees">Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead.</param> /// <param name="fortyFiveDegrees">Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead.</param>
/// <returns>The rotated direction</returns> /// <returns>The rotated direction</returns>
public static Direction2 RotateCw(this Direction2 dir, bool fortyFiveDegrees = false) { public static Direction2 RotateCw(this Direction2 dir, bool fortyFiveDegrees = false) {
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex)) if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
return None; return Direction2.None;
return Clockwise[(dirIndex + (fortyFiveDegrees ? 1 : 2)) % Clockwise.Length]; return Direction2Helper.Clockwise[(dirIndex + (fortyFiveDegrees ? 1 : 2)) % Direction2Helper.Clockwise.Length];
} }
/// <summary> /// <summary>
@ -206,10 +205,10 @@ namespace MLEM.Misc {
/// <param name="fortyFiveDegrees">Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead.</param> /// <param name="fortyFiveDegrees">Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead.</param>
/// <returns>The rotated direction</returns> /// <returns>The rotated direction</returns>
public static Direction2 RotateCcw(this Direction2 dir, bool fortyFiveDegrees = false) { public static Direction2 RotateCcw(this Direction2 dir, bool fortyFiveDegrees = false) {
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex)) if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
return None; return Direction2.None;
var index = dirIndex - (fortyFiveDegrees ? 1 : 2); var index = dirIndex - (fortyFiveDegrees ? 1 : 2);
return Clockwise[index < 0 ? index + Clockwise.Length : index]; return Direction2Helper.Clockwise[index < 0 ? index + Direction2Helper.Clockwise.Length : index];
} }
/// <summary> /// <summary>
@ -219,11 +218,11 @@ namespace MLEM.Misc {
/// <returns>The vector's direction</returns> /// <returns>The vector's direction</returns>
public static Direction2 ToDirection(this Vector2 offset) { public static Direction2 ToDirection(this Vector2 offset) {
var offsetAngle = (float) Math.Atan2(offset.Y, offset.X); var offsetAngle = (float) Math.Atan2(offset.Y, offset.X);
foreach (var dir in AllExceptNone) { foreach (var dir in Direction2Helper.AllExceptNone) {
if (Math.Abs(dir.Angle() - offsetAngle) <= MathHelper.PiOver4 / 2) if (Math.Abs(dir.Angle() - offsetAngle) <= MathHelper.PiOver4 / 2)
return dir; return dir;
} }
return None; return Direction2.None;
} }
/// <summary> /// <summary>
@ -234,10 +233,10 @@ namespace MLEM.Misc {
/// <returns>The vector's direction</returns> /// <returns>The vector's direction</returns>
public static Direction2 To90Direction(this Vector2 offset) { public static Direction2 To90Direction(this Vector2 offset) {
if (offset.X == 0 && offset.Y == 0) if (offset.X == 0 && offset.Y == 0)
return None; return Direction2.None;
if (Math.Abs(offset.X) > Math.Abs(offset.Y)) if (Math.Abs(offset.X) > Math.Abs(offset.Y))
return offset.X > 0 ? Right : Left; return offset.X > 0 ? Direction2.Right : Direction2.Left;
return offset.Y > 0 ? Down : Up; return offset.Y > 0 ? Direction2.Down : Direction2.Up;
} }
/// <summary> /// <summary>
@ -247,17 +246,17 @@ namespace MLEM.Misc {
/// <param name="reference">The direction to rotate by</param> /// <param name="reference">The direction to rotate by</param>
/// <param name="start">The direction to use as the default direction</param> /// <param name="start">The direction to use as the default direction</param>
/// <returns>The direction, rotated by the reference direction</returns> /// <returns>The direction, rotated by the reference direction</returns>
public static Direction2 RotateBy(this Direction2 dir, Direction2 reference, Direction2 start = Up) { public static Direction2 RotateBy(this Direction2 dir, Direction2 reference, Direction2 start = Direction2.Up) {
if (!ClockwiseLookup.TryGetValue(reference, out var refIndex)) if (!Direction2Helper.ClockwiseLookup.TryGetValue(reference, out var refIndex))
return None; return Direction2.None;
if (!ClockwiseLookup.TryGetValue(start, out var startIndex)) if (!Direction2Helper.ClockwiseLookup.TryGetValue(start, out var startIndex))
return None; return Direction2.None;
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex)) if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
return None; return Direction2.None;
var diff = refIndex - startIndex; var diff = refIndex - startIndex;
if (diff < 0) if (diff < 0)
diff += Clockwise.Length; diff += Direction2Helper.Clockwise.Length;
return Clockwise[(dirIndex + diff) % Clockwise.Length]; return Direction2Helper.Clockwise[(dirIndex + diff) % Direction2Helper.Clockwise.Length];
} }
} }

View file

@ -72,7 +72,7 @@ namespace MLEM.Misc {
public static readonly Easing InOutElastic = p => p == 0 ? 0 : p == 1 ? 1 : p < 0.5 ? -((float) Math.Pow(2, 20 * p - 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F)) / 2 : (float) Math.Pow(2, -20 * p + 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F) / 2 + 1; public static readonly Easing InOutElastic = p => p == 0 ? 0 : p == 1 ? 1 : p < 0.5 ? -((float) Math.Pow(2, 20 * p - 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F)) / 2 : (float) Math.Pow(2, -20 * p + 10) * (float) Math.Sin((20 * p - 11.125) * 1.39626340159546F) / 2 + 1;
/// <summary>https://easings.net/#easeInBounce</summary> /// <summary>https://easings.net/#easeInBounce</summary>
public static readonly Easing InBounce = p => 1 - OutBounce(1 - p); public static readonly Easing InBounce = p => 1 - Easings.OutBounce(1 - p);
/// <summary>https://easings.net/#easeOutBounce</summary> /// <summary>https://easings.net/#easeOutBounce</summary>
public static readonly Easing OutBounce = p => { public static readonly Easing OutBounce = p => {
const float n1 = 7.5625F; const float n1 = 7.5625F;
@ -88,7 +88,7 @@ namespace MLEM.Misc {
} }
}; };
/// <summary>https://easings.net/#easeInOutBounce</summary> /// <summary>https://easings.net/#easeInOutBounce</summary>
public static readonly Easing InOutBounce = p => p < 0.5 ? (1 - OutBounce(1 - 2 * p)) / 2 : (1 + OutBounce(2 * p - 1)) / 2; public static readonly Easing InOutBounce = p => p < 0.5 ? (1 - Easings.OutBounce(1 - 2 * p)) / 2 : (1 + Easings.OutBounce(2 * p - 1)) / 2;
/// <summary> /// <summary>
/// Scales the input of an easing function, which is usually between 0 and 1, to a given minimum and maximum. /// Scales the input of an easing function, which is usually between 0 and 1, to a given minimum and maximum.

View file

@ -12,11 +12,11 @@ namespace MLEM.Misc {
/// <summary> /// <summary>
/// All values of the <see cref="Buttons"/> enum. /// All values of the <see cref="Buttons"/> enum.
/// </summary> /// </summary>
public static readonly Buttons[] Buttons = GetValues<Buttons>().ToArray(); public static readonly Buttons[] Buttons = EnumHelper.GetValues<Buttons>().ToArray();
/// <summary> /// <summary>
/// All values of the <see cref="Keys"/> enum. /// All values of the <see cref="Keys"/> enum.
/// </summary> /// </summary>
public static readonly Keys[] Keys = GetValues<Keys>().ToArray(); public static readonly Keys[] Keys = EnumHelper.GetValues<Keys>().ToArray();
/// <summary> /// <summary>
/// Returns all of the values of the given enum type. /// Returns all of the values of the given enum type.

View file

@ -50,7 +50,7 @@ namespace MLEM.Misc {
/// </summary> /// </summary>
/// <exception cref="InvalidOperationException">If <see cref="Current"/> is null</exception> /// <exception cref="InvalidOperationException">If <see cref="Current"/> is null</exception>
public static void EnsureExists() { public static void EnsureExists() {
if (Current == null) if (MlemPlatform.Current == null)
throw new InvalidOperationException("MlemPlatform was not initialized. For more information, see the MlemPlatform class or https://mlem.ellpeck.de/api/MLEM.Misc.MlemPlatform"); throw new InvalidOperationException("MlemPlatform was not initialized. For more information, see the MlemPlatform class or https://mlem.ellpeck.de/api/MLEM.Misc.MlemPlatform");
} }

View file

@ -135,9 +135,9 @@ namespace MLEM.Misc {
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns> /// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
public override int GetHashCode() { public override int GetHashCode() {
var hashCode = this.Left.GetHashCode(); var hashCode = this.Left.GetHashCode();
hashCode = (hashCode * 397) ^ this.Right.GetHashCode(); hashCode = hashCode * 397 ^ this.Right.GetHashCode();
hashCode = (hashCode * 397) ^ this.Top.GetHashCode(); hashCode = hashCode * 397 ^ this.Top.GetHashCode();
hashCode = (hashCode * 397) ^ this.Bottom.GetHashCode(); hashCode = hashCode * 397 ^ this.Bottom.GetHashCode();
return hashCode; return hashCode;
} }

View file

@ -248,7 +248,7 @@ namespace MLEM.Misc {
var num2 = Math.Min(value1.Y + value1.Height, value2.Y + value2.Height); var num2 = Math.Min(value1.Y + value1.Height, value2.Y + value2.Height);
return new RectangleF(x, y, num1 - x, num2 - y); return new RectangleF(x, y, num1 - x, num2 - y);
} else { } else {
return Empty; return RectangleF.Empty;
} }
} }

View file

@ -14,6 +14,7 @@ namespace MLEM.Pathfinding {
/// <summary> /// <summary>
/// A value that represents an infinite path cost, or a cost for a location that cannot possibly be reached. /// A value that represents an infinite path cost, or a cost for a location that cannot possibly be reached.
/// </summary> /// </summary>
[Obsolete("This field is deprecated. Use float.PositiveInfinity or float.MaxValue instead.")]
public const float InfiniteCost = float.PositiveInfinity; public const float InfiniteCost = float.PositiveInfinity;
/// <summary> /// <summary>
/// The array of all directions that will be checked for path finding. /// The array of all directions that will be checked for path finding.
@ -110,7 +111,7 @@ namespace MLEM.Pathfinding {
closed.Add(current.Pos, current); closed.Add(current.Pos, current);
if (current.Pos.Equals(goal)) { if (current.Pos.Equals(goal)) {
ret = CompilePath(current); ret = AStar<T>.CompilePath(current);
break; break;
} }
@ -167,7 +168,7 @@ namespace MLEM.Pathfinding {
/// <summary> /// <summary>
/// A cost function for a given path finding position. /// A cost function for a given path finding position.
/// If a path point should have the default cost, <see cref="AStar{T}.DefaultCost"/> should be returned. /// If a path point should have the default cost, <see cref="AStar{T}.DefaultCost"/> should be returned.
/// If a path point should be unreachable, <see cref="AStar{T}.InfiniteCost"/> should be returned. /// If a path point should be unreachable, <see cref="float.PositiveInfinity"/> or <see cref="float.MaxValue"/> should be returned.
/// </summary> /// </summary>
/// <param name="currPos">The current position in the path</param> /// <param name="currPos">The current position in the path</param>
/// <param name="nextPos">The position we're trying to reach from the current position</param> /// <param name="nextPos">The position we're trying to reach from the current position</param>
@ -218,7 +219,7 @@ namespace MLEM.Pathfinding {
/// <param name="other">An object to compare with this object.</param> /// <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> /// <returns>true if the current object is equal to the <paramref name="other">other</paramref> parameter; otherwise, false.</returns>
public bool Equals(PathPoint<T> other) { public bool Equals(PathPoint<T> other) {
return ReferenceEquals(this, other) || EqualityComparer<T>.Default.Equals(this.Pos, other.Pos); return object.ReferenceEquals(this, other) || EqualityComparer<T>.Default.Equals(this.Pos, other.Pos);
} }
/// <summary>Indicates whether this instance and a specified object are equal.</summary> /// <summary>Indicates whether this instance and a specified object are equal.</summary>

View file

@ -14,7 +14,7 @@ namespace MLEM.Pathfinding {
/// <inheritdoc /> /// <inheritdoc />
public AStar2(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) : public AStar2(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) :
base(AllDirs, AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {} base(AStar2.AllDirs, AStar2.AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
/// <inheritdoc /> /// <inheritdoc />
protected override Point AddPositions(Point first, Point second) { protected override Point AddPositions(Point first, Point second) {

View file

@ -30,12 +30,12 @@ namespace MLEM.Pathfinding {
} }
} }
} }
AllDirs = dirs.ToArray(); AStar3.AllDirs = dirs.ToArray();
} }
/// <inheritdoc /> /// <inheritdoc />
public AStar3(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) : public AStar3(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) :
base(AllDirs, AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {} base(AStar3.AllDirs, AStar3.AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
/// <inheritdoc /> /// <inheritdoc />
protected override Vector3 AddPositions(Vector3 first, Vector3 second) { protected override Vector3 AddPositions(Vector3 first, Vector3 second) {

View file

@ -57,7 +57,7 @@ namespace MLEM.Sound {
public float GetRandomPitch() { public float GetRandomPitch() {
if (this.RandomPitchModifier == 0) if (this.RandomPitchModifier == 0)
return this.Pitch; return this.Pitch;
return this.Pitch + ((float) Random.NextDouble() * 2 - 1) * this.RandomPitchModifier; return this.Pitch + ((float) SoundEffectInfo.Random.NextDouble() * 2 - 1) * this.RandomPitchModifier;
} }
/// <summary> /// <summary>

View file

@ -54,7 +54,7 @@ namespace Sandbox {
this.Components.Add(this.rawContent = new RawContentManager(this.Services)); this.Components.Add(this.rawContent = new RawContentManager(this.Services));
this.map = LoadContent<TiledMap>("Tiled/Map"); this.map = MlemGame.LoadContent<TiledMap>("Tiled/Map");
this.mapRenderer = new IndividualTiledMapRenderer(this.map); this.mapRenderer = new IndividualTiledMapRenderer(this.map);
this.collisions = new TiledMapCollisions(this.map); this.collisions = new TiledMapCollisions(this.map);
@ -78,7 +78,7 @@ namespace Sandbox {
//var font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")); //var font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"));
//var font = new GenericBitmapFont(LoadContent<BitmapFont>("Fonts/Regular")); //var font = new GenericBitmapFont(LoadContent<BitmapFont>("Fonts/Regular"));
var font = new GenericStashFont(system.GetFont(32)); var font = new GenericStashFont(system.GetFont(32));
var spriteFont = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")); var spriteFont = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/TestFont"));
this.UiSystem.Style = new UntexturedStyle(this.SpriteBatch) { this.UiSystem.Style = new UntexturedStyle(this.SpriteBatch) {
Font = font, Font = font,
TextScale = 0.5F, TextScale = 0.5F,
@ -277,7 +277,7 @@ namespace Sandbox {
this.OnDraw += (g, time) => { this.OnDraw += (g, time) => {
const string testString = "This is a\ntest string\n\twith long lines.\nLet's write some more stuff. Let's\r\nsplit lines weirdly."; const string testString = "This is a\ntest string\n\twith long lines.\nLet's write some more stuff. Let's\r\nsplit lines weirdly.";
if (Input.IsKeyPressed(Keys.I)) { if (MlemGame.Input.IsKeyPressed(Keys.I)) {
index++; index++;
if (index == 1) { if (index == 1) {
scale = 2; scale = 2;
@ -295,7 +295,7 @@ namespace Sandbox {
} }
this.SpriteBatch.Begin(); this.SpriteBatch.Begin();
if (Input.IsKeyDown(Keys.LeftShift)) { if (MlemGame.Input.IsKeyDown(Keys.LeftShift)) {
this.SpriteBatch.DrawString(regularFont, testString, pos, Color.Red, rotation, origin, scale, effects, 0); this.SpriteBatch.DrawString(regularFont, testString, pos, Color.Red, rotation, origin, scale, effects, 0);
} else { } else {
genericFont.DrawString(this.SpriteBatch, testString, pos, Color.Green, rotation, origin, scale, effects, 0); genericFont.DrawString(this.SpriteBatch, testString, pos, Color.Green, rotation, origin, scale, effects, 0);
@ -363,8 +363,8 @@ namespace Sandbox {
/*if (Input.InputsDown.Length > 0) /*if (Input.InputsDown.Length > 0)
Console.WriteLine("Down: " + string.Join(", ", Input.InputsDown));*/ Console.WriteLine("Down: " + string.Join(", ", Input.InputsDown));*/
if (Input.InputsPressed.Length > 0) if (MlemGame.Input.InputsPressed.Length > 0)
Console.WriteLine("Pressed: " + string.Join(", ", Input.InputsPressed)); Console.WriteLine("Pressed: " + string.Join(", ", MlemGame.Input.InputsPressed));
} }
protected override void DoDraw(GameTime gameTime) { protected override void DoDraw(GameTime gameTime) {

View file

@ -7,7 +7,6 @@ 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; using Vector2 = Microsoft.Xna.Framework.Vector2;
namespace Tests { namespace Tests {
@ -41,27 +40,27 @@ namespace Tests {
public void TestDynamicEnum() { public void TestDynamicEnum() {
var flags = new TestEnum[100]; var flags = new TestEnum[100];
for (var i = 0; i < flags.Length; i++) for (var i = 0; i < flags.Length; i++)
flags[i] = AddFlag<TestEnum>("Flag" + i); flags[i] = DynamicEnum.AddFlag<TestEnum>("Flag" + i);
Assert.AreEqual(GetValue(flags[7]), BigInteger.One << 7); Assert.AreEqual(DynamicEnum.GetValue(flags[7]), BigInteger.One << 7);
Assert.AreEqual(GetEnumValue<TestEnum>(BigInteger.One << 75), flags[75]); Assert.AreEqual(DynamicEnum.GetEnumValue<TestEnum>(BigInteger.One << 75), flags[75]);
Assert.AreEqual(GetValue(Or(flags[2], flags[17])), (BigInteger.One << 2) | (BigInteger.One << 17)); Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.Or(flags[2], flags[17])), BigInteger.One << 2 | BigInteger.One << 17);
Assert.AreEqual(GetValue(And(flags[2], flags[3])), BigInteger.Zero); Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.And(flags[2], flags[3])), BigInteger.Zero);
Assert.AreEqual(And(Or(flags[24], flags[52]), Or(flags[52], flags[75])), flags[52]); Assert.AreEqual(DynamicEnum.And(DynamicEnum.Or(flags[24], flags[52]), DynamicEnum.Or(flags[52], flags[75])), flags[52]);
Assert.AreEqual(Xor(Or(flags[85], flags[73]), flags[73]), flags[85]); Assert.AreEqual(DynamicEnum.Xor(DynamicEnum.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(DynamicEnum.Xor(DynamicEnum.Or(flags[85], DynamicEnum.Or(flags[73], flags[12])), flags[73]), DynamicEnum.Or(flags[85], flags[12]));
Assert.AreEqual(GetValue(Neg(flags[74])), ~(BigInteger.One << 74)); Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.Neg(flags[74])), ~(BigInteger.One << 74));
Assert.AreEqual(Or(flags[24], flags[52]).HasFlag(flags[24]), true); Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasFlag(flags[24]), true);
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(flags[24]), true); Assert.AreEqual(DynamicEnum.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(DynamicEnum.Or(flags[24], flags[52]).HasFlag(DynamicEnum.Or(flags[24], flags[26])), false);
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(Or(flags[24], flags[26])), true); Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasAnyFlag(DynamicEnum.Or(flags[24], flags[26])), true);
Assert.AreEqual(Parse<TestEnum>("Flag24"), flags[24]); Assert.AreEqual(DynamicEnum.Parse<TestEnum>("Flag24"), flags[24]);
Assert.AreEqual(Parse<TestEnum>("Flag24 | Flag43"), Or(flags[24], flags[43])); Assert.AreEqual(DynamicEnum.Parse<TestEnum>("Flag24 | Flag43"), DynamicEnum.Or(flags[24], flags[43]));
Assert.AreEqual(flags[24].ToString(), "Flag24"); Assert.AreEqual(flags[24].ToString(), "Flag24");
Assert.AreEqual(Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43"); Assert.AreEqual(DynamicEnum.Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43");
} }
[Test] [Test]
@ -71,14 +70,14 @@ namespace Tests {
// normal generic data holder should crush the time span down to a string due to its custom serializer // normal generic data holder should crush the time span down to a string due to its custom serializer
var data = new GenericDataHolder(); var data = new GenericDataHolder();
data.SetData("Time", TimeSpan.FromMinutes(5)); data.SetData("Time", TimeSpan.FromMinutes(5));
var read = SerializeAndDeserialize(serializer, data); var read = DataTests.SerializeAndDeserialize(serializer, data);
Assert.IsNotInstanceOf<TimeSpan>(read.GetData<object>("Time")); Assert.IsNotInstanceOf<TimeSpan>(read.GetData<object>("Time"));
Assert.Throws<InvalidCastException>(() => read.GetData<TimeSpan>("Time")); Assert.Throws<InvalidCastException>(() => read.GetData<TimeSpan>("Time"));
// json type safe generic data holder should wrap the time span to ensure that it stays a time span // json type safe generic data holder should wrap the time span to ensure that it stays a time span
var safeData = new JsonTypeSafeGenericDataHolder(); var safeData = new JsonTypeSafeGenericDataHolder();
safeData.SetData("Time", TimeSpan.FromMinutes(5)); safeData.SetData("Time", TimeSpan.FromMinutes(5));
var safeRead = SerializeAndDeserialize(serializer, safeData); var safeRead = DataTests.SerializeAndDeserialize(serializer, safeData);
Assert.IsInstanceOf<TimeSpan>(safeRead.GetData<object>("Time")); Assert.IsInstanceOf<TimeSpan>(safeRead.GetData<object>("Time"));
Assert.DoesNotThrow(() => safeRead.GetData<TimeSpan>("Time")); Assert.DoesNotThrow(() => safeRead.GetData<TimeSpan>("Time"));
} }
@ -99,11 +98,11 @@ namespace Tests {
public TestObject(Vector2 test, string test2) {} public TestObject(Vector2 test, string test2) {}
protected bool Equals(TestObject other) { protected bool Equals(TestObject other) {
return this.Vec.Equals(other.Vec) && this.Point.Equals(other.Point) && Equals(this.OtherTest, other.OtherTest) && this.Dir == other.Dir; return this.Vec.Equals(other.Vec) && this.Point.Equals(other.Point) && object.Equals(this.OtherTest, other.OtherTest) && this.Dir == other.Dir;
} }
public override bool Equals(object obj) { public override bool Equals(object obj) {
return ReferenceEquals(this, obj) || obj is TestObject other && this.Equals(other); return object.ReferenceEquals(this, obj) || obj is TestObject other && this.Equals(other);
} }
public override int GetHashCode() { public override int GetHashCode() {

View file

@ -1,58 +1,57 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using MLEM.Misc; using MLEM.Misc;
using NUnit.Framework; using NUnit.Framework;
using static MLEM.Misc.Direction2;
namespace Tests { namespace Tests {
public class DirectionTests { public class DirectionTests {
[Test] [Test]
public void TestDirections() { public void TestDirections() {
Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), DownRight); Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), Direction2.DownRight);
Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), DownRight); Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), Direction2.DownRight);
Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Down); Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Direction2.Down);
} }
[Test] [Test]
public void Test90Directions() { public void Test90Directions() {
Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Right); Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Direction2.Right);
Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Down); Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Direction2.Down);
Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Down); Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Direction2.Down);
} }
[Test] [Test]
public void TestRotations() { public void TestRotations() {
// rotate cw // rotate cw
Assert.AreEqual(Up.RotateCw(), Right); Assert.AreEqual(Direction2.Up.RotateCw(), Direction2.Right);
Assert.AreEqual(Up.RotateCw(true), UpRight); Assert.AreEqual(Direction2.Up.RotateCw(true), Direction2.UpRight);
Assert.AreEqual(Left.RotateCw(), Up); Assert.AreEqual(Direction2.Left.RotateCw(), Direction2.Up);
Assert.AreEqual(UpLeft.RotateCw(), UpRight); Assert.AreEqual(Direction2.UpLeft.RotateCw(), Direction2.UpRight);
// rotate ccw // rotate ccw
Assert.AreEqual(Up.RotateCcw(), Left); Assert.AreEqual(Direction2.Up.RotateCcw(), Direction2.Left);
Assert.AreEqual(Up.RotateCcw(true), UpLeft); Assert.AreEqual(Direction2.Up.RotateCcw(true), Direction2.UpLeft);
Assert.AreEqual(Left.RotateCcw(), Down); Assert.AreEqual(Direction2.Left.RotateCcw(), Direction2.Down);
Assert.AreEqual(UpLeft.RotateCcw(), DownLeft); Assert.AreEqual(Direction2.UpLeft.RotateCcw(), Direction2.DownLeft);
// rotate 360 degrees // rotate 360 degrees
foreach (var dir in Direction2Helper.AllExceptNone) { foreach (var dir in Direction2Helper.AllExceptNone) {
Assert.AreEqual(RotateMultipleTimes(dir, true, false, 4), dir); Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, false, 4), dir);
Assert.AreEqual(RotateMultipleTimes(dir, true, true, 8), dir); Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, true, 8), dir);
Assert.AreEqual(RotateMultipleTimes(dir, false, false, 4), dir); Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, false, 4), dir);
Assert.AreEqual(RotateMultipleTimes(dir, false, true, 8), dir); Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, true, 8), dir);
} }
// rotate by with start Up // rotate by with start Up
Assert.AreEqual(Right.RotateBy(Right), Down); Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Right), Direction2.Down);
Assert.AreEqual(Right.RotateBy(Down), Left); Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Down), Direction2.Left);
Assert.AreEqual(Right.RotateBy(Left), Up); Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Left), Direction2.Up);
Assert.AreEqual(Right.RotateBy(Up), Right); Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Up), Direction2.Right);
// rotate by with start Left // rotate by with start Left
Assert.AreEqual(Up.RotateBy(Right, Left), Down); Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Right, Direction2.Left), Direction2.Down);
Assert.AreEqual(Up.RotateBy(Down, Left), Left); Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Down, Direction2.Left), Direction2.Left);
Assert.AreEqual(Up.RotateBy(Left, Left), Up); Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Left, Direction2.Left), Direction2.Up);
Assert.AreEqual(Up.RotateBy(Up, Left), Right); Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Up, Direction2.Left), Direction2.Right);
} }
private static Direction2 RotateMultipleTimes(Direction2 dir, bool clockwise, bool fortyFiveDegrees, int times) { private static Direction2 RotateMultipleTimes(Direction2 dir, bool clockwise, bool fortyFiveDegrees, int times) {

View file

@ -16,12 +16,12 @@ namespace Tests {
"XXXX" "XXXX"
}; };
var noDiagonals = FindPathInArea(new Point(1, 1), new Point(2, 2), area, false).ToArray(); var noDiagonals = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 2), area, false).ToArray();
Assert.AreEqual(noDiagonals.Length, 3); Assert.AreEqual(noDiagonals.Length, 3);
Assert.AreEqual(noDiagonals[0], new Point(1, 1)); Assert.AreEqual(noDiagonals[0], new Point(1, 1));
Assert.AreEqual(noDiagonals[2], new Point(2, 2)); Assert.AreEqual(noDiagonals[2], new Point(2, 2));
var diagonals = FindPathInArea(new Point(1, 1), new Point(2, 2), area, true).ToArray(); var diagonals = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 2), area, true).ToArray();
Assert.AreEqual(diagonals.Length, 2); Assert.AreEqual(diagonals.Length, 2);
Assert.AreEqual(diagonals[0], new Point(1, 1)); Assert.AreEqual(diagonals[0], new Point(1, 1));
Assert.AreEqual(diagonals[1], new Point(2, 2)); Assert.AreEqual(diagonals[1], new Point(2, 2));
@ -36,11 +36,11 @@ namespace Tests {
"XXXXXXXX" "XXXXXXXX"
}; };
var firstPath = FindPathInArea(new Point(1, 1), new Point(3, 1), area, false).ToArray(); var firstPath = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(3, 1), area, false).ToArray();
var firstExpected = new[] {new Point(1, 1), new Point(1, 2), new Point(2, 2), new Point(3, 2), new Point(3, 1)}; var firstExpected = new[] {new Point(1, 1), new Point(1, 2), new Point(2, 2), new Point(3, 2), new Point(3, 1)};
Assert.AreEqual(firstPath, firstExpected); Assert.AreEqual(firstPath, firstExpected);
var secondPath = FindPathInArea(new Point(1, 1), new Point(5, 2), area, false).ToArray(); var secondPath = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(5, 2), area, false).ToArray();
var secondExpected = firstExpected.Concat(new[] {new Point(4, 1), new Point(5, 1), new Point(5, 2)}).ToArray(); var secondExpected = firstExpected.Concat(new[] {new Point(4, 1), new Point(5, 1), new Point(5, 2)}).ToArray();
Assert.AreEqual(secondPath, secondExpected); Assert.AreEqual(secondPath, secondExpected);
} }
@ -55,15 +55,15 @@ namespace Tests {
"XXXX" "XXXX"
}; };
// non-diagonal pathfinding should get stuck in the corner // non-diagonal pathfinding should get stuck in the corner
Assert.IsNull(FindPathInArea(new Point(1, 1), new Point(2, 3), area, false)); Assert.IsNull(PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 3), area, false));
// diagonal pathfinding should be able to cross the diagonal gap // diagonal pathfinding should be able to cross the diagonal gap
Assert.IsNotNull(FindPathInArea(new Point(1, 1), new Point(2, 3), area, true)); Assert.IsNotNull(PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 3), area, true));
} }
private static Stack<Point> FindPathInArea(Point start, Point end, IEnumerable<string> area, bool allowDiagonals) { private static Stack<Point> FindPathInArea(Point start, Point end, IEnumerable<string> area, bool allowDiagonals) {
var costs = area.Select(s => s.Select(c => c switch { var costs = area.Select(s => s.Select(c => c switch {
' ' => 1, ' ' => 1,
'X' => AStar2.InfiniteCost, 'X' => float.PositiveInfinity,
_ => (float) char.GetNumericValue(c) _ => (float) char.GetNumericValue(c)
}).ToArray()).ToArray(); }).ToArray()).ToArray();
var pathFinder = new AStar2((p1, p2) => costs[p2.Y][p2.X], allowDiagonals); var pathFinder = new AStar2((p1, p2) => costs[p2.Y][p2.X], allowDiagonals);

View file

@ -13,7 +13,7 @@ namespace Tests {
protected override void LoadContent() { protected override void LoadContent() {
base.LoadContent(); base.LoadContent();
this.RawContent = new RawContentManager(this.Services, this.Content.RootDirectory); this.RawContent = new RawContentManager(this.Services, this.Content.RootDirectory);
this.UiSystem.Style.Font = new GenericSpriteFont(LoadContent<SpriteFont>("TestFont")); this.UiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("TestFont"));
} }
public static TestGame Create() { public static TestGame Create() {

View file

@ -43,8 +43,8 @@ namespace Tests {
[Test] [Test]
public void TestDisposal() { public void TestDisposal() {
using var packer = new RuntimeTexturePacker(128, disposeTextures: true); using var packer = new RuntimeTexturePacker(128, disposeTextures: true);
packer.Add(new TextureRegion(this.disposedTestTexture), StubResult); packer.Add(new TextureRegion(this.disposedTestTexture), TexturePackerTests.StubResult);
packer.Add(new TextureRegion(this.disposedTestTexture, 0, 0, 8, 8), StubResult); packer.Add(new TextureRegion(this.disposedTestTexture, 0, 0, 8, 8), TexturePackerTests.StubResult);
packer.Pack(this.game.GraphicsDevice); packer.Pack(this.game.GraphicsDevice);
Assert.True(this.disposedTestTexture.IsDisposed); Assert.True(this.disposedTestTexture.IsDisposed);
Assert.False(packer.PackedTexture.IsDisposed); Assert.False(packer.PackedTexture.IsDisposed);
@ -55,26 +55,26 @@ namespace Tests {
// test forced max width // test forced max width
using var packer = new RuntimeTexturePacker(128); using var packer = new RuntimeTexturePacker(128);
Assert.Throws<InvalidOperationException>(() => { Assert.Throws<InvalidOperationException>(() => {
packer.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), StubResult); packer.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), TexturePackerTests.StubResult);
}); });
// test auto-expanding width // test auto-expanding width
using var packer2 = new RuntimeTexturePacker(128, true); using var packer2 = new RuntimeTexturePacker(128, true);
Assert.DoesNotThrow(() => { Assert.DoesNotThrow(() => {
packer2.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), StubResult); packer2.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), TexturePackerTests.StubResult);
}); });
packer2.Pack(this.game.GraphicsDevice); packer2.Pack(this.game.GraphicsDevice);
// test power of two forcing // test power of two forcing
using var packer3 = new RuntimeTexturePacker(128, forcePowerOfTwo: true); using var packer3 = new RuntimeTexturePacker(128, forcePowerOfTwo: true);
packer3.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), StubResult); packer3.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), TexturePackerTests.StubResult);
packer3.Pack(this.game.GraphicsDevice); packer3.Pack(this.game.GraphicsDevice);
Assert.AreEqual(64, packer3.PackedTexture.Width); Assert.AreEqual(64, packer3.PackedTexture.Width);
Assert.AreEqual(256, packer3.PackedTexture.Height); Assert.AreEqual(256, packer3.PackedTexture.Height);
// test square forcing // test square forcing
using var packer4 = new RuntimeTexturePacker(128, forceSquare: true); using var packer4 = new RuntimeTexturePacker(128, forceSquare: true);
packer4.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), StubResult); packer4.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), TexturePackerTests.StubResult);
packer4.Pack(this.game.GraphicsDevice); packer4.Pack(this.game.GraphicsDevice);
Assert.AreEqual(170, packer4.PackedTexture.Width); Assert.AreEqual(170, packer4.PackedTexture.Width);
Assert.AreEqual(170, packer4.PackedTexture.Height); Assert.AreEqual(170, packer4.PackedTexture.Height);