mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 14:08:34 +01:00
Compare commits
No commits in common. "1795acb30e99babdce01b51f81feed630c21e2ad" and "d0ece925502067eb5303854cc21101f53d92d3e8" have entirely different histories.
1795acb30e
...
d0ece92550
65 changed files with 589 additions and 588 deletions
|
@ -21,10 +21,6 @@ Additions
|
|||
Improvements
|
||||
- Allow comparing Keybind and Combination based on the amount of modifiers they have
|
||||
- Allow using multiple textures in a StaticSpriteBatch
|
||||
- Added GenericInput support for Buttons.None
|
||||
|
||||
Removals
|
||||
- Marked AStar.InfiniteCost as obsolete
|
||||
|
||||
### MLEM.Ui
|
||||
Additions
|
||||
|
|
|
@ -8,6 +8,7 @@ using Microsoft.Xna.Framework;
|
|||
using Microsoft.Xna.Framework.Input;
|
||||
using MLEM.Extensions;
|
||||
using MLEM.Misc;
|
||||
using static Android.Views.SystemUiFlags;
|
||||
|
||||
namespace Demos.Android {
|
||||
[Activity(
|
||||
|
@ -47,7 +48,7 @@ namespace Demos.Android {
|
|||
base.OnWindowFocusChanged(hasFocus);
|
||||
// hide the status bar
|
||||
if (hasFocus)
|
||||
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.ImmersiveSticky | SystemUiFlags.LayoutStable | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen);
|
||||
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (ImmersiveSticky | LayoutStable | LayoutHideNavigation | LayoutFullscreen | HideNavigation | Fullscreen);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Demos {
|
|||
// 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
|
||||
// (as seen below)
|
||||
var atlas = new UniformTextureAtlas(Demo.LoadContent<Texture2D>("Textures/Anim"), 4, 4);
|
||||
var atlas = new UniformTextureAtlas(LoadContent<Texture2D>("Textures/Anim"), 4, 4);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Demos {
|
|||
public override void 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
|
||||
this.texture = Demo.LoadContent<Texture2D>("Textures/AutoTiling");
|
||||
this.texture = LoadContent<Texture2D>("Textures/AutoTiling");
|
||||
|
||||
// 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)
|
||||
|
@ -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
|
||||
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);
|
||||
AutoTiling.DrawAutoTile(this.SpriteBatch, new Vector2(x + 1, y + 1) * TileSize, new TextureRegion(this.texture, 0, 0, TileSize, TileSize), ConnectsTo, Color.White);
|
||||
|
||||
// when drawing extended auto-tiles, the same rules apply, but the source texture layout is different
|
||||
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(AutoTilingDemo.TileSize, 0)));
|
||||
AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * AutoTilingDemo.TileSize, background, overlay, ConnectsTo, Color.White, Color.White);
|
||||
var background = new TextureRegion(this.texture, 0, TileSize * 2, TileSize, TileSize);
|
||||
var overlay = new TextureRegion(this.texture, background.Area.OffsetCopy(new Point(TileSize, 0)));
|
||||
AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * TileSize, background, overlay, ConnectsTo, Color.White, Color.White);
|
||||
}
|
||||
}
|
||||
this.SpriteBatch.End();
|
||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
|||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>JetBrainsMono-Regular.ttf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>JetBrainsMono-Regular.ttf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
|||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYETANO.ttf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYETANO.ttf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
|||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYTANOB</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYTANOB</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
|||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYETANI</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>CAYETANI</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Demos {
|
|||
|
||||
private static readonly FieldInfo[] EasingFields = typeof(Easings)
|
||||
.GetFields(BindingFlags.Public | BindingFlags.Static).ToArray();
|
||||
private static readonly Easings.Easing[] Easings = EasingsDemo.EasingFields
|
||||
private static readonly Easings.Easing[] Easings = EasingFields
|
||||
.Select(f => (Easings.Easing) f.GetValue(null)).ToArray();
|
||||
private Group group;
|
||||
private int current;
|
||||
|
@ -27,11 +27,11 @@ namespace Demos {
|
|||
this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false};
|
||||
this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") {
|
||||
OnPressed = e => {
|
||||
this.current = (this.current + 1) % EasingsDemo.Easings.Length;
|
||||
this.current = (this.current + 1) % Easings.Length;
|
||||
this.progress = 0;
|
||||
}
|
||||
});
|
||||
this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingsDemo.EasingFields[this.current].Name, true));
|
||||
this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingFields[this.current].Name, true));
|
||||
this.UiRoot.AddChild(this.group);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ namespace Demos {
|
|||
var view = this.GraphicsDevice.Viewport;
|
||||
|
||||
// graph the easing function
|
||||
var graphEase = EasingsDemo.Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3);
|
||||
var graphEase = Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3);
|
||||
for (var x = 0; x < view.Width; x++) {
|
||||
var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4);
|
||||
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
|
||||
this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1;
|
||||
var dotEase = EasingsDemo.Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4);
|
||||
var dotEase = 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);
|
||||
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red);
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ namespace Demos {
|
|||
private TimeSpan secondCounter;
|
||||
|
||||
static GameImpl() {
|
||||
GameImpl.Demos.Add("Ui", ("An in-depth demonstration of the MLEM.Ui package and its abilities", game => new UiDemo(game)));
|
||||
GameImpl.Demos.Add("Easings", ("An example of MLEM's Easings class, an adaptation of easings.net", game => new EasingsDemo(game)));
|
||||
GameImpl.Demos.Add("Pathfinding", ("An example of MLEM's A* pathfinding implementation in 2D", game => new PathfindingDemo(game)));
|
||||
GameImpl.Demos.Add("Animation and Texture Atlas", ("An example of UniformTextureAtlases, SpriteAnimations and SpriteAnimationGroups", game => new AnimationDemo(game)));
|
||||
GameImpl.Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game)));
|
||||
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)));
|
||||
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)));
|
||||
Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game)));
|
||||
}
|
||||
|
||||
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 VerticalSpace(5));
|
||||
foreach (var demo in GameImpl.Demos) {
|
||||
foreach (var demo in Demos) {
|
||||
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
|
||||
OnPressed = e => {
|
||||
selection.IsHidden = true;
|
||||
|
@ -92,9 +92,9 @@ namespace Demos {
|
|||
}
|
||||
|
||||
protected override UiStyle InitializeDefaultUiStyle(SpriteBatch batch) {
|
||||
var tex = MlemGame.LoadContent<Texture2D>("Textures/Test");
|
||||
var tex = LoadContent<Texture2D>("Textures/Test");
|
||||
return new UntexturedStyle(this.SpriteBatch) {
|
||||
Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/TestFont")),
|
||||
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")),
|
||||
TextScale = 0.1F,
|
||||
PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8),
|
||||
ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace Demos {
|
|||
// pathfinder's constructor
|
||||
float Cost(Point pos, Point nextPos) {
|
||||
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
|
||||
return float.PositiveInfinity;
|
||||
return this.world[nextPos.X, nextPos.Y] ? 1 : float.PositiveInfinity;
|
||||
return AStar2.InfiniteCost;
|
||||
return this.world[nextPos.X, nextPos.Y] ? 1 : AStar2.InfiniteCost;
|
||||
}
|
||||
|
||||
// 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 override void LoadContent() {
|
||||
this.testTexture = Demo.LoadContent<Texture2D>("Textures/Test");
|
||||
this.testTexture = LoadContent<Texture2D>("Textures/Test");
|
||||
this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8);
|
||||
base.LoadContent();
|
||||
|
||||
|
@ -38,10 +38,7 @@ namespace Demos {
|
|||
// 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
|
||||
// Supplying a bold and an italic version is optional
|
||||
Font = new GenericSpriteFont(
|
||||
Demo.LoadContent<SpriteFont>("Fonts/TestFont"),
|
||||
Demo.LoadContent<SpriteFont>("Fonts/TestFontBold"),
|
||||
Demo.LoadContent<SpriteFont>("Fonts/TestFontItalic")),
|
||||
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"), LoadContent<SpriteFont>("Fonts/TestFontBold"), LoadContent<SpriteFont>("Fonts/TestFontItalic")),
|
||||
TextScale = 0.1F,
|
||||
PanelTexture = this.testPatch,
|
||||
ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
|
||||
|
@ -52,7 +49,7 @@ namespace Demos {
|
|||
CheckboxCheckmark = new TextureRegion(this.testTexture, 24, 0, 8, 8),
|
||||
RadioTexture = new NinePatch(new TextureRegion(this.testTexture, 16, 0, 8, 8), 3),
|
||||
RadioCheckmark = new TextureRegion(this.testTexture, 32, 0, 8, 8),
|
||||
AdditionalFonts = {{"Monospaced", new GenericSpriteFont(Demo.LoadContent<SpriteFont>("Fonts/MonospacedFont"))}},
|
||||
AdditionalFonts = {{"Monospaced", new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/MonospacedFont"))}},
|
||||
LinkColor = Color.CornflowerBlue
|
||||
};
|
||||
var untexturedStyle = new UntexturedStyle(this.SpriteBatch) {
|
||||
|
@ -161,7 +158,7 @@ namespace Demos {
|
|||
|
||||
// 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") {
|
||||
OnPressed = element => CoroutineHandler.Start(UiDemo.WobbleButton(element)),
|
||||
OnPressed = element => CoroutineHandler.Start(WobbleButton(element)),
|
||||
PositionOffset = new Vector2(0, 1)
|
||||
});
|
||||
// Another button that shows animations!
|
||||
|
@ -194,13 +191,13 @@ namespace Demos {
|
|||
this.root.AddChild(new VerticalSpace(3));
|
||||
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)});
|
||||
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar1));
|
||||
CoroutineHandler.Start(WobbleProgressBar(bar1));
|
||||
var bar2 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)});
|
||||
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar2));
|
||||
CoroutineHandler.Start(WobbleProgressBar(bar2));
|
||||
var bar3 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)});
|
||||
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar3));
|
||||
CoroutineHandler.Start(WobbleProgressBar(bar3));
|
||||
var bar4 = this.root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 0)});
|
||||
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar4));
|
||||
CoroutineHandler.Start(WobbleProgressBar(bar4));
|
||||
|
||||
this.root.AddChild(new VerticalSpace(3));
|
||||
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) {
|
||||
var triedFiles = new List<string>();
|
||||
if (RawContentManager.readers == null)
|
||||
RawContentManager.readers = RawContentManager.CollectContentReaders();
|
||||
foreach (var reader in RawContentManager.readers) {
|
||||
if (readers == null)
|
||||
readers = CollectContentReaders();
|
||||
foreach (var reader in readers) {
|
||||
if (!reader.CanRead(typeof(T)))
|
||||
continue;
|
||||
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="serializer">The json serializer to add</param>
|
||||
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
|
||||
ContentExtensions.Serializers[content] = serializer;
|
||||
Serializers[content] = serializer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -31,7 +31,7 @@ namespace MLEM.Data {
|
|||
/// <param name="content">The content manager whose serializer to get</param>
|
||||
/// <returns>The content manager's serializer</returns>
|
||||
public static JsonSerializer GetJsonSerializer(this ContentManager content) {
|
||||
if (!ContentExtensions.Serializers.TryGetValue(content, out var serializer)) {
|
||||
if (!Serializers.TryGetValue(content, out var serializer)) {
|
||||
serializer = JsonConverters.AddAll(new JsonSerializer());
|
||||
content.SetJsonSerializer(serializer);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace MLEM.Data {
|
|||
/// <param name="content">The content manager to add the converter to</param>
|
||||
/// <param name="converter">The converter to add</param>
|
||||
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
|
||||
var serializer = content.GetJsonSerializer();
|
||||
var serializer = GetJsonSerializer(content);
|
||||
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) {
|
||||
var triedFiles = new List<string>();
|
||||
var serializerToUse = serializer ?? content.GetJsonSerializer();
|
||||
foreach (var extension in extensions ?? ContentExtensions.JsonExtensions) {
|
||||
foreach (var extension in extensions ?? JsonExtensions) {
|
||||
var file = Path.Combine(content.RootDirectory, name + extension);
|
||||
triedFiles.Add(file);
|
||||
try {
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||
/// <returns>A shallow copy of the object</returns>
|
||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||
public static T Copy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
|
||||
public static T Copy<T>(this T obj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
var copy = (T) Construct(typeof(T), flags);
|
||||
obj.CopyInto(copy, flags, fieldInclusion);
|
||||
return copy;
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||
/// <returns>A deep copy of the object</returns>
|
||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||
public static T DeepCopy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
|
||||
public static T DeepCopy<T>(this T obj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
var copy = (T) Construct(typeof(T), flags);
|
||||
obj.DeepCopyInto(copy, flags, fieldInclusion);
|
||||
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>
|
||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||
public static void CopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
public static void CopyInto<T>(this T obj, T otherObj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
foreach (var field in typeof(T).GetFields(flags)) {
|
||||
if (fieldInclusion == null || fieldInclusion(field))
|
||||
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>
|
||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||
public static void DeepCopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
public static void DeepCopyInto<T>(this T obj, T otherObj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||
foreach (var field in obj.GetType().GetFields(flags)) {
|
||||
if (fieldInclusion != null && !fieldInclusion(field))
|
||||
continue;
|
||||
|
@ -83,7 +83,7 @@ namespace MLEM.Data {
|
|||
var otherVal = field.GetValue(otherObj);
|
||||
// if the object we want to copy into doesn't have a value yet, we create one
|
||||
if (otherVal == null) {
|
||||
otherVal = CopyExtensions.Construct(field.FieldType, flags);
|
||||
otherVal = Construct(field.FieldType, flags);
|
||||
field.SetValue(otherObj, otherVal);
|
||||
}
|
||||
val.DeepCopyInto(otherVal, flags);
|
||||
|
@ -92,7 +92,7 @@ namespace MLEM.Data {
|
|||
}
|
||||
|
||||
private static object Construct(Type t, BindingFlags flags) {
|
||||
if (!CopyExtensions.ConstructorCache.TryGetValue(t, out var constructor)) {
|
||||
if (!ConstructorCache.TryGetValue(t, out var constructor)) {
|
||||
var constructors = t.GetConstructors(flags);
|
||||
// find a contructor with the correct attribute
|
||||
constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
|
||||
|
@ -104,7 +104,7 @@ namespace MLEM.Data {
|
|||
constructor = constructors.FirstOrDefault();
|
||||
if (constructor == null)
|
||||
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
|
||||
CopyExtensions.ConstructorCache.Add(t, constructor);
|
||||
ConstructorCache.Add(t, constructor);
|
||||
}
|
||||
return constructor.Invoke(new object[constructor.GetParameters().Length]);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace MLEM.Data {
|
|||
if (this.allFlagsCache == null)
|
||||
this.allFlagsCache = new Dictionary<DynamicEnum, bool>();
|
||||
if (!this.allFlagsCache.TryGetValue(flags, out var ret)) {
|
||||
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) == DynamicEnum.GetValue(flags);
|
||||
ret = (GetValue(this) & GetValue(flags)) == GetValue(flags);
|
||||
this.allFlagsCache.Add(flags, ret);
|
||||
}
|
||||
return ret;
|
||||
|
@ -76,7 +76,7 @@ namespace MLEM.Data {
|
|||
if (this.anyFlagsCache == null)
|
||||
this.anyFlagsCache = new Dictionary<DynamicEnum, bool>();
|
||||
if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) {
|
||||
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) != 0;
|
||||
ret = (GetValue(this) & GetValue(flags)) != 0;
|
||||
this.anyFlagsCache.Add(flags, ret);
|
||||
}
|
||||
return ret;
|
||||
|
@ -87,13 +87,13 @@ namespace MLEM.Data {
|
|||
public override string ToString() {
|
||||
if (this.name == null) {
|
||||
var included = new List<DynamicEnum>();
|
||||
if (DynamicEnum.GetValue(this) != 0) {
|
||||
foreach (var v in DynamicEnum.GetValues(this.GetType())) {
|
||||
if (this.HasFlag(v) && DynamicEnum.GetValue(v) != 0)
|
||||
if (GetValue(this) != 0) {
|
||||
foreach (var v in GetValues(this.GetType())) {
|
||||
if (this.HasFlag(v) && GetValue(v) != 0)
|
||||
included.Add(v);
|
||||
}
|
||||
}
|
||||
this.name = included.Count > 0 ? string.Join(" | ", included) : DynamicEnum.GetValue(this).ToString();
|
||||
this.name = included.Count > 0 ? string.Join(" | ", included) : GetValue(this).ToString();
|
||||
}
|
||||
return this.name;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ namespace MLEM.Data {
|
|||
/// <returns>The newly created enum value</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if the name or value passed are already present</exception>
|
||||
public static T Add<T>(string name, BigInteger value) where T : DynamicEnum {
|
||||
var storage = DynamicEnum.GetStorage(typeof(T));
|
||||
var storage = GetStorage(typeof(T));
|
||||
|
||||
// cached parsed values and names might be incomplete with new values
|
||||
storage.ClearCaches();
|
||||
|
@ -119,7 +119,7 @@ namespace MLEM.Data {
|
|||
throw new ArgumentException($"Duplicate name {name}", nameof(name));
|
||||
}
|
||||
|
||||
var ret = DynamicEnum.Construct(typeof(T), name, value);
|
||||
var ret = Construct(typeof(T), name, value);
|
||||
storage.Values.Add(value, ret);
|
||||
return (T) ret;
|
||||
}
|
||||
|
@ -134,9 +134,9 @@ namespace MLEM.Data {
|
|||
/// <returns>The newly created enum value</returns>
|
||||
public static T AddValue<T>(string name) where T : DynamicEnum {
|
||||
BigInteger value = 0;
|
||||
while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||
while (GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||
value++;
|
||||
return DynamicEnum.Add<T>(name, value);
|
||||
return Add<T>(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -149,9 +149,9 @@ namespace MLEM.Data {
|
|||
/// <returns>The newly created enum value</returns>
|
||||
public static T AddFlag<T>(string name) where T : DynamicEnum {
|
||||
BigInteger value = 1;
|
||||
while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||
while (GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||
value <<= 1;
|
||||
return DynamicEnum.Add<T>(name, value);
|
||||
return Add<T>(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -161,7 +161,7 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type whose values to get</typeparam>
|
||||
/// <returns>The defined values for the given type</returns>
|
||||
public static IEnumerable<T> GetValues<T>() where T : DynamicEnum {
|
||||
return DynamicEnum.GetValues(typeof(T)).Cast<T>();
|
||||
return GetValues(typeof(T)).Cast<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -171,7 +171,7 @@ namespace MLEM.Data {
|
|||
/// <param name="type">The type whose values to get</param>
|
||||
/// <returns>The defined values for the given type</returns>
|
||||
public static IEnumerable<DynamicEnum> GetValues(Type type) {
|
||||
return DynamicEnum.GetStorage(type).Values.Values;
|
||||
return GetStorage(type).Values.Values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -182,9 +182,9 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the values</typeparam>
|
||||
/// <returns>The bitwise OR (|) combination</returns>
|
||||
public static T Or<T>(T left, T right) where T : DynamicEnum {
|
||||
var cache = DynamicEnum.GetStorage(typeof(T)).OrCache;
|
||||
var cache = GetStorage(typeof(T)).OrCache;
|
||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) | DynamicEnum.GetValue(right));
|
||||
ret = GetEnumValue<T>(GetValue(left) | GetValue(right));
|
||||
cache.Add((left, right), ret);
|
||||
}
|
||||
return (T) ret;
|
||||
|
@ -198,9 +198,9 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the values</typeparam>
|
||||
/// <returns>The bitwise AND (&) combination</returns>
|
||||
public static T And<T>(T left, T right) where T : DynamicEnum {
|
||||
var cache = DynamicEnum.GetStorage(typeof(T)).AndCache;
|
||||
var cache = GetStorage(typeof(T)).AndCache;
|
||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) & DynamicEnum.GetValue(right));
|
||||
ret = GetEnumValue<T>(GetValue(left) & GetValue(right));
|
||||
cache.Add((left, right), ret);
|
||||
}
|
||||
return (T) ret;
|
||||
|
@ -214,9 +214,9 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the values</typeparam>
|
||||
/// <returns>The bitwise XOR (^) combination</returns>
|
||||
public static T Xor<T>(T left, T right) where T : DynamicEnum {
|
||||
var cache = DynamicEnum.GetStorage(typeof(T)).XorCache;
|
||||
var cache = GetStorage(typeof(T)).XorCache;
|
||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) ^ DynamicEnum.GetValue(right));
|
||||
ret = GetEnumValue<T>(GetValue(left) ^ GetValue(right));
|
||||
cache.Add((left, right), ret);
|
||||
}
|
||||
return (T) ret;
|
||||
|
@ -229,9 +229,9 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the values</typeparam>
|
||||
/// <returns>The bitwise NEG (~) value</returns>
|
||||
public static T Neg<T>(T value) where T : DynamicEnum {
|
||||
var cache = DynamicEnum.GetStorage(typeof(T)).NegCache;
|
||||
var cache = GetStorage(typeof(T)).NegCache;
|
||||
if (!cache.TryGetValue(value, out var ret)) {
|
||||
ret = DynamicEnum.GetEnumValue<T>(~DynamicEnum.GetValue(value));
|
||||
ret = GetEnumValue<T>(~GetValue(value));
|
||||
cache.Add(value, ret);
|
||||
}
|
||||
return (T) ret;
|
||||
|
@ -253,7 +253,7 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type that the returned dynamic enum should have</typeparam>
|
||||
/// <returns>The defined or combined dynamic enum value</returns>
|
||||
public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum {
|
||||
return (T) DynamicEnum.GetEnumValue(typeof(T), value);
|
||||
return (T) GetEnumValue(typeof(T), value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -263,7 +263,7 @@ namespace MLEM.Data {
|
|||
/// <param name="value">The value whose dynamic enum value to get</param>
|
||||
/// <returns>The defined or combined dynamic enum value</returns>
|
||||
public static DynamicEnum GetEnumValue(Type type, BigInteger value) {
|
||||
var storage = DynamicEnum.GetStorage(type);
|
||||
var storage = GetStorage(type);
|
||||
|
||||
// get the defined value if it exists
|
||||
if (storage.Values.TryGetValue(value, out var defined))
|
||||
|
@ -271,7 +271,7 @@ namespace MLEM.Data {
|
|||
|
||||
// otherwise, cache the combined value
|
||||
if (!storage.FlagCache.TryGetValue(value, out var combined)) {
|
||||
combined = DynamicEnum.Construct(type, null, value);
|
||||
combined = Construct(type, null, value);
|
||||
storage.FlagCache.Add(value, combined);
|
||||
}
|
||||
return combined;
|
||||
|
@ -286,7 +286,7 @@ namespace MLEM.Data {
|
|||
/// <typeparam name="T">The type of the dynamic enum value to parse</typeparam>
|
||||
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
||||
public static T Parse<T>(string strg) where T : DynamicEnum {
|
||||
return (T) DynamicEnum.Parse(typeof(T), strg);
|
||||
return (T) Parse(typeof(T), strg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -297,28 +297,28 @@ namespace MLEM.Data {
|
|||
/// <param name="strg">The string to parse into a dynamic enum value</param>
|
||||
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
||||
public static DynamicEnum Parse(Type type, string strg) {
|
||||
var cache = DynamicEnum.GetStorage(type).ParseCache;
|
||||
var cache = GetStorage(type).ParseCache;
|
||||
if (!cache.TryGetValue(strg, out var cached)) {
|
||||
BigInteger? accum = null;
|
||||
foreach (var val in strg.Split('|')) {
|
||||
foreach (var defined in DynamicEnum.GetValues(type)) {
|
||||
foreach (var defined in GetValues(type)) {
|
||||
if (defined.name == val.Trim()) {
|
||||
accum = (accum ?? 0) | DynamicEnum.GetValue(defined);
|
||||
accum = (accum ?? 0) | GetValue(defined);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accum != null)
|
||||
cached = DynamicEnum.GetEnumValue(type, accum.Value);
|
||||
cached = GetEnumValue(type, accum.Value);
|
||||
cache.Add(strg, cached);
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
private static Storage GetStorage(Type type) {
|
||||
if (!DynamicEnum.Storages.TryGetValue(type, out var storage)) {
|
||||
if (!Storages.TryGetValue(type, out var storage)) {
|
||||
storage = new Storage();
|
||||
DynamicEnum.Storages.Add(type, storage);
|
||||
Storages.Add(type, storage);
|
||||
}
|
||||
return storage;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace MLEM.Data.Json {
|
|||
/// <param name="serializer">The serializer to add the converters to</param>
|
||||
/// <returns>The given serializer, for chaining</returns>
|
||||
public static JsonSerializer AddAll(JsonSerializer serializer) {
|
||||
foreach (var converter in JsonConverters.Converters)
|
||||
foreach (var converter in Converters)
|
||||
serializer.Converters.Add(converter);
|
||||
return serializer;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace MLEM.Data.Json {
|
|||
/// </summary>
|
||||
/// <param name="type">The type that the dictionary is declared in</param>
|
||||
/// <param name="memberName">The name of the dictionary itself</param>
|
||||
public StaticJsonConverter(Type type, string memberName) : this(StaticJsonConverter<T>.GetEntries(type, memberName)) {}
|
||||
public StaticJsonConverter(Type type, string memberName) : this(GetEntries(type, memberName)) {}
|
||||
|
||||
/// <summary>Writes the JSON representation of the object.</summary>
|
||||
/// <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];
|
||||
|
||||
if (ignoreTransparent) {
|
||||
if (this.IsTransparent(region))
|
||||
if (IsTransparent(region))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -180,8 +180,8 @@ namespace MLEM.Data {
|
|||
var width = this.alreadyPackedTextures.Max(t => t.PackedArea.Right);
|
||||
var height = this.alreadyPackedTextures.Max(t => t.PackedArea.Bottom);
|
||||
if (this.forcePowerOfTwo) {
|
||||
width = RuntimeTexturePacker.ToPowerOfTwo(width);
|
||||
height = RuntimeTexturePacker.ToPowerOfTwo(height);
|
||||
width = ToPowerOfTwo(width);
|
||||
height = ToPowerOfTwo(height);
|
||||
}
|
||||
if (this.forceSquare)
|
||||
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="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) {
|
||||
var draw = drawFunction ?? IndividualTiledMapRenderer.DefaultDraw;
|
||||
var draw = drawFunction ?? DefaultDraw;
|
||||
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
|
||||
for (var x = minX; x < maxX; x++) {
|
||||
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="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) {
|
||||
var add = addFunction ?? IndividualTiledMapRenderer.DefaultAdd;
|
||||
var add = addFunction ?? DefaultAdd;
|
||||
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
|
||||
for (var x = minX; x < maxX; x++) {
|
||||
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>
|
||||
public override int GetHashCode() {
|
||||
var hashCode = this.Layer.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.X;
|
||||
hashCode = hashCode * 397 ^ this.Y;
|
||||
hashCode = (hashCode * 397) ^ this.X;
|
||||
hashCode = (hashCode * 397) ^ this.Y;
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <param name="right">The right position.</param>
|
||||
/// <returns>The sum of the positions.</returns>
|
||||
public static LayerPosition operator +(LayerPosition left, LayerPosition right) {
|
||||
return LayerPosition.Add(left, right);
|
||||
return Add(left, right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -115,7 +115,7 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <param name="right">The right position.</param>
|
||||
/// <returns>The difference of the positions.</returns>
|
||||
public static LayerPosition operator -(LayerPosition left, LayerPosition right) {
|
||||
return LayerPosition.Add(left, -right);
|
||||
return Add(left, -right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode() {
|
||||
var hashCode = this.Layer.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.X.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.Y.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ this.X.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ this.Y.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <param name="right">The right position.</param>
|
||||
/// <returns>The sum of the positions.</returns>
|
||||
public static LayerPositionF operator +(LayerPositionF left, LayerPositionF right) {
|
||||
return LayerPositionF.Add(left, right);
|
||||
return Add(left, right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -115,7 +115,7 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <param name="right">The right position.</param>
|
||||
/// <returns>The difference of the positions.</returns>
|
||||
public static LayerPositionF operator -(LayerPositionF left, LayerPositionF right) {
|
||||
return LayerPositionF.Add(left, -right);
|
||||
return Add(left, -right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -5,6 +5,7 @@ using Microsoft.Xna.Framework;
|
|||
using Microsoft.Xna.Framework.Graphics;
|
||||
using MonoGame.Extended;
|
||||
using MonoGame.Extended.Tiled;
|
||||
using static MonoGame.Extended.Tiled.TiledMapTileFlipFlags;
|
||||
using ColorHelper = MLEM.Extensions.ColorHelper;
|
||||
|
||||
namespace MLEM.Extended.Tiled {
|
||||
|
@ -143,9 +144,9 @@ namespace MLEM.Extended.Tiled {
|
|||
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, int localId, bool createStub = true) {
|
||||
var tilesetTile = tileset.Tiles.FirstOrDefault(t => t.LocalTileIdentifier == localId);
|
||||
if (tilesetTile == null && createStub) {
|
||||
if (!TiledExtensions.StubTilesetTiles.TryGetValue(localId, out tilesetTile)) {
|
||||
if (!StubTilesetTiles.TryGetValue(localId, out tilesetTile)) {
|
||||
tilesetTile = new TiledMapTilesetTile(localId);
|
||||
TiledExtensions.StubTilesetTiles.Add(localId, tilesetTile);
|
||||
StubTilesetTiles.Add(localId, tilesetTile);
|
||||
}
|
||||
}
|
||||
return tilesetTile;
|
||||
|
@ -270,12 +271,12 @@ namespace MLEM.Extended.Tiled {
|
|||
/// <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>
|
||||
/// <returns>The area that the tile covers</returns>
|
||||
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = TiledMapTileFlipFlags.None) {
|
||||
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = None) {
|
||||
var tileSize = map.GetTileSize();
|
||||
var area = new RectangleF(obj.Position / tileSize, obj.Size / tileSize);
|
||||
if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipHorizontally))
|
||||
if (flipFlags.HasFlag(FlipHorizontally))
|
||||
area.X = 1 - area.X - area.Width;
|
||||
if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipVertically))
|
||||
if (flipFlags.HasFlag(FlipVertically))
|
||||
area.Y = 1 - area.Y - area.Height;
|
||||
if (position != null)
|
||||
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>
|
||||
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
|
||||
this.map = map;
|
||||
this.collisionFunction = collisionFunction ?? TiledMapCollisions.DefaultCollectCollisions;
|
||||
this.collisionFunction = collisionFunction ?? DefaultCollectCollisions;
|
||||
this.collisionInfos = new TileCollisionInfo[map.Layers.Count, map.Width, map.Height];
|
||||
for (var i = 0; i < map.TileLayers.Count; i++) {
|
||||
for (var x = 0; x < map.Width; x++) {
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace MLEM.Startup {
|
|||
/// <summary>
|
||||
/// The static game instance's input handler
|
||||
/// </summary>
|
||||
public static InputHandler Input => MlemGame.instance.InputHandler;
|
||||
public static InputHandler Input => instance.InputHandler;
|
||||
|
||||
/// <summary>
|
||||
/// 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="windowHeight">The default window height</param>
|
||||
public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
|
||||
MlemGame.instance = this;
|
||||
instance = this;
|
||||
|
||||
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
|
||||
PreferredBackBufferWidth = windowWidth,
|
||||
|
@ -160,7 +160,7 @@ namespace MLEM.Startup {
|
|||
/// <typeparam name="T">The type of content to load</typeparam>
|
||||
/// <returns>The loaded content</returns>
|
||||
public static T LoadContent<T>(string name) {
|
||||
return MlemGame.instance.Content.Load<T>(name);
|
||||
return instance.Content.Load<T>(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -652,7 +652,7 @@ namespace MLEM.Ui.Elements {
|
|||
var newX = prevArea.Right + this.ScaledOffset.X;
|
||||
// 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
|
||||
if (newX + newSize.X <= parentArea.Right + Element.Epsilon) {
|
||||
if (newX + newSize.X <= parentArea.Right + Epsilon) {
|
||||
pos.X = newX;
|
||||
pos.Y = prevArea.Y + this.ScaledOffset.Y;
|
||||
} else {
|
||||
|
@ -715,7 +715,7 @@ namespace MLEM.Ui.Elements {
|
|||
}
|
||||
|
||||
// we want to leave some leeway to prevent float rounding causing an infinite loop
|
||||
if (!autoSize.Equals(this.UnscrolledArea.Size, Element.Epsilon)) {
|
||||
if (!autoSize.Equals(this.UnscrolledArea.Size, Epsilon)) {
|
||||
recursion++;
|
||||
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?");
|
||||
|
|
|
@ -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})"/>
|
||||
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 ElementHelper.KeybindButton(anchor, size, keybind, inputHandler, activePlaceholder, new Keybind(unbindKey), unboundPlaceholder, inputName, index, isKeybindAllowed);
|
||||
return KeybindButton(anchor, size, keybind, inputHandler, activePlaceholder, new Keybind(unbindKey), unboundPlaceholder, inputName, index, isKeybindAllowed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -139,9 +139,7 @@ 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>
|
||||
/// <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) {
|
||||
string GetCurrentName() {
|
||||
return keybind.TryGetCombination(index, out var combination) ? combination.ToString(" + ", inputName) : unboundPlaceholder;
|
||||
}
|
||||
string GetCurrentName() => keybind.TryGetCombination(index, out var combination) ? combination.ToString(" + ", inputName) : unboundPlaceholder;
|
||||
|
||||
var button = new Button(anchor, size, GetCurrentName());
|
||||
var activeNext = false;
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace MLEM.Ui.Elements {
|
|||
var offset = new Vector2(0, -this.ScrollBar.CurrentValue);
|
||||
// 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)) {
|
||||
if (!child.ScrollOffset.Equals(offset, Element.Epsilon)) {
|
||||
if (!child.ScrollOffset.Equals(offset, Epsilon)) {
|
||||
child.ScrollOffset = offset;
|
||||
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
|
||||
var scrollBarMax = (childrenHeight - this.ChildPaddedArea.Height) / this.Scale;
|
||||
if (!this.ScrollBar.MaxValue.Equals(scrollBarMax, Element.Epsilon)) {
|
||||
if (!this.ScrollBar.MaxValue.Equals(scrollBarMax, Epsilon)) {
|
||||
this.ScrollBar.MaxValue = scrollBarMax;
|
||||
this.relevantChildrenDirty = true;
|
||||
|
||||
// update child padding based on whether the scroll bar is visible
|
||||
var childOffset = this.ScrollBar.IsHidden ? 0 : this.ScrollerSize.Value.X + this.ScrollBarOffset;
|
||||
if (!this.scrollBarChildOffset.Equals(childOffset, Element.Epsilon)) {
|
||||
if (!this.scrollBarChildOffset.Equals(childOffset, Epsilon)) {
|
||||
this.ChildPadding += new Padding(0, -this.scrollBarChildOffset + childOffset, 0, 0);
|
||||
this.scrollBarChildOffset = childOffset;
|
||||
this.SetAreaDirty();
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace MLEM.Ui.Elements {
|
|||
if (this.text != value) {
|
||||
this.text = value;
|
||||
this.SetTextDirty();
|
||||
|
||||
|
||||
var force = string.IsNullOrWhiteSpace(this.text);
|
||||
if (this.forceHide != force) {
|
||||
this.forceHide = force;
|
||||
|
@ -197,7 +197,7 @@ namespace MLEM.Ui.Elements {
|
|||
protected void SetTextDirty() {
|
||||
this.TokenizedText = null;
|
||||
// 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, Element.Epsilon))
|
||||
if (!this.AreaDirty && !this.CalcActualSize(this.ParentArea).Equals(this.DisplayArea.Size, Epsilon))
|
||||
this.SetAreaDirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace MLEM.Ui.Elements {
|
|||
// force current value to be clamped
|
||||
this.CurrentValue = this.CurrentValue;
|
||||
// auto-hide if necessary
|
||||
var shouldHide = this.maxValue <= Element.Epsilon;
|
||||
var shouldHide = this.maxValue <= Epsilon;
|
||||
if (this.AutoHideWhenEmpty && this.IsHidden != shouldHide) {
|
||||
this.IsHidden = shouldHide;
|
||||
this.OnAutoHide?.Invoke(this);
|
||||
|
@ -188,7 +188,7 @@ namespace MLEM.Ui.Elements {
|
|||
|
||||
if (this.SmoothScrolling && this.scrollAdded != 0) {
|
||||
this.scrollAdded *= this.SmoothScrollFactor;
|
||||
if (Math.Abs(this.scrollAdded) <= Element.Epsilon)
|
||||
if (Math.Abs(this.scrollAdded) <= Epsilon)
|
||||
this.scrollAdded = 0;
|
||||
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
|
||||
for (var i = 0; i < this.SortedChildren.Count; i++) {
|
||||
var child = this.SortedChildren[i];
|
||||
if (SquishingGroup.SquishChild(child, out var squished))
|
||||
if (SquishChild(child, out var squished))
|
||||
child.SetAreaAndUpdateChildren(squished);
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ namespace MLEM.Ui.Elements {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!pos.Equals(element.Area.Location, Element.Epsilon) || !size.Equals(element.Area.Size, Element.Epsilon)) {
|
||||
if (!pos.Equals(element.Area.Location, Epsilon) || !size.Equals(element.Area.Size, Epsilon)) {
|
||||
squishedArea = new RectangleF(pos, size);
|
||||
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="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) {
|
||||
this.InputRule = rule ?? TextField.DefaultRule;
|
||||
this.InputRule = rule ?? DefaultRule;
|
||||
this.Multiline = multiline;
|
||||
if (font != null)
|
||||
this.Font = font;
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace MLEM.Ui.Parsers {
|
|||
this.Style<VerticalSpace>(ElementType.VerticalSpace, v => v.Size = new Vector2(1, 5));
|
||||
for (var i = 0; i < 6; i++) {
|
||||
var level = i;
|
||||
this.Style<Paragraph>(UiMarkdownParser.ElementTypes[Array.IndexOf(UiMarkdownParser.ElementTypes, ElementType.Header1) + i], p => {
|
||||
this.Style<Paragraph>(ElementTypes[Array.IndexOf(ElementTypes, ElementType.Header1) + i], p => {
|
||||
p.Alignment = TextAlignment.Center;
|
||||
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>
|
||||
/// <returns>This parser, for chaining.</returns>
|
||||
public UiMarkdownParser Style<T>(ElementType types, Action<T> style, bool add = false) where T : Element {
|
||||
foreach (var type in UiMarkdownParser.ElementTypes) {
|
||||
foreach (var type in ElementTypes) {
|
||||
if (types.HasFlag(type)) {
|
||||
if (add && this.elementStyles.ContainsKey(type)) {
|
||||
this.elementStyles[type] += Action;
|
||||
|
@ -193,7 +193,7 @@ namespace MLEM.Ui.Parsers {
|
|||
var parsedHeader = false;
|
||||
for (var h = 6; h >= 1; h--) {
|
||||
if (line.StartsWith(new string('#', h))) {
|
||||
var type = UiMarkdownParser.ElementTypes[Array.IndexOf(UiMarkdownParser.ElementTypes, ElementType.Header1) + h - 1];
|
||||
var type = ElementTypes[Array.IndexOf(ElementTypes, ElementType.Header1) + h - 1];
|
||||
yield return (type, new Paragraph(Anchor.AutoLeft, 1, line.Substring(h).Trim()));
|
||||
parsedHeader = true;
|
||||
break;
|
||||
|
@ -275,7 +275,7 @@ namespace MLEM.Ui.Parsers {
|
|||
/// A combined flag that contains <see cref="Header1"/> through <see cref="Header6"/>.
|
||||
/// This element type is a <see cref="Paragraph"/>.
|
||||
/// </summary>
|
||||
Headers = ElementType.Header1 | ElementType.Header2 | ElementType.Header3 | ElementType.Header4 | ElementType.Header5 | ElementType.Header6,
|
||||
Headers = Header1 | Header2 | Header3 | Header4 | Header5 | Header6,
|
||||
/// <summary>
|
||||
/// A paragraph, which is one line of markdown text.
|
||||
/// This element type is a <see cref="Paragraph"/>.
|
||||
|
|
|
@ -164,7 +164,7 @@ namespace MLEM.Cameras {
|
|||
if (this.Max.Y > max.Y)
|
||||
this.Max = new Vector2(this.Max.X, max.Y);
|
||||
}
|
||||
return !this.Position.Equals(lastPos, Camera.Epsilon);
|
||||
return !this.Position.Equals(lastPos, Epsilon);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -15,9 +15,9 @@ namespace MLEM.Extensions {
|
|||
/// <param name="c">The character to turn into a string</param>
|
||||
/// <returns>A string representing the character</returns>
|
||||
public static string ToCachedString(this char c) {
|
||||
if (!CharExtensions.Cache.TryGetValue(c, out var ret)) {
|
||||
if (!Cache.TryGetValue(c, out var ret)) {
|
||||
ret = c.ToString();
|
||||
CharExtensions.Cache.Add(c, ret);
|
||||
Cache.Add(c, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace MLEM.Extensions {
|
|||
/// <param name="value">The number to parse.</param>
|
||||
/// <returns>The resulting color.</returns>
|
||||
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>
|
||||
|
@ -60,7 +60,7 @@ namespace MLEM.Extensions {
|
|||
/// <param name="value">The number to parse.</param>
|
||||
/// <returns>The resulting color.</returns>
|
||||
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>
|
||||
|
@ -73,7 +73,7 @@ namespace MLEM.Extensions {
|
|||
if (value.StartsWith("#"))
|
||||
value = value.Substring(1);
|
||||
var val = int.Parse(value, NumberStyles.HexNumber);
|
||||
return value.Length > 6 ? ColorHelper.FromHexRgba(val) : ColorHelper.FromHexRgb(val);
|
||||
return value.Length > 6 ? FromHexRgba(val) : FromHexRgb(val);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,18 +21,18 @@ namespace MLEM.Extensions {
|
|||
manager.IsFullScreen = fullscreen;
|
||||
if (fullscreen) {
|
||||
var view = manager.GraphicsDevice.Viewport;
|
||||
GraphicsExtensions.lastWidth = view.Width;
|
||||
GraphicsExtensions.lastHeight = view.Height;
|
||||
lastWidth = view.Width;
|
||||
lastHeight = view.Height;
|
||||
|
||||
var curr = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode;
|
||||
manager.PreferredBackBufferWidth = curr.Width;
|
||||
manager.PreferredBackBufferHeight = curr.Height;
|
||||
} else {
|
||||
if (GraphicsExtensions.lastWidth <= 0 || GraphicsExtensions.lastHeight <= 0)
|
||||
if (lastWidth <= 0 || lastHeight <= 0)
|
||||
throw new InvalidOperationException("Can't call SetFullscreen to change out of fullscreen mode without going into fullscreen mode first");
|
||||
|
||||
manager.PreferredBackBufferWidth = GraphicsExtensions.lastWidth;
|
||||
manager.PreferredBackBufferHeight = GraphicsExtensions.lastHeight;
|
||||
manager.PreferredBackBufferWidth = lastWidth;
|
||||
manager.PreferredBackBufferHeight = lastHeight;
|
||||
}
|
||||
manager.ApplyChanges();
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace MLEM.Extensions {
|
|||
/// <param name="batch">The sprite batch</param>
|
||||
/// <returns>A 1x1 pixel white texture</returns>
|
||||
public static Texture2D GetBlankTexture(this SpriteBatch batch) {
|
||||
if (SpriteBatchExtensions.blankTexture == null) {
|
||||
SpriteBatchExtensions.blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1);
|
||||
SpriteBatchExtensions.blankTexture.SetData(new[] {Color.White});
|
||||
SpriteBatchExtensions.AutoDispose(batch, SpriteBatchExtensions.blankTexture);
|
||||
if (blankTexture == null) {
|
||||
blankTexture = new Texture2D(batch.GraphicsDevice, 1, 1);
|
||||
blankTexture.SetData(new[] {Color.White});
|
||||
AutoDispose(batch, blankTexture);
|
||||
}
|
||||
return SpriteBatchExtensions.blankTexture;
|
||||
return blankTexture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -43,7 +43,7 @@ namespace MLEM.Extensions {
|
|||
outli, color, outli,
|
||||
outli, outli, outli
|
||||
});
|
||||
SpriteBatchExtensions.AutoDispose(batch, tex);
|
||||
AutoDispose(batch, tex);
|
||||
return new NinePatch(tex, 1);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace MLEM.Extensions {
|
|||
public static Texture2D GenerateSquareTexture(this SpriteBatch batch, Color color) {
|
||||
var tex = new Texture2D(batch.GraphicsDevice, 1, 1);
|
||||
tex.SetData(new[] {color});
|
||||
SpriteBatchExtensions.AutoDispose(batch, tex);
|
||||
AutoDispose(batch, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace MLEM.Extensions {
|
|||
}
|
||||
}
|
||||
}
|
||||
SpriteBatchExtensions.AutoDispose(batch, tex);
|
||||
AutoDispose(batch, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ namespace MLEM.Extensions {
|
|||
data[x, y] = Color.Lerp(top, btm, y / (float) height);
|
||||
}
|
||||
}
|
||||
SpriteBatchExtensions.AutoDispose(batch, tex);
|
||||
AutoDispose(batch, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace MLEM.Font {
|
|||
public const char Emsp = '\u2003';
|
||||
/// <inheritdoc cref="Emsp"/>
|
||||
[Obsolete("Use the Emsp field instead.")]
|
||||
public const char OneEmSpace = GenericFont.Emsp;
|
||||
public const char OneEmSpace = Emsp;
|
||||
/// <summary>
|
||||
/// This field holds the unicode representation of a non-breaking space.
|
||||
/// Whereas a regular <see cref="SpriteFont"/> would have to explicitly support this character for width calculations, generic fonts implicitly support it in <see cref="MeasureString(string,bool)"/>.
|
||||
|
@ -185,17 +185,17 @@ namespace MLEM.Font {
|
|||
xOffset = 0;
|
||||
size.Y += this.LineHeight;
|
||||
break;
|
||||
case GenericFont.Emsp:
|
||||
case Emsp:
|
||||
xOffset += this.LineHeight;
|
||||
break;
|
||||
case GenericFont.Nbsp:
|
||||
case Nbsp:
|
||||
xOffset += font.MeasureChar(' ');
|
||||
break;
|
||||
case GenericFont.Zwsp:
|
||||
case Zwsp:
|
||||
// don't add width for a zero-width space
|
||||
break;
|
||||
case ' ':
|
||||
if (ignoreTrailingSpaces && GenericFont.IsTrailingSpace(text, i)) {
|
||||
if (ignoreTrailingSpaces && IsTrailingSpace(text, i)) {
|
||||
// if this is a trailing space, we can skip remaining spaces too
|
||||
i = text.Length - 1;
|
||||
break;
|
||||
|
@ -252,7 +252,7 @@ namespace MLEM.Font {
|
|||
} else {
|
||||
var font = fontFunction?.Invoke(i) ?? this;
|
||||
var cWidth = font.MeasureString(c.ToCachedString()).X * scale;
|
||||
if (c == ' ' || c == GenericFont.Emsp || c == GenericFont.Zwsp) {
|
||||
if (c == ' ' || c == Emsp || c == Zwsp) {
|
||||
// remember the location of this (breaking!) space
|
||||
lastSpaceIndex = curr.Length;
|
||||
widthSinceLastSpace = 0;
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace MLEM.Font {
|
|||
/// <param name="bold">A bold 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) {
|
||||
this.Font = GenericSpriteFont.SetDefaults(font);
|
||||
this.Bold = bold != null ? new GenericSpriteFont(GenericSpriteFont.SetDefaults(bold)) : this;
|
||||
this.Italic = italic != null ? new GenericSpriteFont(GenericSpriteFont.SetDefaults(italic)) : this;
|
||||
this.Font = SetDefaults(font);
|
||||
this.Bold = bold != null ? new GenericSpriteFont(SetDefaults(bold)) : this;
|
||||
this.Italic = italic != null ? new GenericSpriteFont(SetDefaults(italic)) : this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -87,13 +87,13 @@ namespace MLEM.Formatting {
|
|||
// if we've reached the end of the string
|
||||
if (next == null) {
|
||||
var sub = s.Substring(rawIndex, s.Length - rawIndex);
|
||||
tokens.Add(new Token(codes.ToArray(), index, rawIndex, TextFormatter.StripFormatting(font, sub, codes), sub));
|
||||
tokens.Add(new Token(codes.ToArray(), index, rawIndex, StripFormatting(font, sub, codes), sub));
|
||||
break;
|
||||
}
|
||||
|
||||
// create a new token for the content up to the next code
|
||||
var ret = s.Substring(rawIndex, next.Match.Index - rawIndex);
|
||||
var strippedRet = TextFormatter.StripFormatting(font, ret, codes);
|
||||
var strippedRet = StripFormatting(font, ret, codes);
|
||||
tokens.Add(new Token(codes.ToArray(), index, rawIndex, strippedRet, ret));
|
||||
|
||||
// move to the start of the next code
|
||||
|
@ -104,7 +104,7 @@ namespace MLEM.Formatting {
|
|||
codes.RemoveAll(c => c.EndsHere(next));
|
||||
codes.Add(next);
|
||||
}
|
||||
return new TokenizedString(font, alignment, s, TextFormatter.StripFormatting(font, s, tokens.SelectMany(t => t.AppliedCodes)), tokens.ToArray());
|
||||
return new TokenizedString(font, alignment, s, StripFormatting(font, s, tokens.SelectMany(t => t.AppliedCodes)), tokens.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -123,12 +123,12 @@ namespace MLEM.Formatting {
|
|||
var token = this.Tokens[t];
|
||||
var drawFont = token.GetFont(font);
|
||||
var drawColor = token.GetColor(color);
|
||||
|
||||
|
||||
var indexInToken = 0;
|
||||
for (var l = 0; l < token.SplitDisplayString.Length; l++) {
|
||||
foreach (var c in token.SplitDisplayString[l]) {
|
||||
var cString = c.ToCachedString();
|
||||
|
||||
|
||||
if (indexInToken == 0)
|
||||
token.DrawSelf(time, batch, pos + innerOffset, drawFont, color, scale, depth);
|
||||
token.DrawCharacter(time, batch, c, cString, indexInToken, pos + innerOffset, drawFont, drawColor, scale, depth);
|
||||
|
@ -136,7 +136,7 @@ namespace MLEM.Formatting {
|
|||
innerOffset.X += drawFont.MeasureString(cString).X * scale;
|
||||
indexInToken++;
|
||||
}
|
||||
|
||||
|
||||
// only split at a new line, not between tokens!
|
||||
if (l < token.SplitDisplayString.Length - 1) {
|
||||
innerOffset.X = token.InnerOffsets[l] * scale;
|
||||
|
|
|
@ -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) {
|
||||
var orig = origin ?? Vector2.Zero;
|
||||
var sc = scale ?? Vector2.One;
|
||||
var (p1, r1, p2, r2, p3, r3, p4, r4) = AutoTiling.CalculateAutoTile(pos, texture.Area, connectsTo, sc);
|
||||
var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, texture.Area, connectsTo, sc);
|
||||
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, 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) {
|
||||
var orig = origin ?? Vector2.Zero;
|
||||
var sc = scale ?? Vector2.One;
|
||||
var (p1, r1, p2, r2, p3, r3, p4, r4) = AutoTiling.CalculateAutoTile(pos, texture.Area, connectsTo, sc);
|
||||
var (p1, r1, p2, r2, p3, r3, p4, r4) = CalculateAutoTile(pos, texture.Area, connectsTo, sc);
|
||||
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 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 sc = scale ?? Vector2.One;
|
||||
var od = layerDepth + overlayDepthOffset;
|
||||
var (r1, r2, r3, r4) = AutoTiling.CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
|
||||
var (r1, r2, r3, r4) = CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
|
||||
if (backgroundTexture != null)
|
||||
batch.Draw(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth);
|
||||
if (r1 != Rectangle.Empty)
|
||||
|
@ -106,7 +106,7 @@ namespace MLEM.Graphics {
|
|||
var orig = origin ?? Vector2.Zero;
|
||||
var sc = scale ?? Vector2.One;
|
||||
var od = layerDepth + overlayDepthOffset;
|
||||
var (r1, r2, r3, r4) = AutoTiling.CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
|
||||
var (r1, r2, r3, r4) = CalculateExtendedAutoTile(pos, overlayTexture.Area, connectsTo, sc);
|
||||
if (backgroundTexture != null) {
|
||||
var background = batch.Add(backgroundTexture, pos, backgroundColor, 0, orig, sc, SpriteEffects.None, layerDepth);
|
||||
items?.Add(background);
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace MLEM.Graphics {
|
|||
|
||||
// this maximum is limited by indices being a short
|
||||
private const int MaxBatchItems = short.MaxValue / 6;
|
||||
private static readonly VertexPositionColorTexture[] Data = new VertexPositionColorTexture[StaticSpriteBatch.MaxBatchItems * 4];
|
||||
private static readonly VertexPositionColorTexture[] Data = new VertexPositionColorTexture[MaxBatchItems * 4];
|
||||
|
||||
/// <summary>
|
||||
/// The amount of vertices that are currently batched.
|
||||
|
@ -106,21 +106,21 @@ namespace MLEM.Graphics {
|
|||
Texture2D texture = null;
|
||||
foreach (var item in ordered) {
|
||||
// if the texture changes, we also have to start a new buffer!
|
||||
if (dataIndex > 0 && (item.Texture != texture || dataIndex >= StaticSpriteBatch.Data.Length)) {
|
||||
this.FillBuffer(this.FilledBuffers++, texture, StaticSpriteBatch.Data);
|
||||
if (dataIndex > 0 && (item.Texture != texture || dataIndex >= Data.Length)) {
|
||||
this.FillBuffer(this.FilledBuffers++, texture, Data);
|
||||
dataIndex = 0;
|
||||
}
|
||||
StaticSpriteBatch.Data[dataIndex++] = item.TopLeft;
|
||||
StaticSpriteBatch.Data[dataIndex++] = item.TopRight;
|
||||
StaticSpriteBatch.Data[dataIndex++] = item.BottomLeft;
|
||||
StaticSpriteBatch.Data[dataIndex++] = item.BottomRight;
|
||||
Data[dataIndex++] = item.TopLeft;
|
||||
Data[dataIndex++] = item.TopRight;
|
||||
Data[dataIndex++] = item.BottomLeft;
|
||||
Data[dataIndex++] = item.BottomRight;
|
||||
texture = item.Texture;
|
||||
}
|
||||
if (dataIndex > 0)
|
||||
this.FillBuffer(this.FilledBuffers++, texture, StaticSpriteBatch.Data);
|
||||
this.FillBuffer(this.FilledBuffers++, texture, Data);
|
||||
|
||||
// ensure we have enough indices
|
||||
var maxItems = Math.Min(this.items.Count, StaticSpriteBatch.MaxBatchItems);
|
||||
var maxItems = Math.Min(this.items.Count, MaxBatchItems);
|
||||
// each item has 2 triangles which each have 3 indices
|
||||
if (this.indices == null || this.indices.IndexCount < 6 * maxItems) {
|
||||
var newIndices = new short[6 * maxItems];
|
||||
|
@ -434,7 +434,7 @@ namespace MLEM.Graphics {
|
|||
|
||||
private void FillBuffer(int index, Texture2D texture, VertexPositionColorTexture[] data) {
|
||||
if (this.vertexBuffers.Count <= index)
|
||||
this.vertexBuffers.Add(new VertexBuffer(this.graphicsDevice, VertexPositionColorTexture.VertexDeclaration, StaticSpriteBatch.MaxBatchItems * 4, BufferUsage.WriteOnly));
|
||||
this.vertexBuffers.Add(new VertexBuffer(this.graphicsDevice, VertexPositionColorTexture.VertexDeclaration, MaxBatchItems * 4, BufferUsage.WriteOnly));
|
||||
this.vertexBuffers[index].SetData(data);
|
||||
this.textures.Insert(index, texture);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,13 @@ namespace MLEM.Input {
|
|||
/// Returns this generic input's <see cref="Keys"/>.
|
||||
/// </summary>
|
||||
/// <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 => this.Type == InputType.None ? 0 : this.Type == InputType.Keyboard ? (Keys) this.value : throw new InvalidOperationException();
|
||||
public Keys Key {
|
||||
get {
|
||||
if (this.Type == InputType.None)
|
||||
return Keys.None;
|
||||
return this.Type == InputType.Keyboard ? (Keys) this.value : throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns this generic input's <see cref="MouseButton"/>.
|
||||
/// </summary>
|
||||
|
@ -33,8 +39,8 @@ namespace MLEM.Input {
|
|||
/// <summary>
|
||||
/// Returns this generic input's <see cref="Buttons"/>.
|
||||
/// </summary>
|
||||
/// <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.None ? 0 : this.Type == InputType.Gamepad ? (Buttons) this.value : throw new InvalidOperationException();
|
||||
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/>.</exception>
|
||||
public Buttons Button => this.Type == InputType.Gamepad ? (Buttons) this.value : throw new InvalidOperationException();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new generic input from the given keyboard <see cref="Keys"/>.
|
||||
|
@ -101,7 +107,7 @@ namespace MLEM.Input {
|
|||
/// <summary>Returns the hash code for this instance.</summary>
|
||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode() {
|
||||
return (int) this.Type * 397 ^ this.value;
|
||||
return ((int) this.Type * 397) ^ this.value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -829,9 +829,9 @@ namespace MLEM.Input {
|
|||
/// <param name="gestures">The gestures to enable or disable</param>
|
||||
public static void SetGesturesEnabled(bool enabled, params GestureType[] gestures) {
|
||||
if (enabled) {
|
||||
InputHandler.EnableGestures(gestures);
|
||||
EnableGestures(gestures);
|
||||
} else {
|
||||
InputHandler.DisableGestures(gestures);
|
||||
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>
|
||||
public int CompareTo(object obj) {
|
||||
if (object.ReferenceEquals(null, obj))
|
||||
if (ReferenceEquals(null, obj))
|
||||
return 1;
|
||||
if (object.ReferenceEquals(this, obj))
|
||||
if (ReferenceEquals(this, obj))
|
||||
return 0;
|
||||
if (!(obj is Keybind other))
|
||||
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>
|
||||
public int CompareTo(object obj) {
|
||||
if (object.ReferenceEquals(null, obj))
|
||||
if (ReferenceEquals(null, obj))
|
||||
return 1;
|
||||
if (object.ReferenceEquals(this, obj))
|
||||
if (ReferenceEquals(this, obj))
|
||||
return 0;
|
||||
if (!(obj is Combination other))
|
||||
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.Alt, new[] {Keys.LeftAlt, Keys.RightAlt}}
|
||||
};
|
||||
private static readonly Dictionary<Keys, ModifierKey> ModifiersLookup = KeysExtensions.KeysLookup
|
||||
private static readonly Dictionary<Keys, ModifierKey> ModifiersLookup = KeysLookup
|
||||
.SelectMany(kv => kv.Value.Select(v => (kv.Key, v)))
|
||||
.ToDictionary(kv => kv.Item2, kv => kv.Item1);
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace MLEM.Input {
|
|||
/// <param name="modifier">The modifier key</param>
|
||||
/// <returns>All of the keys the modifier key represents</returns>
|
||||
public static IEnumerable<Keys> GetKeys(this ModifierKey modifier) {
|
||||
return KeysExtensions.KeysLookup.TryGetValue(modifier, out var keys) ? keys : Enumerable.Empty<Keys>();
|
||||
return KeysLookup.TryGetValue(modifier, out var keys) ? keys : Enumerable.Empty<Keys>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -38,12 +38,12 @@ namespace MLEM.Input {
|
|||
/// <param name="key">The key to convert to a modifier key</param>
|
||||
/// <returns>The modifier key, or <see cref="ModifierKey.None"/></returns>
|
||||
public static ModifierKey GetModifier(this Keys key) {
|
||||
return KeysExtensions.ModifiersLookup.TryGetValue(key, out var mod) ? mod : ModifierKey.None;
|
||||
return ModifiersLookup.TryGetValue(key, out var mod) ? mod : ModifierKey.None;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="GetModifier(Microsoft.Xna.Framework.Input.Keys)"/>
|
||||
public static ModifierKey GetModifier(this GenericInput input) {
|
||||
return input.Type == GenericInput.InputType.Keyboard ? ((Keys) input).GetModifier() : ModifierKey.None;
|
||||
return input.Type == GenericInput.InputType.Keyboard ? GetModifier((Keys) input) : ModifierKey.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -52,12 +52,12 @@ namespace MLEM.Input {
|
|||
/// <param name="key">The key</param>
|
||||
/// <returns>If the key is a modifier key</returns>
|
||||
public static bool IsModifier(this Keys key) {
|
||||
return key.GetModifier() != ModifierKey.None;
|
||||
return GetModifier(key) != ModifierKey.None;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IsModifier(Microsoft.Xna.Framework.Input.Keys)"/>
|
||||
public static bool IsModifier(this GenericInput input) {
|
||||
return input.GetModifier() != ModifierKey.None;
|
||||
return GetModifier(input) != ModifierKey.None;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using static MLEM.Misc.Direction2;
|
||||
|
||||
namespace MLEM.Misc {
|
||||
/// <summary>
|
||||
|
@ -44,22 +45,22 @@ namespace MLEM.Misc {
|
|||
/// The up and right direction, or +x, -y.
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
UpRight = Direction2.Up | Direction2.Right,
|
||||
UpRight = Up | Right,
|
||||
/// <summary>
|
||||
/// The down and right direction, or +x, +y.
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
DownRight = Direction2.Down | Direction2.Right,
|
||||
DownRight = Down | Right,
|
||||
/// <summary>
|
||||
/// The up and left direction, or -x, -y.
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
UpLeft = Direction2.Up | Direction2.Left,
|
||||
UpLeft = Up | Left,
|
||||
/// <summary>
|
||||
/// The down and left direction, or -x, +y.
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
DownLeft = Direction2.Down | Direction2.Left
|
||||
DownLeft = Down | Left
|
||||
|
||||
}
|
||||
|
||||
|
@ -75,18 +76,18 @@ namespace MLEM.Misc {
|
|||
/// <summary>
|
||||
/// The <see cref="Direction2.Up"/> through <see cref="Direction2.Left"/> directions
|
||||
/// </summary>
|
||||
public static readonly Direction2[] Adjacent = Direction2Helper.All.Where(Direction2Helper.IsAdjacent).ToArray();
|
||||
public static readonly Direction2[] Adjacent = All.Where(IsAdjacent).ToArray();
|
||||
/// <summary>
|
||||
/// The <see cref="Direction2.UpRight"/> through <see cref="Direction2.UpLeft"/> directions
|
||||
/// </summary>
|
||||
public static readonly Direction2[] Diagonals = Direction2Helper.All.Where(Direction2Helper.IsDiagonal).ToArray();
|
||||
public static readonly Direction2[] Diagonals = All.Where(IsDiagonal).ToArray();
|
||||
/// <summary>
|
||||
/// All directions except <see cref="Direction2.None"/>
|
||||
/// </summary>
|
||||
public static readonly Direction2[] AllExceptNone = Direction2Helper.All.Where(dir => dir != Direction2.None).ToArray();
|
||||
public static readonly Direction2[] AllExceptNone = All.Where(dir => dir != None).ToArray();
|
||||
|
||||
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 = Direction2Helper.Clockwise.Select((d, i) => (d, i)).ToDictionary(kv => kv.d, kv => kv.i);
|
||||
private static readonly Direction2[] Clockwise = {Up, UpRight, Right, DownRight, Down, DownLeft, Left, UpLeft};
|
||||
private static readonly Dictionary<Direction2, int> ClockwiseLookup = Clockwise.Select((d, i) => (d, i)).ToDictionary(kv => kv.d, kv => kv.i);
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the given direction is considered an "adjacent" direction.
|
||||
|
@ -95,7 +96,7 @@ namespace MLEM.Misc {
|
|||
/// <param name="dir">The direction to query</param>
|
||||
/// <returns>Whether the direction is adjacent</returns>
|
||||
public static bool IsAdjacent(this Direction2 dir) {
|
||||
return dir == Direction2.Up || dir == Direction2.Right || dir == Direction2.Down || dir == Direction2.Left;
|
||||
return dir == Up || dir == Right || dir == Down || dir == Left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -104,7 +105,7 @@ namespace MLEM.Misc {
|
|||
/// <param name="dir">The direction to query</param>
|
||||
/// <returns>Whether the direction is diagonal</returns>
|
||||
public static bool IsDiagonal(this Direction2 dir) {
|
||||
return dir == Direction2.UpRight || dir == Direction2.DownRight || dir == Direction2.UpLeft || dir == Direction2.DownLeft;
|
||||
return dir == UpRight || dir == DownRight || dir == UpLeft || dir == DownLeft;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -115,21 +116,21 @@ namespace MLEM.Misc {
|
|||
/// <returns>The direction's offset</returns>
|
||||
public static Point Offset(this Direction2 dir) {
|
||||
switch (dir) {
|
||||
case Direction2.Up:
|
||||
case Up:
|
||||
return new Point(0, -1);
|
||||
case Direction2.Right:
|
||||
case Right:
|
||||
return new Point(1, 0);
|
||||
case Direction2.Down:
|
||||
case Down:
|
||||
return new Point(0, 1);
|
||||
case Direction2.Left:
|
||||
case Left:
|
||||
return new Point(-1, 0);
|
||||
case Direction2.UpRight:
|
||||
case UpRight:
|
||||
return new Point(1, -1);
|
||||
case Direction2.DownRight:
|
||||
case DownRight:
|
||||
return new Point(1, 1);
|
||||
case Direction2.DownLeft:
|
||||
case DownLeft:
|
||||
return new Point(-1, 1);
|
||||
case Direction2.UpLeft:
|
||||
case UpLeft:
|
||||
return new Point(-1, -1);
|
||||
default:
|
||||
return Point.Zero;
|
||||
|
@ -155,24 +156,24 @@ namespace MLEM.Misc {
|
|||
/// <returns>The opposite of the direction</returns>
|
||||
public static Direction2 Opposite(this Direction2 dir) {
|
||||
switch (dir) {
|
||||
case Direction2.Up:
|
||||
return Direction2.Down;
|
||||
case Direction2.Right:
|
||||
return Direction2.Left;
|
||||
case Direction2.Down:
|
||||
return Direction2.Up;
|
||||
case Direction2.Left:
|
||||
return Direction2.Right;
|
||||
case Direction2.UpRight:
|
||||
return Direction2.DownLeft;
|
||||
case Direction2.DownRight:
|
||||
return Direction2.UpLeft;
|
||||
case Direction2.DownLeft:
|
||||
return Direction2.UpRight;
|
||||
case Direction2.UpLeft:
|
||||
return Direction2.DownRight;
|
||||
case Up:
|
||||
return Down;
|
||||
case Right:
|
||||
return Left;
|
||||
case Down:
|
||||
return Up;
|
||||
case Left:
|
||||
return Right;
|
||||
case UpRight:
|
||||
return DownLeft;
|
||||
case DownRight:
|
||||
return UpLeft;
|
||||
case DownLeft:
|
||||
return UpRight;
|
||||
case UpLeft:
|
||||
return DownRight;
|
||||
default:
|
||||
return Direction2.None;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,9 +194,9 @@ namespace MLEM.Misc {
|
|||
/// <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>
|
||||
public static Direction2 RotateCw(this Direction2 dir, bool fortyFiveDegrees = false) {
|
||||
if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return Direction2.None;
|
||||
return Direction2Helper.Clockwise[(dirIndex + (fortyFiveDegrees ? 1 : 2)) % Direction2Helper.Clockwise.Length];
|
||||
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return None;
|
||||
return Clockwise[(dirIndex + (fortyFiveDegrees ? 1 : 2)) % Clockwise.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -205,10 +206,10 @@ namespace MLEM.Misc {
|
|||
/// <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>
|
||||
public static Direction2 RotateCcw(this Direction2 dir, bool fortyFiveDegrees = false) {
|
||||
if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return Direction2.None;
|
||||
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return None;
|
||||
var index = dirIndex - (fortyFiveDegrees ? 1 : 2);
|
||||
return Direction2Helper.Clockwise[index < 0 ? index + Direction2Helper.Clockwise.Length : index];
|
||||
return Clockwise[index < 0 ? index + Clockwise.Length : index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -218,11 +219,11 @@ namespace MLEM.Misc {
|
|||
/// <returns>The vector's direction</returns>
|
||||
public static Direction2 ToDirection(this Vector2 offset) {
|
||||
var offsetAngle = (float) Math.Atan2(offset.Y, offset.X);
|
||||
foreach (var dir in Direction2Helper.AllExceptNone) {
|
||||
foreach (var dir in AllExceptNone) {
|
||||
if (Math.Abs(dir.Angle() - offsetAngle) <= MathHelper.PiOver4 / 2)
|
||||
return dir;
|
||||
}
|
||||
return Direction2.None;
|
||||
return None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -233,10 +234,10 @@ namespace MLEM.Misc {
|
|||
/// <returns>The vector's direction</returns>
|
||||
public static Direction2 To90Direction(this Vector2 offset) {
|
||||
if (offset.X == 0 && offset.Y == 0)
|
||||
return Direction2.None;
|
||||
return None;
|
||||
if (Math.Abs(offset.X) > Math.Abs(offset.Y))
|
||||
return offset.X > 0 ? Direction2.Right : Direction2.Left;
|
||||
return offset.Y > 0 ? Direction2.Down : Direction2.Up;
|
||||
return offset.X > 0 ? Right : Left;
|
||||
return offset.Y > 0 ? Down : Up;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -246,17 +247,17 @@ namespace MLEM.Misc {
|
|||
/// <param name="reference">The direction to rotate by</param>
|
||||
/// <param name="start">The direction to use as the default direction</param>
|
||||
/// <returns>The direction, rotated by the reference direction</returns>
|
||||
public static Direction2 RotateBy(this Direction2 dir, Direction2 reference, Direction2 start = Direction2.Up) {
|
||||
if (!Direction2Helper.ClockwiseLookup.TryGetValue(reference, out var refIndex))
|
||||
return Direction2.None;
|
||||
if (!Direction2Helper.ClockwiseLookup.TryGetValue(start, out var startIndex))
|
||||
return Direction2.None;
|
||||
if (!Direction2Helper.ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return Direction2.None;
|
||||
public static Direction2 RotateBy(this Direction2 dir, Direction2 reference, Direction2 start = Up) {
|
||||
if (!ClockwiseLookup.TryGetValue(reference, out var refIndex))
|
||||
return None;
|
||||
if (!ClockwiseLookup.TryGetValue(start, out var startIndex))
|
||||
return None;
|
||||
if (!ClockwiseLookup.TryGetValue(dir, out var dirIndex))
|
||||
return None;
|
||||
var diff = refIndex - startIndex;
|
||||
if (diff < 0)
|
||||
diff += Direction2Helper.Clockwise.Length;
|
||||
return Direction2Helper.Clockwise[(dirIndex + diff) % Direction2Helper.Clockwise.Length];
|
||||
diff += Clockwise.Length;
|
||||
return Clockwise[(dirIndex + diff) % 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;
|
||||
|
||||
/// <summary>https://easings.net/#easeInBounce</summary>
|
||||
public static readonly Easing InBounce = p => 1 - Easings.OutBounce(1 - p);
|
||||
public static readonly Easing InBounce = p => 1 - OutBounce(1 - p);
|
||||
/// <summary>https://easings.net/#easeOutBounce</summary>
|
||||
public static readonly Easing OutBounce = p => {
|
||||
const float n1 = 7.5625F;
|
||||
|
@ -88,7 +88,7 @@ namespace MLEM.Misc {
|
|||
}
|
||||
};
|
||||
/// <summary>https://easings.net/#easeInOutBounce</summary>
|
||||
public static readonly Easing InOutBounce = p => p < 0.5 ? (1 - Easings.OutBounce(1 - 2 * p)) / 2 : (1 + Easings.OutBounce(2 * p - 1)) / 2;
|
||||
public static readonly Easing InOutBounce = p => p < 0.5 ? (1 - OutBounce(1 - 2 * p)) / 2 : (1 + OutBounce(2 * p - 1)) / 2;
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// All values of the <see cref="Buttons"/> enum.
|
||||
/// </summary>
|
||||
public static readonly Buttons[] Buttons = EnumHelper.GetValues<Buttons>().ToArray();
|
||||
public static readonly Buttons[] Buttons = GetValues<Buttons>().ToArray();
|
||||
/// <summary>
|
||||
/// All values of the <see cref="Keys"/> enum.
|
||||
/// </summary>
|
||||
public static readonly Keys[] Keys = EnumHelper.GetValues<Keys>().ToArray();
|
||||
public static readonly Keys[] Keys = GetValues<Keys>().ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the values of the given enum type.
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace MLEM.Misc {
|
|||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">If <see cref="Current"/> is null</exception>
|
||||
public static void EnsureExists() {
|
||||
if (MlemPlatform.Current == null)
|
||||
if (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");
|
||||
}
|
||||
|
||||
|
|
|
@ -135,9 +135,9 @@ namespace MLEM.Misc {
|
|||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||
public override int GetHashCode() {
|
||||
var hashCode = this.Left.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.Right.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.Top.GetHashCode();
|
||||
hashCode = hashCode * 397 ^ this.Bottom.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ this.Right.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ this.Top.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ this.Bottom.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ namespace MLEM.Misc {
|
|||
var num2 = Math.Min(value1.Y + value1.Height, value2.Y + value2.Height);
|
||||
return new RectangleF(x, y, num1 - x, num2 - y);
|
||||
} else {
|
||||
return RectangleF.Empty;
|
||||
return Empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace MLEM.Pathfinding {
|
|||
/// <summary>
|
||||
/// A value that represents an infinite path cost, or a cost for a location that cannot possibly be reached.
|
||||
/// </summary>
|
||||
[Obsolete("This field is deprecated. Use float.PositiveInfinity or float.MaxValue instead.")]
|
||||
public const float InfiniteCost = float.PositiveInfinity;
|
||||
/// <summary>
|
||||
/// The array of all directions that will be checked for path finding.
|
||||
|
@ -111,7 +110,7 @@ namespace MLEM.Pathfinding {
|
|||
closed.Add(current.Pos, current);
|
||||
|
||||
if (current.Pos.Equals(goal)) {
|
||||
ret = AStar<T>.CompilePath(current);
|
||||
ret = CompilePath(current);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -168,7 +167,7 @@ namespace MLEM.Pathfinding {
|
|||
/// <summary>
|
||||
/// 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 be unreachable, <see cref="float.PositiveInfinity"/> or <see cref="float.MaxValue"/> should be returned.
|
||||
/// If a path point should be unreachable, <see cref="AStar{T}.InfiniteCost"/> should be returned.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
|
@ -219,7 +218,7 @@ namespace MLEM.Pathfinding {
|
|||
/// <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>
|
||||
public bool Equals(PathPoint<T> other) {
|
||||
return object.ReferenceEquals(this, other) || EqualityComparer<T>.Default.Equals(this.Pos, other.Pos);
|
||||
return ReferenceEquals(this, other) || EqualityComparer<T>.Default.Equals(this.Pos, other.Pos);
|
||||
}
|
||||
|
||||
/// <summary>Indicates whether this instance and a specified object are equal.</summary>
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace MLEM.Pathfinding {
|
|||
|
||||
/// <inheritdoc />
|
||||
public AStar2(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) :
|
||||
base(AStar2.AllDirs, AStar2.AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
|
||||
base(AllDirs, AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Point AddPositions(Point first, Point second) {
|
||||
|
|
|
@ -30,12 +30,12 @@ namespace MLEM.Pathfinding {
|
|||
}
|
||||
}
|
||||
}
|
||||
AStar3.AllDirs = dirs.ToArray();
|
||||
AllDirs = dirs.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public AStar3(GetCost defaultCostFunction, bool defaultAllowDiagonals, float defaultCost = 1, int defaultMaxTries = 10000) :
|
||||
base(AStar3.AllDirs, AStar3.AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
|
||||
base(AllDirs, AdjacentDirs, defaultCostFunction, defaultAllowDiagonals, defaultCost, defaultMaxTries) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Vector3 AddPositions(Vector3 first, Vector3 second) {
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace MLEM.Sound {
|
|||
public float GetRandomPitch() {
|
||||
if (this.RandomPitchModifier == 0)
|
||||
return this.Pitch;
|
||||
return this.Pitch + ((float) SoundEffectInfo.Random.NextDouble() * 2 - 1) * this.RandomPitchModifier;
|
||||
return this.Pitch + ((float) Random.NextDouble() * 2 - 1) * this.RandomPitchModifier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
|||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>Cadman_Roman.otf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>Cadman_Roman.otf</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>32</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<DefaultCharacter>*</DefaultCharacter>
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>ɏ</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace Sandbox {
|
|||
|
||||
this.Components.Add(this.rawContent = new RawContentManager(this.Services));
|
||||
|
||||
this.map = MlemGame.LoadContent<TiledMap>("Tiled/Map");
|
||||
this.map = LoadContent<TiledMap>("Tiled/Map");
|
||||
this.mapRenderer = new IndividualTiledMapRenderer(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 GenericBitmapFont(LoadContent<BitmapFont>("Fonts/Regular"));
|
||||
var font = new GenericStashFont(system.GetFont(32));
|
||||
var spriteFont = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/TestFont"));
|
||||
var spriteFont = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"));
|
||||
this.UiSystem.Style = new UntexturedStyle(this.SpriteBatch) {
|
||||
Font = font,
|
||||
TextScale = 0.5F,
|
||||
|
@ -277,7 +277,7 @@ namespace Sandbox {
|
|||
|
||||
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.";
|
||||
if (MlemGame.Input.IsKeyPressed(Keys.I)) {
|
||||
if (Input.IsKeyPressed(Keys.I)) {
|
||||
index++;
|
||||
if (index == 1) {
|
||||
scale = 2;
|
||||
|
@ -295,7 +295,7 @@ namespace Sandbox {
|
|||
}
|
||||
|
||||
this.SpriteBatch.Begin();
|
||||
if (MlemGame.Input.IsKeyDown(Keys.LeftShift)) {
|
||||
if (Input.IsKeyDown(Keys.LeftShift)) {
|
||||
this.SpriteBatch.DrawString(regularFont, testString, pos, Color.Red, rotation, origin, scale, effects, 0);
|
||||
} else {
|
||||
genericFont.DrawString(this.SpriteBatch, testString, pos, Color.Green, rotation, origin, scale, effects, 0);
|
||||
|
@ -363,8 +363,8 @@ namespace Sandbox {
|
|||
|
||||
/*if (Input.InputsDown.Length > 0)
|
||||
Console.WriteLine("Down: " + string.Join(", ", Input.InputsDown));*/
|
||||
if (MlemGame.Input.InputsPressed.Length > 0)
|
||||
Console.WriteLine("Pressed: " + string.Join(", ", MlemGame.Input.InputsPressed));
|
||||
if (Input.InputsPressed.Length > 0)
|
||||
Console.WriteLine("Pressed: " + string.Join(", ", Input.InputsPressed));
|
||||
}
|
||||
|
||||
protected override void DoDraw(GameTime gameTime) {
|
||||
|
|
|
@ -7,6 +7,7 @@ using MLEM.Data.Json;
|
|||
using MLEM.Misc;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using static MLEM.Data.DynamicEnum;
|
||||
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||
|
||||
namespace Tests {
|
||||
|
@ -40,27 +41,27 @@ namespace Tests {
|
|||
public void TestDynamicEnum() {
|
||||
var flags = new TestEnum[100];
|
||||
for (var i = 0; i < flags.Length; i++)
|
||||
flags[i] = DynamicEnum.AddFlag<TestEnum>("Flag" + i);
|
||||
flags[i] = AddFlag<TestEnum>("Flag" + i);
|
||||
|
||||
Assert.AreEqual(DynamicEnum.GetValue(flags[7]), BigInteger.One << 7);
|
||||
Assert.AreEqual(DynamicEnum.GetEnumValue<TestEnum>(BigInteger.One << 75), flags[75]);
|
||||
Assert.AreEqual(GetValue(flags[7]), BigInteger.One << 7);
|
||||
Assert.AreEqual(GetEnumValue<TestEnum>(BigInteger.One << 75), flags[75]);
|
||||
|
||||
Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.Or(flags[2], flags[17])), BigInteger.One << 2 | BigInteger.One << 17);
|
||||
Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.And(flags[2], flags[3])), BigInteger.Zero);
|
||||
Assert.AreEqual(DynamicEnum.And(DynamicEnum.Or(flags[24], flags[52]), DynamicEnum.Or(flags[52], flags[75])), flags[52]);
|
||||
Assert.AreEqual(DynamicEnum.Xor(DynamicEnum.Or(flags[85], flags[73]), flags[73]), flags[85]);
|
||||
Assert.AreEqual(DynamicEnum.Xor(DynamicEnum.Or(flags[85], DynamicEnum.Or(flags[73], flags[12])), flags[73]), DynamicEnum.Or(flags[85], flags[12]));
|
||||
Assert.AreEqual(DynamicEnum.GetValue(DynamicEnum.Neg(flags[74])), ~(BigInteger.One << 74));
|
||||
Assert.AreEqual(GetValue(Or(flags[2], flags[17])), (BigInteger.One << 2) | (BigInteger.One << 17));
|
||||
Assert.AreEqual(GetValue(And(flags[2], flags[3])), BigInteger.Zero);
|
||||
Assert.AreEqual(And(Or(flags[24], flags[52]), Or(flags[52], flags[75])), flags[52]);
|
||||
Assert.AreEqual(Xor(Or(flags[85], flags[73]), flags[73]), flags[85]);
|
||||
Assert.AreEqual(Xor(Or(flags[85], Or(flags[73], flags[12])), flags[73]), Or(flags[85], flags[12]));
|
||||
Assert.AreEqual(GetValue(Neg(flags[74])), ~(BigInteger.One << 74));
|
||||
|
||||
Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasFlag(flags[24]), true);
|
||||
Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasAnyFlag(flags[24]), true);
|
||||
Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasFlag(DynamicEnum.Or(flags[24], flags[26])), false);
|
||||
Assert.AreEqual(DynamicEnum.Or(flags[24], flags[52]).HasAnyFlag(DynamicEnum.Or(flags[24], flags[26])), true);
|
||||
Assert.AreEqual(Or(flags[24], flags[52]).HasFlag(flags[24]), true);
|
||||
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(flags[24]), true);
|
||||
Assert.AreEqual(Or(flags[24], flags[52]).HasFlag(Or(flags[24], flags[26])), false);
|
||||
Assert.AreEqual(Or(flags[24], flags[52]).HasAnyFlag(Or(flags[24], flags[26])), true);
|
||||
|
||||
Assert.AreEqual(DynamicEnum.Parse<TestEnum>("Flag24"), flags[24]);
|
||||
Assert.AreEqual(DynamicEnum.Parse<TestEnum>("Flag24 | Flag43"), DynamicEnum.Or(flags[24], flags[43]));
|
||||
Assert.AreEqual(Parse<TestEnum>("Flag24"), flags[24]);
|
||||
Assert.AreEqual(Parse<TestEnum>("Flag24 | Flag43"), Or(flags[24], flags[43]));
|
||||
Assert.AreEqual(flags[24].ToString(), "Flag24");
|
||||
Assert.AreEqual(DynamicEnum.Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43");
|
||||
Assert.AreEqual(Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -70,14 +71,14 @@ namespace Tests {
|
|||
// normal generic data holder should crush the time span down to a string due to its custom serializer
|
||||
var data = new GenericDataHolder();
|
||||
data.SetData("Time", TimeSpan.FromMinutes(5));
|
||||
var read = DataTests.SerializeAndDeserialize(serializer, data);
|
||||
var read = SerializeAndDeserialize(serializer, data);
|
||||
Assert.IsNotInstanceOf<TimeSpan>(read.GetData<object>("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
|
||||
var safeData = new JsonTypeSafeGenericDataHolder();
|
||||
safeData.SetData("Time", TimeSpan.FromMinutes(5));
|
||||
var safeRead = DataTests.SerializeAndDeserialize(serializer, safeData);
|
||||
var safeRead = SerializeAndDeserialize(serializer, safeData);
|
||||
Assert.IsInstanceOf<TimeSpan>(safeRead.GetData<object>("Time"));
|
||||
Assert.DoesNotThrow(() => safeRead.GetData<TimeSpan>("Time"));
|
||||
}
|
||||
|
@ -98,11 +99,11 @@ namespace Tests {
|
|||
public TestObject(Vector2 test, string test2) {}
|
||||
|
||||
protected bool Equals(TestObject other) {
|
||||
return this.Vec.Equals(other.Vec) && this.Point.Equals(other.Point) && object.Equals(this.OtherTest, other.OtherTest) && this.Dir == other.Dir;
|
||||
return this.Vec.Equals(other.Vec) && this.Point.Equals(other.Point) && Equals(this.OtherTest, other.OtherTest) && this.Dir == other.Dir;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) {
|
||||
return object.ReferenceEquals(this, obj) || obj is TestObject other && this.Equals(other);
|
||||
return ReferenceEquals(this, obj) || obj is TestObject other && this.Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
|
|
|
@ -1,57 +1,58 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
using MLEM.Misc;
|
||||
using NUnit.Framework;
|
||||
using static MLEM.Misc.Direction2;
|
||||
|
||||
namespace Tests {
|
||||
public class DirectionTests {
|
||||
|
||||
[Test]
|
||||
public void TestDirections() {
|
||||
Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), Direction2.DownRight);
|
||||
Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), Direction2.DownRight);
|
||||
Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Direction2.Down);
|
||||
Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), DownRight);
|
||||
Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), DownRight);
|
||||
Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Down);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test90Directions() {
|
||||
Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Direction2.Right);
|
||||
Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Direction2.Down);
|
||||
Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Direction2.Down);
|
||||
Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Right);
|
||||
Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Down);
|
||||
Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Down);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRotations() {
|
||||
// rotate cw
|
||||
Assert.AreEqual(Direction2.Up.RotateCw(), Direction2.Right);
|
||||
Assert.AreEqual(Direction2.Up.RotateCw(true), Direction2.UpRight);
|
||||
Assert.AreEqual(Direction2.Left.RotateCw(), Direction2.Up);
|
||||
Assert.AreEqual(Direction2.UpLeft.RotateCw(), Direction2.UpRight);
|
||||
Assert.AreEqual(Up.RotateCw(), Right);
|
||||
Assert.AreEqual(Up.RotateCw(true), UpRight);
|
||||
Assert.AreEqual(Left.RotateCw(), Up);
|
||||
Assert.AreEqual(UpLeft.RotateCw(), UpRight);
|
||||
|
||||
// rotate ccw
|
||||
Assert.AreEqual(Direction2.Up.RotateCcw(), Direction2.Left);
|
||||
Assert.AreEqual(Direction2.Up.RotateCcw(true), Direction2.UpLeft);
|
||||
Assert.AreEqual(Direction2.Left.RotateCcw(), Direction2.Down);
|
||||
Assert.AreEqual(Direction2.UpLeft.RotateCcw(), Direction2.DownLeft);
|
||||
Assert.AreEqual(Up.RotateCcw(), Left);
|
||||
Assert.AreEqual(Up.RotateCcw(true), UpLeft);
|
||||
Assert.AreEqual(Left.RotateCcw(), Down);
|
||||
Assert.AreEqual(UpLeft.RotateCcw(), DownLeft);
|
||||
|
||||
// rotate 360 degrees
|
||||
foreach (var dir in Direction2Helper.AllExceptNone) {
|
||||
Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, false, 4), dir);
|
||||
Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, true, 8), dir);
|
||||
Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, false, 4), dir);
|
||||
Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, true, 8), dir);
|
||||
Assert.AreEqual(RotateMultipleTimes(dir, true, false, 4), dir);
|
||||
Assert.AreEqual(RotateMultipleTimes(dir, true, true, 8), dir);
|
||||
Assert.AreEqual(RotateMultipleTimes(dir, false, false, 4), dir);
|
||||
Assert.AreEqual(RotateMultipleTimes(dir, false, true, 8), dir);
|
||||
}
|
||||
|
||||
// rotate by with start Up
|
||||
Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Right), Direction2.Down);
|
||||
Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Down), Direction2.Left);
|
||||
Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Left), Direction2.Up);
|
||||
Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Up), Direction2.Right);
|
||||
Assert.AreEqual(Right.RotateBy(Right), Down);
|
||||
Assert.AreEqual(Right.RotateBy(Down), Left);
|
||||
Assert.AreEqual(Right.RotateBy(Left), Up);
|
||||
Assert.AreEqual(Right.RotateBy(Up), Right);
|
||||
|
||||
// rotate by with start Left
|
||||
Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Right, Direction2.Left), Direction2.Down);
|
||||
Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Down, Direction2.Left), Direction2.Left);
|
||||
Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Left, Direction2.Left), Direction2.Up);
|
||||
Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Up, Direction2.Left), Direction2.Right);
|
||||
Assert.AreEqual(Up.RotateBy(Right, Left), Down);
|
||||
Assert.AreEqual(Up.RotateBy(Down, Left), Left);
|
||||
Assert.AreEqual(Up.RotateBy(Left, Left), Up);
|
||||
Assert.AreEqual(Up.RotateBy(Up, Left), Right);
|
||||
}
|
||||
|
||||
private static Direction2 RotateMultipleTimes(Direction2 dir, bool clockwise, bool fortyFiveDegrees, int times) {
|
||||
|
|
|
@ -16,12 +16,12 @@ namespace Tests {
|
|||
"XXXX"
|
||||
};
|
||||
|
||||
var noDiagonals = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 2), area, false).ToArray();
|
||||
var noDiagonals = FindPathInArea(new Point(1, 1), new Point(2, 2), area, false).ToArray();
|
||||
Assert.AreEqual(noDiagonals.Length, 3);
|
||||
Assert.AreEqual(noDiagonals[0], new Point(1, 1));
|
||||
Assert.AreEqual(noDiagonals[2], new Point(2, 2));
|
||||
|
||||
var diagonals = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 2), area, true).ToArray();
|
||||
var diagonals = FindPathInArea(new Point(1, 1), new Point(2, 2), area, true).ToArray();
|
||||
Assert.AreEqual(diagonals.Length, 2);
|
||||
Assert.AreEqual(diagonals[0], new Point(1, 1));
|
||||
Assert.AreEqual(diagonals[1], new Point(2, 2));
|
||||
|
@ -36,11 +36,11 @@ namespace Tests {
|
|||
"XXXXXXXX"
|
||||
};
|
||||
|
||||
var firstPath = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(3, 1), area, false).ToArray();
|
||||
var firstPath = 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)};
|
||||
Assert.AreEqual(firstPath, firstExpected);
|
||||
|
||||
var secondPath = PathfindingTests.FindPathInArea(new Point(1, 1), new Point(5, 2), area, false).ToArray();
|
||||
var secondPath = 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();
|
||||
Assert.AreEqual(secondPath, secondExpected);
|
||||
}
|
||||
|
@ -55,15 +55,15 @@ namespace Tests {
|
|||
"XXXX"
|
||||
};
|
||||
// non-diagonal pathfinding should get stuck in the corner
|
||||
Assert.IsNull(PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 3), area, false));
|
||||
Assert.IsNull(FindPathInArea(new Point(1, 1), new Point(2, 3), area, false));
|
||||
// diagonal pathfinding should be able to cross the diagonal gap
|
||||
Assert.IsNotNull(PathfindingTests.FindPathInArea(new Point(1, 1), new Point(2, 3), area, true));
|
||||
Assert.IsNotNull(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) {
|
||||
var costs = area.Select(s => s.Select(c => c switch {
|
||||
' ' => 1,
|
||||
'X' => float.PositiveInfinity,
|
||||
'X' => AStar2.InfiniteCost,
|
||||
_ => (float) char.GetNumericValue(c)
|
||||
}).ToArray()).ToArray();
|
||||
var pathFinder = new AStar2((p1, p2) => costs[p2.Y][p2.X], allowDiagonals);
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Tests {
|
|||
protected override void LoadContent() {
|
||||
base.LoadContent();
|
||||
this.RawContent = new RawContentManager(this.Services, this.Content.RootDirectory);
|
||||
this.UiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("TestFont"));
|
||||
this.UiSystem.Style.Font = new GenericSpriteFont(LoadContent<SpriteFont>("TestFont"));
|
||||
}
|
||||
|
||||
public static TestGame Create() {
|
||||
|
|
|
@ -43,8 +43,8 @@ namespace Tests {
|
|||
[Test]
|
||||
public void TestDisposal() {
|
||||
using var packer = new RuntimeTexturePacker(128, disposeTextures: true);
|
||||
packer.Add(new TextureRegion(this.disposedTestTexture), TexturePackerTests.StubResult);
|
||||
packer.Add(new TextureRegion(this.disposedTestTexture, 0, 0, 8, 8), TexturePackerTests.StubResult);
|
||||
packer.Add(new TextureRegion(this.disposedTestTexture), StubResult);
|
||||
packer.Add(new TextureRegion(this.disposedTestTexture, 0, 0, 8, 8), StubResult);
|
||||
packer.Pack(this.game.GraphicsDevice);
|
||||
Assert.True(this.disposedTestTexture.IsDisposed);
|
||||
Assert.False(packer.PackedTexture.IsDisposed);
|
||||
|
@ -55,26 +55,26 @@ namespace Tests {
|
|||
// test forced max width
|
||||
using var packer = new RuntimeTexturePacker(128);
|
||||
Assert.Throws<InvalidOperationException>(() => {
|
||||
packer.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), TexturePackerTests.StubResult);
|
||||
packer.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), StubResult);
|
||||
});
|
||||
|
||||
// test auto-expanding width
|
||||
using var packer2 = new RuntimeTexturePacker(128, true);
|
||||
Assert.DoesNotThrow(() => {
|
||||
packer2.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), TexturePackerTests.StubResult);
|
||||
packer2.Add(new TextureRegion(this.testTexture, 0, 0, 256, 128), StubResult);
|
||||
});
|
||||
packer2.Pack(this.game.GraphicsDevice);
|
||||
|
||||
// test power of two forcing
|
||||
using var packer3 = new RuntimeTexturePacker(128, forcePowerOfTwo: true);
|
||||
packer3.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), TexturePackerTests.StubResult);
|
||||
packer3.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), StubResult);
|
||||
packer3.Pack(this.game.GraphicsDevice);
|
||||
Assert.AreEqual(64, packer3.PackedTexture.Width);
|
||||
Assert.AreEqual(256, packer3.PackedTexture.Height);
|
||||
|
||||
// test square forcing
|
||||
using var packer4 = new RuntimeTexturePacker(128, forceSquare: true);
|
||||
packer4.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), TexturePackerTests.StubResult);
|
||||
packer4.Add(new TextureRegion(this.testTexture, 0, 0, 37, 170), StubResult);
|
||||
packer4.Pack(this.game.GraphicsDevice);
|
||||
Assert.AreEqual(170, packer4.PackedTexture.Width);
|
||||
Assert.AreEqual(170, packer4.PackedTexture.Height);
|
||||
|
|
Loading…
Reference in a new issue