mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 14:08:34 +01:00
Compare commits
2 commits
d0ece92550
...
1795acb30e
Author | SHA1 | Date | |
---|---|---|---|
1795acb30e | |||
59af00c89a |
65 changed files with 588 additions and 589 deletions
|
@ -21,6 +21,10 @@ Additions
|
||||||
Improvements
|
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
|
||||||
|
- Added GenericInput support for Buttons.None
|
||||||
|
|
||||||
|
Removals
|
||||||
|
- Marked AStar.InfiniteCost as obsolete
|
||||||
|
|
||||||
### MLEM.Ui
|
### MLEM.Ui
|
||||||
Additions
|
Additions
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (&) combination</returns>
|
/// <returns>The bitwise AND (&) 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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?");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"/>.
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,7 @@ namespace MLEM.Input {
|
||||||
/// Returns this generic input's <see cref="Keys"/>.
|
/// Returns this generic input's <see cref="Keys"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Keyboard"/> or <see cref="InputType.None"/>.</exception>
|
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Keyboard"/> or <see cref="InputType.None"/>.</exception>
|
||||||
public Keys Key {
|
public Keys Key => this.Type == InputType.None ? 0 : this.Type == InputType.Keyboard ? (Keys) this.value : throw new InvalidOperationException();
|
||||||
get {
|
|
||||||
if (this.Type == InputType.None)
|
|
||||||
return Keys.None;
|
|
||||||
return this.Type == InputType.Keyboard ? (Keys) this.value : throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns this generic input's <see cref="MouseButton"/>.
|
/// Returns this generic input's <see cref="MouseButton"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -39,8 +33,8 @@ namespace MLEM.Input {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns this generic input's <see cref="Buttons"/>.
|
/// Returns this generic input's <see cref="Buttons"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/>.</exception>
|
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/> or <see cref="InputType.None"/>.</exception>
|
||||||
public Buttons Button => this.Type == InputType.Gamepad ? (Buttons) this.value : throw new InvalidOperationException();
|
public Buttons Button => this.Type == InputType.None ? 0 : this.Type == InputType.Gamepad ? (Buttons) this.value : throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new generic input from the given keyboard <see cref="Keys"/>.
|
/// Creates a new generic input from the given keyboard <see cref="Keys"/>.
|
||||||
|
@ -107,7 +101,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>
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)}");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue