mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 14:08:34 +01:00
Compare commits
6 commits
aff61508c4
...
334918103f
Author | SHA1 | Date | |
---|---|---|---|
334918103f | |||
42a87471fc | |||
9c370f75e8 | |||
059e26781b | |||
5fcdda80dc | |||
5d7d238630 |
91 changed files with 742 additions and 160 deletions
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[submodule "FNA"]
|
||||||
|
path = FNA
|
||||||
|
url = https://github.com/FNA-XNA/FNA
|
||||||
|
[submodule "FontStashSharp"]
|
||||||
|
path = FontStashSharp
|
||||||
|
url = https://github.com/FontStashSharp/FontStashSharp
|
|
@ -18,6 +18,7 @@ Additions
|
||||||
- Added an Enum constructor to GenericInput
|
- Added an Enum constructor to GenericInput
|
||||||
- Added RandomPitchModifier and GetRandomPitch to SoundEffectInfo
|
- Added RandomPitchModifier and GetRandomPitch to SoundEffectInfo
|
||||||
- Added TextInput class, which is an isolated version of MLEM.Ui's TextField logic
|
- Added TextInput class, which is an isolated version of MLEM.Ui's TextField logic
|
||||||
|
- Added MLEM.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Allow comparing Keybind and Combination based on the amount of modifiers they have
|
- Allow comparing Keybind and Combination based on the amount of modifiers they have
|
||||||
|
@ -31,6 +32,7 @@ Removals
|
||||||
Additions
|
Additions
|
||||||
- Added Element.AutoNavGroup which allows forming groups for auto-navigation
|
- Added Element.AutoNavGroup which allows forming groups for auto-navigation
|
||||||
- Added UiMarkdownParser
|
- Added UiMarkdownParser
|
||||||
|
- Added MLEM.Ui.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Ensure that Element.IsMouseOver is always accurate by making it an auto-property
|
- Ensure that Element.IsMouseOver is always accurate by making it an auto-property
|
||||||
|
@ -59,6 +61,7 @@ Removals
|
||||||
### MLEM.Extended
|
### MLEM.Extended
|
||||||
Additions
|
Additions
|
||||||
- Added LayerPositionF
|
- Added LayerPositionF
|
||||||
|
- Added MLEM.Extended.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Allow using a StaticSpriteBatch to render an IndividualTiledMapRenderer
|
- Allow using a StaticSpriteBatch to render an IndividualTiledMapRenderer
|
||||||
|
@ -67,6 +70,7 @@ Improvements
|
||||||
Additions
|
Additions
|
||||||
- Added the ability to add padding to RuntimeTexturePacker texture regions
|
- Added the ability to add padding to RuntimeTexturePacker texture regions
|
||||||
- Added the ability to pack UniformTextureAtlas and DataTextureAtlas using RuntimeTexturePacker
|
- Added the ability to pack UniformTextureAtlas and DataTextureAtlas using RuntimeTexturePacker
|
||||||
|
- Added MLEM.Data.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
Improvements
|
Improvements
|
||||||
- Premultiply textures when using RawContentManager
|
- Premultiply textures when using RawContentManager
|
||||||
|
@ -77,6 +81,10 @@ Improvements
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed SoundEffectReader incorrectly claiming it could read ogg and mp3 files
|
- Fixed SoundEffectReader incorrectly claiming it could read ogg and mp3 files
|
||||||
|
|
||||||
|
### MLEM.Startup
|
||||||
|
Additions
|
||||||
|
- Added MLEM.Startup.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
## 5.3.0
|
## 5.3.0
|
||||||
### MLEM
|
### MLEM
|
||||||
Additions
|
Additions
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
<PackageReference Include="Coroutine" Version="2.1.3" />
|
<PackageReference Include="Coroutine" Version="2.1.3" />
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
||||||
<PackageReference Include="MonoGame.Framework.Android" Version="3.8.0.1641" />
|
<PackageReference Include="MonoGame.Framework.Android" Version="3.8.0.1641" />
|
||||||
<PackageReference Include="TextCopy" Version="4.3.0" />
|
<PackageReference Include="TextCopy" Version="6.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Demos\Demos.csproj">
|
<ProjectReference Include="..\Demos\Demos.csproj">
|
||||||
|
|
37
Demos.DesktopGL/Demos.DesktopGL.FNA.csproj
Normal file
37
Demos.DesktopGL/Demos.DesktopGL.FNA.csproj
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
<AssemblyName>MLEM Desktop Demos</AssemblyName>
|
||||||
|
<RootNamespace>Demos.DesktopGL</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
<!-- We still use the MG content builder for ease of compatibility between the MG and FNA demo projects -->
|
||||||
|
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Demos\Demos.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
||||||
|
<Content Include="..\Demos\Content\*\**" />
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
<Content Include="FNA/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<Link>%(Filename)%(Extension)</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
BIN
Demos.DesktopGL/FNA/FAudio.dll
Normal file
BIN
Demos.DesktopGL/FNA/FAudio.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/FNA3D.dll
Normal file
BIN
Demos.DesktopGL/FNA/FNA3D.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/SDL2.dll
Normal file
BIN
Demos.DesktopGL/FNA/SDL2.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libFAudio.0.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libFAudio.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libFAudio.so.0
Normal file
BIN
Demos.DesktopGL/FNA/libFAudio.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libFNA3D.0.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libFNA3D.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libFNA3D.so.0
Normal file
BIN
Demos.DesktopGL/FNA/libFNA3D.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libMoltenVK.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libMoltenVK.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libSDL2-2.0.0.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libSDL2-2.0.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libSDL2-2.0.so.0
Normal file
BIN
Demos.DesktopGL/FNA/libSDL2-2.0.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libtheorafile.dll
Normal file
BIN
Demos.DesktopGL/FNA/libtheorafile.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libtheorafile.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libtheorafile.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libtheorafile.so
Normal file
BIN
Demos.DesktopGL/FNA/libtheorafile.so
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FNA/libvulkan.1.dylib
Normal file
BIN
Demos.DesktopGL/FNA/libvulkan.1.dylib
Normal file
Binary file not shown.
|
@ -1,11 +1,17 @@
|
||||||
using Microsoft.Xna.Framework;
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
|
|
||||||
namespace Demos.DesktopGL {
|
namespace Demos.DesktopGL {
|
||||||
public static class Program {
|
public static class Program {
|
||||||
|
|
||||||
public static void Main() {
|
public static void Main() {
|
||||||
|
#if FNA
|
||||||
|
MlemPlatform.Current = new MlemPlatform.DesktopFna(a => TextInputEXT.TextInput += a);
|
||||||
|
#else
|
||||||
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
||||||
|
#endif
|
||||||
using var game = new GameImpl();
|
using var game = new GameImpl();
|
||||||
game.Run();
|
game.Run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace Demos {
|
||||||
public override void DoDraw(GameTime gameTime) {
|
public override void DoDraw(GameTime gameTime) {
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(10));
|
||||||
// draw the group's current region
|
// draw the group's current region
|
||||||
// if not using a group, just draw the animation's CurrentRegion here
|
// if not using a group, just draw the animation's CurrentRegion here
|
||||||
this.SpriteBatch.Draw(this.group.CurrentRegion, new Vector2(10, 10), Color.White);
|
this.SpriteBatch.Draw(this.group.CurrentRegion, new Vector2(10, 10), Color.White);
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Demos {
|
||||||
this.GraphicsDevice.Clear(Color.Black);
|
this.GraphicsDevice.Clear(Color.Black);
|
||||||
|
|
||||||
// drawing the auto tiles
|
// drawing the auto tiles
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(10));
|
||||||
for (var x = 0; x < 6; x++) {
|
for (var x = 0; x < 6; x++) {
|
||||||
for (var y = 0; y < 5; y++) {
|
for (var y = 0; y < 5; y++) {
|
||||||
// don't draw non-grass tiles ( )
|
// don't draw non-grass tiles ( )
|
||||||
|
|
21
Demos/Demos.FNA.csproj
Normal file
21
Demos/Demos.FNA.csproj
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>Demos</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -43,7 +43,7 @@ namespace Demos {
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
base.DoDraw(time);
|
base.DoDraw(time);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp);
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
|
||||||
var view = this.GraphicsDevice.Viewport;
|
var view = this.GraphicsDevice.Viewport;
|
||||||
|
|
||||||
// graph the easing function
|
// graph the easing function
|
||||||
|
|
|
@ -9,7 +9,9 @@ using MLEM.Textures;
|
||||||
using MLEM.Ui;
|
using MLEM.Ui;
|
||||||
using MLEM.Ui.Elements;
|
using MLEM.Ui.Elements;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
#if !FNA
|
||||||
using MonoGame.Framework.Utilities;
|
using MonoGame.Framework.Utilities;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Demos {
|
namespace Demos {
|
||||||
public class GameImpl : MlemGame {
|
public class GameImpl : MlemGame {
|
||||||
|
@ -47,11 +49,13 @@ namespace Demos {
|
||||||
|
|
||||||
protected override void LoadContent() {
|
protected override void LoadContent() {
|
||||||
// TODO remove with MonoGame 3.8.1 https://github.com/MonoGame/MonoGame/issues/7298
|
// TODO remove with MonoGame 3.8.1 https://github.com/MonoGame/MonoGame/issues/7298
|
||||||
|
#if !FNA
|
||||||
if (PlatformInfo.MonoGamePlatform == MonoGamePlatform.DesktopGL) {
|
if (PlatformInfo.MonoGamePlatform == MonoGamePlatform.DesktopGL) {
|
||||||
this.GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
|
this.GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
|
||||||
this.GraphicsDeviceManager.PreferredBackBufferHeight = 720;
|
this.GraphicsDeviceManager.PreferredBackBufferHeight = 720;
|
||||||
this.GraphicsDeviceManager.ApplyChanges();
|
this.GraphicsDeviceManager.ApplyChanges();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
base.LoadContent();
|
base.LoadContent();
|
||||||
this.UiSystem.AutoScaleReferenceSize = new Point(1280, 720);
|
this.UiSystem.AutoScaleReferenceSize = new Point(1280, 720);
|
||||||
|
|
|
@ -35,9 +35,9 @@ namespace Demos {
|
||||||
|
|
||||||
// Create a cost function, which determines how expensive (or difficult) it should be to move from a given position
|
// Create a cost function, which determines how expensive (or difficult) it should be to move from a given position
|
||||||
// to the next, adjacent position. In our case, the only restriction should be walls and out-of-bounds positions, which
|
// to the next, adjacent position. In our case, the only restriction should be walls and out-of-bounds positions, which
|
||||||
// both have a cost of AStar2.InfiniteCost, meaning they are completely unwalkable.
|
// both have a cost of AStar2.InfiniteCost, meaning they are completely unwalkable.
|
||||||
// If your game contains harder-to-move-on areas like, say, a muddy pit, you can return a higher cost value for those
|
// If your game contains harder-to-move-on areas like, say, a muddy pit, you can return a higher cost value for those
|
||||||
// locations. If you want to scale your cost function differently, you can specify a different default cost in your
|
// locations. If you want to scale your cost function differently, you can specify a different default cost in your
|
||||||
// pathfinder's constructor
|
// pathfinder's constructor
|
||||||
float Cost(Point pos, Point nextPos) {
|
float Cost(Point pos, Point nextPos) {
|
||||||
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
|
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
|
||||||
|
@ -73,7 +73,7 @@ namespace Demos {
|
||||||
public override void DoDraw(GameTime gameTime) {
|
public override void DoDraw(GameTime gameTime) {
|
||||||
this.GraphicsDevice.Clear(Color.White);
|
this.GraphicsDevice.Clear(Color.White);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(14));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(14));
|
||||||
var tex = this.SpriteBatch.GetBlankTexture();
|
var tex = this.SpriteBatch.GetBlankTexture();
|
||||||
// draw the world with simple shapes
|
// draw the world with simple shapes
|
||||||
for (var x = 0; x < 50; x++) {
|
for (var x = 0; x < 50; x++) {
|
||||||
|
@ -87,9 +87,9 @@ namespace Demos {
|
||||||
// in a real game, you'd obviously make your characters walk along the path instead of drawing it
|
// in a real game, you'd obviously make your characters walk along the path instead of drawing it
|
||||||
if (this.path != null) {
|
if (this.path != null) {
|
||||||
for (var i = 1; i < this.path.Count; i++) {
|
for (var i = 1; i < this.path.Count; i++) {
|
||||||
var (firstX, firstY) = this.path[i - 1];
|
var first = this.path[i - 1];
|
||||||
var (secondX, secondY) = this.path[i];
|
var second = this.path[i];
|
||||||
this.SpriteBatch.Draw(tex, RectangleF.FromCorners(new Vector2(firstX + 0.25F, firstY + 0.25F), new Vector2(secondX + 0.75F, secondY + 0.75F)), Color.Blue);
|
this.SpriteBatch.Draw(tex, RectangleF.FromCorners(new Vector2(first.X + 0.25F, first.Y + 0.25F), new Vector2(second.X + 0.75F, second.Y + 0.75F)), Color.Blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.SpriteBatch.End();
|
this.SpriteBatch.End();
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Demos {
|
||||||
|
|
||||||
public override void DoDraw(GameTime time) {
|
public override void DoDraw(GameTime time) {
|
||||||
this.GraphicsDevice.Clear(Color.DarkSlateGray);
|
this.GraphicsDevice.Clear(Color.DarkSlateGray);
|
||||||
this.SpriteBatch.Begin(samplerState: SamplerState.PointClamp);
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
|
||||||
|
|
||||||
// we draw the tokenized text in the center of the screen
|
// we draw the tokenized text in the center of the screen
|
||||||
// since the text is already center-aligned, we only need to align it on the y axis here
|
// since the text is already center-aligned, we only need to align it on the y axis here
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace Demos {
|
||||||
// add the root to the demos' ui
|
// add the root to the demos' ui
|
||||||
this.UiRoot.AddChild(this.root);
|
this.UiRoot.AddChild(this.root);
|
||||||
|
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame."));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame and FNA."));
|
||||||
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
|
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
|
||||||
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
||||||
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Banner.png)
|
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Banner.png)
|
||||||
|
|
||||||
**MLEM Library for Extending MonoGame** is an addition to the game framework [MonoGame](https://www.monogame.net/) that provides extension methods, quality of life improvements and additional features like a ui system and easy input handling.
|
**MLEM Library for Extending MonoGame and FNA** is an addition to the game frameworks [MonoGame](https://www.monogame.net/) and [FNA](https://fna-xna.github.io/) that provides extension methods, quality of life improvements and additional features like a ui system and easy input handling.
|
||||||
|
|
||||||
# What next?
|
# What next?
|
||||||
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
||||||
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de)
|
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de/?q=mlem)
|
||||||
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
||||||
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
||||||
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/release/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/release/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/release/Demos.Android)
|
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/release/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/release/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/release/Demos.Android)
|
||||||
|
|
1
FNA
Submodule
1
FNA
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit e27bfb5a34112461a6bff960888c0cce2b0c5be2
|
1
FontStashSharp
Submodule
1
FontStashSharp
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 460a60ca817e10b6c9bae3e3c05affd1b0bb4ba7
|
5
Jenkinsfile
vendored
5
Jenkinsfile
vendored
|
@ -1,6 +1,11 @@
|
||||||
pipeline {
|
pipeline {
|
||||||
agent any
|
agent any
|
||||||
stages {
|
stages {
|
||||||
|
stage('Submodules') {
|
||||||
|
steps {
|
||||||
|
sh 'git submodule update --init --recursive --force'
|
||||||
|
}
|
||||||
|
}
|
||||||
stage('Cake Build') {
|
stage('Cake Build') {
|
||||||
steps {
|
steps {
|
||||||
sh 'dotnet tool restore'
|
sh 'dotnet tool restore'
|
||||||
|
|
|
@ -7,19 +7,22 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace MLEM.Data.Content {
|
namespace MLEM.Data.Content {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a version of <see cref="ContentManager"/> that doesn't load content binary <c>xnb</c> files, but rather as their regular formats.
|
/// Represents a version of <see cref="ContentManager"/> that doesn't load content binary <c>xnb</c> files, but rather as their regular formats.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RawContentManager : ContentManager, IGameComponent {
|
public class RawContentManager : ContentManager, IGameComponent {
|
||||||
|
|
||||||
private static List<RawContentReader> readers;
|
private static List<RawContentReader> readers;
|
||||||
|
|
||||||
private readonly List<IDisposable> disposableAssets = new List<IDisposable>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The graphics device that this content manager uses
|
/// The graphics device that this content manager uses
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly GraphicsDevice GraphicsDevice;
|
public readonly GraphicsDevice GraphicsDevice;
|
||||||
|
|
||||||
|
private readonly List<IDisposable> disposableAssets = new List<IDisposable>();
|
||||||
|
#if FNA
|
||||||
|
private Dictionary<string, object> LoadedAssets { get; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new content manager with an optionally specified root directory.
|
/// Creates a new content manager with an optionally specified root directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -50,7 +53,11 @@ namespace MLEM.Data.Content {
|
||||||
/// <param name="originalAssetName">The original name of the asset.</param>
|
/// <param name="originalAssetName">The original name of the asset.</param>
|
||||||
/// <param name="currentAsset">The current asset instance.</param>
|
/// <param name="currentAsset">The current asset instance.</param>
|
||||||
/// <typeparam name="T">The asset's type.</typeparam>
|
/// <typeparam name="T">The asset's type.</typeparam>
|
||||||
protected override void ReloadAsset<T>(string originalAssetName, T currentAsset) {
|
protected
|
||||||
|
#if !FNA
|
||||||
|
override
|
||||||
|
#endif
|
||||||
|
void ReloadAsset<T>(string originalAssetName, T currentAsset) {
|
||||||
this.Read(originalAssetName, currentAsset);
|
this.Read(originalAssetName, currentAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,13 @@ namespace MLEM.Data.Content {
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) {
|
protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) {
|
||||||
|
#if !FNA
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
existing.Reload(stream);
|
existing.Reload(stream);
|
||||||
return existing;
|
return existing;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
// premultiply the texture's color to be in line with the pipeline's texture reader
|
// premultiply the texture's color to be in line with the pipeline's texture reader
|
||||||
// TODO this can be converted to use https://github.com/MonoGame/MonoGame/pull/7369 in the future
|
// TODO this can be converted to use https://github.com/MonoGame/MonoGame/pull/7369 in the future
|
||||||
using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream)) {
|
using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream)) {
|
||||||
|
|
|
@ -5,12 +5,13 @@ using System.Text.RegularExpressions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Content;
|
using Microsoft.Xna.Framework.Content;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// This class represents an atlas of <see cref="TextureRegion"/> objects which are loaded from a special texture atlas file.
|
/// This class represents an atlas of <see cref="TextureRegion"/> objects which are loaded from a special texture atlas file.
|
||||||
/// To load a data texture atlas, you can use <see cref="DataTextureAtlasExtensions.LoadTextureAtlas"/>.
|
/// To load a data texture atlas, you can use <see cref="DataTextureAtlasExtensions.LoadTextureAtlas"/>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
|
@ -95,7 +96,7 @@ namespace MLEM.Data {
|
||||||
var loc = new Rectangle(
|
var loc = new Rectangle(
|
||||||
int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value),
|
int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value),
|
||||||
int.Parse(match.Groups[4].Value), int.Parse(match.Groups[5].Value));
|
int.Parse(match.Groups[4].Value), int.Parse(match.Groups[5].Value));
|
||||||
loc.Offset(off);
|
loc.Offset(off.ToPoint());
|
||||||
|
|
||||||
// pivot
|
// pivot
|
||||||
var piv = !match.Groups[6].Success ? Vector2.Zero : off + new Vector2(
|
var piv = !match.Groups[6].Success ? Vector2.Zero : off + new Vector2(
|
||||||
|
|
45
MLEM.Data/MLEM.Data.FNA.csproj
Normal file
45
MLEM.Data/MLEM.Data.FNA.csproj
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Data</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>Simple loading and processing of textures and other data for FNA, including the ability to load non-XNB content files easily</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions data serialize</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
||||||
|
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -3,8 +3,9 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Ellpeck</Authors>
|
<Authors>Ellpeck</Authors>
|
||||||
<Description>Simple loading and processing of textures and other data for MonoGame, including the ability to load non-XNB content files easily</Description>
|
<Description>Simple loading and processing of textures and other data for MonoGame, including the ability to load non-XNB content files easily</Description>
|
||||||
|
@ -15,12 +16,11 @@
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Logo.png</PackageIcon>
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<NoWarn>NU1701</NoWarn>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
||||||
|
|
||||||
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
||||||
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
@ -35,9 +35,9 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -170,7 +170,7 @@ namespace MLEM.Data {
|
||||||
foreach (var request in this.texturesToPack.OrderByDescending(t => t.Texture.Width * t.Texture.Height)) {
|
foreach (var request in this.texturesToPack.OrderByDescending(t => t.Texture.Width * t.Texture.Height)) {
|
||||||
request.PackedArea = this.FindFreeArea(request);
|
request.PackedArea = this.FindFreeArea(request);
|
||||||
// if this is the first position that this request fit in, no other requests of the same size will find a position before it
|
// if this is the first position that this request fit in, no other requests of the same size will find a position before it
|
||||||
this.firstPossiblePosForSizeCache[request.PackedArea.Size] = request.PackedArea.Location;
|
this.firstPossiblePosForSizeCache[new Point(request.PackedArea.Width, request.PackedArea.Height)] = request.PackedArea.Location;
|
||||||
this.alreadyPackedTextures.Add(request);
|
this.alreadyPackedTextures.Add(request);
|
||||||
}
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
@ -198,7 +198,7 @@ namespace MLEM.Data {
|
||||||
|
|
||||||
// invoke callbacks
|
// invoke callbacks
|
||||||
foreach (var request in this.alreadyPackedTextures) {
|
foreach (var request in this.alreadyPackedTextures) {
|
||||||
var packedArea = request.PackedArea.Shrink(new Point(request.Padding));
|
var packedArea = request.PackedArea.Shrink(new Point(request.Padding, request.Padding));
|
||||||
request.Result.Invoke(new TextureRegion(this.PackedTexture, packedArea));
|
request.Result.Invoke(new TextureRegion(this.PackedTexture, packedArea));
|
||||||
if (this.disposeTextures)
|
if (this.disposeTextures)
|
||||||
request.Texture.Texture.Dispose();
|
request.Texture.Texture.Dispose();
|
||||||
|
@ -232,7 +232,7 @@ namespace MLEM.Data {
|
||||||
var lowestY = int.MaxValue;
|
var lowestY = int.MaxValue;
|
||||||
while (true) {
|
while (true) {
|
||||||
var intersected = false;
|
var intersected = false;
|
||||||
var area = new Rectangle(pos, size);
|
var area = new Rectangle(pos.X, pos.Y, size.X, size.Y);
|
||||||
foreach (var tex in this.alreadyPackedTextures) {
|
foreach (var tex in this.alreadyPackedTextures) {
|
||||||
if (tex.PackedArea.Intersects(area)) {
|
if (tex.PackedArea.Intersects(area)) {
|
||||||
pos.X = tex.PackedArea.Right;
|
pos.X = tex.PackedArea.Right;
|
||||||
|
@ -255,7 +255,7 @@ namespace MLEM.Data {
|
||||||
|
|
||||||
private void CopyRegion(TextureData destination, Request request) {
|
private void CopyRegion(TextureData destination, Request request) {
|
||||||
var data = this.GetCachedTextureData(request.Texture.Texture);
|
var data = this.GetCachedTextureData(request.Texture.Texture);
|
||||||
var location = request.PackedArea.Location + new Point(request.Padding);
|
var location = request.PackedArea.Location + new Point(request.Padding, request.Padding);
|
||||||
for (var x = -request.Padding; x < request.Texture.Width + request.Padding; x++) {
|
for (var x = -request.Padding; x < request.Texture.Width + request.Padding; x++) {
|
||||||
for (var y = -request.Padding; y < request.Texture.Height + request.Padding; y++) {
|
for (var y = -request.Padding; y < request.Texture.Height + request.Padding; y++) {
|
||||||
Color srcColor;
|
Color srcColor;
|
||||||
|
@ -264,7 +264,7 @@ namespace MLEM.Data {
|
||||||
srcColor = Color.Transparent;
|
srcColor = Color.Transparent;
|
||||||
} else {
|
} else {
|
||||||
// otherwise, we just use the closest pixel that is actually in bounds, causing the border pixels to be doubled up
|
// otherwise, we just use the closest pixel that is actually in bounds, causing the border pixels to be doubled up
|
||||||
var src = new Point(MathHelper.Clamp(x, 0, request.Texture.Width - 1), MathHelper.Clamp(y, 0, request.Texture.Height - 1));
|
var src = new Point((int) MathHelper.Clamp(x, 0, request.Texture.Width - 1), (int) MathHelper.Clamp(y, 0, request.Texture.Height - 1));
|
||||||
srcColor = data[request.Texture.Position + src];
|
srcColor = data[request.Texture.Position + src];
|
||||||
}
|
}
|
||||||
destination[location + new Point(x, y)] = srcColor;
|
destination[location + new Point(x, y)] = srcColor;
|
||||||
|
|
41
MLEM.Extended/MLEM.Extended.FNA.csproj
Normal file
41
MLEM.Extended/MLEM.Extended.FNA.csproj
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Extended</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>MLEM Library for Extending FNA extension that ties in with other FNA libraries</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions extended</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\FontStashSharp\src\XNA\FontStashSharp.FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
|
||||||
|
<Compile Remove="Tiled/**" />
|
||||||
|
<Compile Remove="Extensions/**" />
|
||||||
|
<Compile Remove="Font/GenericBitmapFont.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -26,7 +26,7 @@
|
||||||
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0">
|
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="FontStashSharp.MonoGame" Version="1.0.4">
|
<PackageReference Include="FontStashSharp.MonoGame" Version="1.1.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
||||||
|
|
70
MLEM.FNA.sln
Normal file
70
MLEM.FNA.sln
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.FNA", "MLEM\MLEM.FNA.csproj", "{C2C88AE6-6274-4395-8B03-52AE898BA070}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Ui.FNA", "MLEM.Ui\MLEM.Ui.FNA.csproj", "{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Startup.FNA", "MLEM.Startup\MLEM.Startup.FNA.csproj", "{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Data.FNA", "MLEM.Data\MLEM.Data.FNA.csproj", "{6587BC91-0640-43FB-988A-4F545B8ACFC5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos.FNA", "Demos\Demos.FNA.csproj", "{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos.DesktopGL.FNA", "Demos.DesktopGL\Demos.DesktopGL.FNA.csproj", "{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.FNA", "Tests\Tests.FNA.csproj", "{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Extended.FNA", "MLEM.Extended\MLEM.Extended.FNA.csproj", "{A5B22930-DF4B-4A62-93ED-A6549F7B666B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA.Core", "FNA\FNA.Core.csproj", "{06459F72-CEAA-4B45-B2B1-708FC28D04F8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FontStashSharp.FNA.Core", "FontStashSharp\src\XNA\FontStashSharp.FNA.Core.csproj", "{0B410591-3AED-4C82-A07A-516FF493709B}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
37
MLEM.Startup/MLEM.Startup.FNA.csproj
Normal file
37
MLEM.Startup/MLEM.Startup.FNA.csproj
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Startup</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>MLEM Library for Extending FNA combined with some other useful libraries into a quick Game startup class</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Coroutine" Version="2.1.3" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -69,7 +69,9 @@ namespace MLEM.Startup {
|
||||||
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
|
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
|
||||||
PreferredBackBufferWidth = windowWidth,
|
PreferredBackBufferWidth = windowWidth,
|
||||||
PreferredBackBufferHeight = windowHeight,
|
PreferredBackBufferHeight = windowHeight,
|
||||||
|
#if !FNA
|
||||||
HardwareModeSwitch = false
|
HardwareModeSwitch = false
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
this.Window.AllowUserResizing = true;
|
this.Window.AllowUserResizing = true;
|
||||||
this.Content.RootDirectory = "Content";
|
this.Content.RootDirectory = "Content";
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of this element, where X represents the width and Y represents the height.
|
/// The size of this element, where X represents the width and Y represents the height.
|
||||||
/// If the x or y value of the size is between 0 and 1, the size will be seen as a percentage of its parent's size rather than as an absolute value.
|
/// If the x or y value of the size is between 0 and 1, the size will be seen as a percentage of its parent's size rather than as an absolute value.
|
||||||
/// If the x (or y) value of the size is negative, the width (or height) is seen as a percentage of the element's resulting height (or width).
|
/// If the x (or y) value of the size is negative, the width (or height) is seen as a percentage of the element's resulting height (or width).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// The following example combines both types of percentage-based sizing.
|
/// The following example combines both types of percentage-based sizing.
|
||||||
|
@ -178,12 +178,12 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This element's transform matrix.
|
/// This element's transform matrix.
|
||||||
/// Can easily be scaled using <see cref="ScaleTransform"/>.
|
/// Can easily be scaled using <see cref="ScaleTransform"/>.
|
||||||
/// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element.
|
/// Note that, when this is non-null, a new <c>SpriteBatch.Begin</c> call is used for this element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Matrix Transform = Matrix.Identity;
|
public Matrix Transform = Matrix.Identity;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The call that this element should make to <see cref="SpriteBatch"/> to begin drawing.
|
/// The call that this element should make to <see cref="SpriteBatch"/> to begin drawing.
|
||||||
/// Note that, when this is non-null, a new <see cref="SpriteBatch.Begin"/> call is used for this element.
|
/// Note that, when this is non-null, a new <c>SpriteBatch.Begin</c> call is used for this element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618
|
||||||
[Obsolete("BeginImpl is deprecated. You can create a custom element class and override Draw instead.")]
|
[Obsolete("BeginImpl is deprecated. You can create a custom element class and override Draw instead.")]
|
||||||
|
@ -927,7 +927,7 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
|
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
|
||||||
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <see cref="SpriteBatch.Begin"/> call is also started.
|
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <c>SpriteBatch.Begin</c> call is also started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
@ -944,7 +944,7 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
|
/// Draws this element by calling <see cref="Draw(Microsoft.Xna.Framework.GameTime,Microsoft.Xna.Framework.Graphics.SpriteBatch,float,MLEM.Graphics.SpriteBatchContext)"/> internally.
|
||||||
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <see cref="SpriteBatch.Begin"/> call is also started.
|
/// If <see cref="Transform"/> or <see cref="BeginImpl"/> is set, a new <c>SpriteBatch.Begin</c> call is also started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
@ -981,7 +981,7 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
|
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
|
||||||
/// Note that, when this is called, <see cref="SpriteBatch.Begin"/> has already been called with custom <see cref="Transform"/> etc. applied.
|
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has already been called with custom <see cref="Transform"/> etc. applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
@ -998,7 +998,7 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
|
/// Draws this element and all of its children. Override this method to draw the content of custom elements.
|
||||||
/// Note that, when this is called, <see cref="SpriteBatch.Begin"/> has already been called with custom <see cref="Transform"/> etc. applied.
|
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has already been called with custom <see cref="Transform"/> etc. applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
@ -1021,7 +1021,7 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws this element and all of its <see cref="GetRelevantChildren"/> early.
|
/// Draws this element and all of its <see cref="GetRelevantChildren"/> early.
|
||||||
/// Drawing early involves drawing onto <see cref="RenderTarget2D"/> instances rather than onto the screen.
|
/// Drawing early involves drawing onto <see cref="RenderTarget2D"/> instances rather than onto the screen.
|
||||||
/// Note that, when this is called, <see cref="SpriteBatch.Begin"/> has not yet been called.
|
/// Note that, when this is called, <c>SpriteBatch.Begin</c> has not yet been called.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The game's time</param>
|
/// <param name="time">The game's time</param>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Graphics;
|
using MLEM.Graphics;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
|
|
|
@ -135,8 +135,8 @@ namespace MLEM.Ui.Elements {
|
||||||
protected override Vector2 CalcActualSize(RectangleF parentArea) {
|
protected override Vector2 CalcActualSize(RectangleF parentArea) {
|
||||||
var size = base.CalcActualSize(parentArea);
|
var size = base.CalcActualSize(parentArea);
|
||||||
this.ParseText(size);
|
this.ParseText(size);
|
||||||
var (w, h) = this.TokenizedText.Measure(this.RegularFont) * this.TextScale * this.TextScaleMultiplier * this.Scale;
|
var textSize = this.TokenizedText.Measure(this.RegularFont) * this.TextScale * this.TextScaleMultiplier * this.Scale;
|
||||||
return new Vector2(this.AutoAdjustWidth ? w + this.ScaledPadding.Width : size.X, h + this.ScaledPadding.Height);
|
return new Vector2(this.AutoAdjustWidth ? textSize.X + this.ScaledPadding.Width : size.X, textSize.Y + this.ScaledPadding.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Microsoft.Xna.Framework.Input.Touch;
|
using Microsoft.Xna.Framework.Input.Touch;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Graphics;
|
using MLEM.Graphics;
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
|
@ -195,13 +196,13 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScrollToPos(Vector2 position) {
|
private void ScrollToPos(Vector2 position) {
|
||||||
var (width, height) = this.ScrollerSize * this.Scale;
|
var size = this.ScrollerSize * this.Scale;
|
||||||
if (this.Horizontal) {
|
if (this.Horizontal) {
|
||||||
var offset = this.scrollStartOffset.X >= 0 && this.scrollStartOffset.X <= width ? this.scrollStartOffset.X : width / 2;
|
var offset = this.scrollStartOffset.X >= 0 && this.scrollStartOffset.X <= size.X ? this.scrollStartOffset.X : size.X / 2;
|
||||||
this.CurrentValue = (position.X - this.Area.X - offset) / (this.Area.Width - width) * this.MaxValue;
|
this.CurrentValue = (position.X - this.Area.X - offset) / (this.Area.Width - size.X) * this.MaxValue;
|
||||||
} else {
|
} else {
|
||||||
var offset = this.scrollStartOffset.Y >= 0 && this.scrollStartOffset.Y <= height ? this.scrollStartOffset.Y : height / 2;
|
var offset = this.scrollStartOffset.Y >= 0 && this.scrollStartOffset.Y <= size.Y ? this.scrollStartOffset.Y : size.Y / 2;
|
||||||
this.CurrentValue = (position.Y - this.Area.Y - offset) / (this.Area.Height - height) * this.MaxValue;
|
this.CurrentValue = (position.Y - this.Area.Y - offset) / (this.Area.Height - size.Y) * this.MaxValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using MLEM.Font;
|
using MLEM.Font;
|
||||||
|
@ -110,6 +111,12 @@ namespace MLEM.Ui.Elements {
|
||||||
set => this.textInput.Multiline = value;
|
set => this.textInput.Multiline = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FNA
|
||||||
|
/// <inheritdoc />
|
||||||
|
// we need to make sure that the enter press doesn't get consumed by our press function so that it still works in TextInput
|
||||||
|
public override bool CanBePressed => base.CanBePressed && !this.IsSelected;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The text that displays in this text field if <see cref="Text"/> is empty
|
/// The text that displays in this text field if <see cref="Text"/> is empty
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
|
||||||
|
|
35
MLEM.Ui/MLEM.Ui.FNA.csproj
Normal file
35
MLEM.Ui/MLEM.Ui.FNA.csproj
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Ui</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>A mouse, keyboard, gamepad and touch ready Ui system for FNA that features automatic anchoring, sizing and several ready-to-use element types</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem ui user interface graphical gui system mouse keyboard gamepad touch</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="TextCopy" Version="6.1.0" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -18,7 +18,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="TextCopy" Version="4.3.1" />
|
<PackageReference Include="TextCopy" Version="6.1.0" />
|
||||||
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
||||||
|
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
||||||
|
|
|
@ -170,8 +170,13 @@ namespace MLEM.Ui.Parsers {
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
if (loc.StartsWith("http")) {
|
if (loc.StartsWith("http")) {
|
||||||
using (var client = new HttpClient()) {
|
using (var client = new HttpClient()) {
|
||||||
using (var src = await client.GetStreamAsync(loc))
|
using (var src = await client.GetStreamAsync(loc)) {
|
||||||
tex = Texture2D.FromStream(this.GraphicsDevice, src);
|
using (var memory = new MemoryStream()) {
|
||||||
|
// download the full stream before passing it to texture
|
||||||
|
await src.CopyToAsync(memory);
|
||||||
|
tex = Texture2D.FromStream(this.GraphicsDevice, memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
using (var stream = Path.IsPathRooted(loc) ? File.OpenRead(loc) : TitleContainer.OpenStream(loc))
|
using (var stream = Path.IsPathRooted(loc) ? File.OpenRead(loc) : TitleContainer.OpenStream(loc))
|
||||||
|
|
|
@ -159,7 +159,7 @@ namespace MLEM.Ui {
|
||||||
|
|
||||||
// MOUSE INPUT
|
// MOUSE INPUT
|
||||||
if (this.HandleMouse) {
|
if (this.HandleMouse) {
|
||||||
var mousedNow = this.GetElementUnderPos(this.Input.ViewportMousePosition.ToVector2());
|
var mousedNow = this.GetElementUnderPos(new Vector2(this.Input.ViewportMousePosition.X, this.Input.ViewportMousePosition.Y));
|
||||||
this.SetMousedElement(mousedNow);
|
this.SetMousedElement(mousedNow);
|
||||||
|
|
||||||
if (this.Input.IsMouseButtonPressedAvailable(MouseButton.Left)) {
|
if (this.Input.IsMouseButtonPressedAvailable(MouseButton.Left)) {
|
||||||
|
@ -414,8 +414,8 @@ namespace MLEM.Ui {
|
||||||
foreach (var child in children) {
|
foreach (var child in children) {
|
||||||
if (child == this.SelectedElement)
|
if (child == this.SelectedElement)
|
||||||
continue;
|
continue;
|
||||||
var (xOffset, yOffset) = child.Area.Center - this.SelectedElement.Area.Center;
|
var offset = child.Area.Center - this.SelectedElement.Area.Center;
|
||||||
var angle = Math.Abs(MathHelper.WrapAngle(direction.Angle() - (float) Math.Atan2(yOffset, xOffset)));
|
var angle = Math.Abs(MathHelper.WrapAngle(direction.Angle() - (float) Math.Atan2(offset.Y, offset.X)));
|
||||||
if (angle >= MathHelper.PiOver2 - Element.Epsilon)
|
if (angle >= MathHelper.PiOver2 - Element.Epsilon)
|
||||||
continue;
|
continue;
|
||||||
var distSq = child.Area.DistanceSquared(this.SelectedElement.Area);
|
var distSq = child.Area.DistanceSquared(this.SelectedElement.Area);
|
||||||
|
|
|
@ -5,7 +5,6 @@ using MLEM.Ui.Elements;
|
||||||
namespace MLEM.Ui {
|
namespace MLEM.Ui {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A snapshot of update and rendering statistics from <see cref="UiSystem.Metrics"/> to be used for runtime debugging and profiling.
|
/// A snapshot of update and rendering statistics from <see cref="UiSystem.Metrics"/> to be used for runtime debugging and profiling.
|
||||||
/// This metrics struct works similarly to <see cref="GraphicsMetrics"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct UiMetrics {
|
public struct UiMetrics {
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace MLEM.Ui {
|
||||||
public SamplerState SamplerState;
|
public SamplerState SamplerState;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The depth stencil state that this ui system and all of its elements draw with.
|
/// The depth stencil state that this ui system and all of its elements draw with.
|
||||||
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.DepthStencilState.None"/>, which is also the default for <see cref="SpriteBatch.Begin"/>.
|
/// The default is <see cref="Microsoft.Xna.Framework.Graphics.DepthStencilState.None"/>, which is also the default for <c>SpriteBatch.Begin</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Set this through SpriteBatchContext instead")]
|
[Obsolete("Set this through SpriteBatchContext instead")]
|
||||||
public DepthStencilState DepthStencilState;
|
public DepthStencilState DepthStencilState;
|
||||||
|
@ -241,10 +241,10 @@ namespace MLEM.Ui {
|
||||||
MlemPlatform.Current?.AddTextInputListener(game.Window, (sender, key, character) => this.ApplyToAll(e => e.OnTextInput?.Invoke(e, key, character)));
|
MlemPlatform.Current?.AddTextInputListener(game.Window, (sender, key, character) => this.ApplyToAll(e => e.OnTextInput?.Invoke(e, key, character)));
|
||||||
|
|
||||||
if (automaticViewport) {
|
if (automaticViewport) {
|
||||||
this.Viewport = new Rectangle(Point.Zero, game.Window.ClientBounds.Size);
|
this.Viewport = new Rectangle(0, 0, game.Window.ClientBounds.Width, game.Window.ClientBounds.Height);
|
||||||
this.AutoScaleReferenceSize = this.Viewport.Size;
|
this.AutoScaleReferenceSize = new Point(this.Viewport.Width, this.Viewport.Height);
|
||||||
game.Window.ClientSizeChanged += (sender, args) => {
|
game.Window.ClientSizeChanged += (sender, args) => {
|
||||||
this.Viewport = new Rectangle(Point.Zero, game.Window.ClientBounds.Size);
|
this.Viewport = new Rectangle(0, 0, game.Window.ClientBounds.Width, game.Window.ClientBounds.Height);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,11 +570,11 @@ namespace MLEM.Ui {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Element.GenericCallback OnElementRemoved;
|
public event Element.GenericCallback OnElementRemoved;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event that is invoked when this <see cref="RootElement"/> gets added to a <see cref="UiSystem"/> in <see cref="UiSystem.Add"/>
|
/// Event that is invoked when this <see cref="RootElement"/> gets added to a <see cref="UiSystem"/> in <see cref="UiSystem.Add"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<UiSystem> OnAddedToUi;
|
public event Action<UiSystem> OnAddedToUi;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event that is invoked when this <see cref="RootElement"/> gets removed from a <see cref="UiSystem"/> in <see cref="UiSystem.Remove"/>
|
/// Event that is invoked when this <see cref="RootElement"/> gets removed from a <see cref="UiSystem"/> in <see cref="UiSystem.Remove"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<UiSystem> OnRemovedFromUi;
|
public event Action<UiSystem> OnRemovedFromUi;
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace MLEM.Cameras {
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The matrix that this camera "sees", based on its position and scale.
|
/// The matrix that this camera "sees", based on its position and scale.
|
||||||
/// Use this in your <see cref="SpriteBatch.Begin"/> calls to render based on the camera's viewport.
|
/// Use this in your <c>SpriteBatch.Begin</c> calls to render based on the camera's viewport.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Matrix ViewMatrix {
|
public Matrix ViewMatrix {
|
||||||
get {
|
get {
|
||||||
|
@ -105,7 +105,7 @@ namespace MLEM.Cameras {
|
||||||
/// <param name="roundPosition">Whether the camera's <see cref="Position"/> should be rounded to full integers when calculating the <see cref="ViewMatrix"/></param>
|
/// <param name="roundPosition">Whether the camera's <see cref="Position"/> should be rounded to full integers when calculating the <see cref="ViewMatrix"/></param>
|
||||||
public Camera(GraphicsDevice graphicsDevice, bool roundPosition = true) {
|
public Camera(GraphicsDevice graphicsDevice, bool roundPosition = true) {
|
||||||
this.graphicsDevice = graphicsDevice;
|
this.graphicsDevice = graphicsDevice;
|
||||||
this.AutoScaleReferenceSize = this.Viewport.Size;
|
this.AutoScaleReferenceSize = new Point(this.Viewport.Width, this.Viewport.Height);
|
||||||
this.RoundPosition = roundPosition;
|
this.RoundPosition = roundPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ namespace MLEM.Cameras {
|
||||||
/// <param name="delta">The amount to zoom in or out by</param>
|
/// <param name="delta">The amount to zoom in or out by</param>
|
||||||
/// <param name="zoomCenter">The position that should be regarded as the zoom's center, in screen space. The default value is the center.</param>
|
/// <param name="zoomCenter">The position that should be regarded as the zoom's center, in screen space. The default value is the center.</param>
|
||||||
public void Zoom(float delta, Vector2? zoomCenter = null) {
|
public void Zoom(float delta, Vector2? zoomCenter = null) {
|
||||||
var center = (zoomCenter ?? this.Viewport.Size.ToVector2() / 2) / this.ActualScale;
|
var center = (zoomCenter ?? new Vector2(this.Viewport.Width, this.Viewport.Height) / 2) / this.ActualScale;
|
||||||
var lastScale = this.Scale;
|
var lastScale = this.Scale;
|
||||||
this.Scale += delta;
|
this.Scale += delta;
|
||||||
this.Position += center * ((this.Scale - lastScale) / this.Scale);
|
this.Position += center * ((this.Scale - lastScale) / this.Scale);
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace MLEM.Extensions {
|
||||||
/// <param name="manager">The graphics device manager</param>
|
/// <param name="manager">The graphics device manager</param>
|
||||||
/// <param name="window">The window whose bounds to use</param>
|
/// <param name="window">The window whose bounds to use</param>
|
||||||
public static void ResetWidthAndHeight(this GraphicsDeviceManager manager, GameWindow window) {
|
public static void ResetWidthAndHeight(this GraphicsDeviceManager manager, GameWindow window) {
|
||||||
var (_, _, width, height) = window.ClientBounds;
|
var (width, height) = (window.ClientBounds.Width, window.ClientBounds.Height);
|
||||||
manager.PreferredBackBufferWidth = Math.Max(height, width);
|
manager.PreferredBackBufferWidth = Math.Max(height, width);
|
||||||
manager.PreferredBackBufferHeight = Math.Min(height, width);
|
manager.PreferredBackBufferHeight = Math.Min(height, width);
|
||||||
manager.ApplyChanges();
|
manager.ApplyChanges();
|
||||||
|
@ -90,7 +90,12 @@ namespace MLEM.Extensions {
|
||||||
/// <param name="target">The target to apply</param>
|
/// <param name="target">The target to apply</param>
|
||||||
public TargetContext(GraphicsDevice device, RenderTarget2D target) {
|
public TargetContext(GraphicsDevice device, RenderTarget2D target) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
#if FNA
|
||||||
|
// RenderTargetCount doesn't exist in FNA but we still want the optimization in MG
|
||||||
|
this.lastTargets = device.GetRenderTargets();
|
||||||
|
#else
|
||||||
this.lastTargets = device.RenderTargetCount <= 0 ? null : device.GetRenderTargets();
|
this.lastTargets = device.RenderTargetCount <= 0 ? null : device.GetRenderTargets();
|
||||||
|
#endif
|
||||||
device.SetRenderTarget(target);
|
device.SetRenderTarget(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,13 +223,13 @@ namespace MLEM.Extensions {
|
||||||
/// <param name="matrix">The matrix</param>
|
/// <param name="matrix">The matrix</param>
|
||||||
/// <returns>The rotation of the matrix</returns>
|
/// <returns>The rotation of the matrix</returns>
|
||||||
public static Quaternion Rotation(this Matrix matrix) {
|
public static Quaternion Rotation(this Matrix matrix) {
|
||||||
var (scX, scY, scZ) = matrix.Scale();
|
var sc = matrix.Scale();
|
||||||
if (scX == 0 || scY == 0 || scZ == 0)
|
if (sc.X == 0 || sc.Y == 0 || sc.Z == 0)
|
||||||
return Quaternion.Identity;
|
return Quaternion.Identity;
|
||||||
return Quaternion.CreateFromRotationMatrix(new Matrix(
|
return Quaternion.CreateFromRotationMatrix(new Matrix(
|
||||||
matrix.M11 / scX, matrix.M12 / scX, matrix.M13 / scX, 0,
|
matrix.M11 / sc.X, matrix.M12 / sc.X, matrix.M13 / sc.X, 0,
|
||||||
matrix.M21 / scY, matrix.M22 / scY, matrix.M23 / scY, 0,
|
matrix.M21 / sc.Y, matrix.M22 / sc.Y, matrix.M23 / sc.Y, 0,
|
||||||
matrix.M31 / scZ, matrix.M32 / scZ, matrix.M33 / scZ, 0,
|
matrix.M31 / sc.Z, matrix.M32 / sc.Z, matrix.M33 / sc.Z, 0,
|
||||||
0, 0, 0, 1));
|
0, 0, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ namespace MLEM.Extensions {
|
||||||
/// <param name="quaternion">The quaternion</param>
|
/// <param name="quaternion">The quaternion</param>
|
||||||
/// <returns>The rotation of the quaternion</returns>
|
/// <returns>The rotation of the quaternion</returns>
|
||||||
public static Vector3 RotationVector(this Quaternion quaternion) {
|
public static Vector3 RotationVector(this Quaternion quaternion) {
|
||||||
var (x, y, z, w) = quaternion;
|
var (x, y, z, w) = (quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
|
||||||
return new Vector3(
|
return new Vector3(
|
||||||
(float) Math.Atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)),
|
(float) Math.Atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)),
|
||||||
(float) Math.Asin(MathHelper.Clamp(2 * (w * y - z * x), -1, 1)),
|
(float) Math.Asin(MathHelper.Clamp(2 * (w * y - z * x), -1, 1)),
|
||||||
|
@ -268,16 +268,16 @@ namespace MLEM.Extensions {
|
||||||
/// <param name="penetration">The amount that the penetration occured by, in the direction of <paramref name="normal"/></param>
|
/// <param name="penetration">The amount that the penetration occured by, in the direction of <paramref name="normal"/></param>
|
||||||
/// <returns>Whether or not a penetration occured</returns>
|
/// <returns>Whether or not a penetration occured</returns>
|
||||||
public static bool Penetrate(this RectangleF rect, RectangleF other, out Vector2 normal, out float penetration) {
|
public static bool Penetrate(this RectangleF rect, RectangleF other, out Vector2 normal, out float penetration) {
|
||||||
var (offsetX, offsetY) = other.Center - rect.Center;
|
var offset = other.Center - rect.Center;
|
||||||
var overlapX = rect.Width / 2 + other.Width / 2 - Math.Abs(offsetX);
|
var overlapX = rect.Width / 2 + other.Width / 2 - Math.Abs(offset.X);
|
||||||
if (overlapX > 0) {
|
if (overlapX > 0) {
|
||||||
var overlapY = rect.Height / 2 + other.Height / 2 - Math.Abs(offsetY);
|
var overlapY = rect.Height / 2 + other.Height / 2 - Math.Abs(offset.Y);
|
||||||
if (overlapY > 0) {
|
if (overlapY > 0) {
|
||||||
if (overlapX < overlapY) {
|
if (overlapX < overlapY) {
|
||||||
normal = new Vector2(offsetX < 0 ? -1 : 1, 0);
|
normal = new Vector2(offset.X < 0 ? -1 : 1, 0);
|
||||||
penetration = overlapX;
|
penetration = overlapX;
|
||||||
} else {
|
} else {
|
||||||
normal = new Vector2(0, offsetY < 0 ? -1 : 1);
|
normal = new Vector2(0, offset.Y < 0 ? -1 : 1);
|
||||||
penetration = overlapY;
|
penetration = overlapY;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -288,5 +288,23 @@ namespace MLEM.Extensions {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FNA
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Point"/> representation for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Point"/> representation for this object.</returns>
|
||||||
|
public static Point ToPoint(this Vector2 vector) {
|
||||||
|
return new Point((int) vector.X, (int) vector.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="Vector2"/> representation for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Vector2"/> representation for this object.</returns>
|
||||||
|
public static Vector2 ToVector2(this Point point) {
|
||||||
|
return new Vector2(point.X, point.Y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,18 +285,18 @@ namespace MLEM.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawString(SpriteBatch batch, CharSource text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
|
private void DrawString(SpriteBatch batch, CharSource text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) {
|
||||||
var (flipX, flipY) = Vector2.Zero;
|
var (flipX, flipY) = (0F, 0F);
|
||||||
var flippedV = (effects & SpriteEffects.FlipVertically) != 0;
|
var flippedV = (effects & SpriteEffects.FlipVertically) != 0;
|
||||||
var flippedH = (effects & SpriteEffects.FlipHorizontally) != 0;
|
var flippedH = (effects & SpriteEffects.FlipHorizontally) != 0;
|
||||||
if (flippedV || flippedH) {
|
if (flippedV || flippedH) {
|
||||||
var (w, h) = this.MeasureString(text, false, null);
|
var size = this.MeasureString(text, false, null);
|
||||||
if (flippedH) {
|
if (flippedH) {
|
||||||
origin.X *= -1;
|
origin.X *= -1;
|
||||||
flipX = -w;
|
flipX = -size.X;
|
||||||
}
|
}
|
||||||
if (flippedV) {
|
if (flippedV) {
|
||||||
origin.Y *= -1;
|
origin.Y *= -1;
|
||||||
flipY = this.LineHeight - h;
|
flipY = this.LineHeight - size.Y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,17 +327,17 @@ namespace MLEM.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cString = c.ToCachedString();
|
var cString = c.ToCachedString();
|
||||||
var (cW, cH) = this.MeasureString(cString);
|
var cSize = this.MeasureString(cString);
|
||||||
|
|
||||||
var charPos = offset;
|
var charPos = offset;
|
||||||
if (flippedH)
|
if (flippedH)
|
||||||
charPos.X += cW;
|
charPos.X += cSize.X;
|
||||||
if (flippedV)
|
if (flippedV)
|
||||||
charPos.Y += cH - this.LineHeight;
|
charPos.Y += cSize.Y - this.LineHeight;
|
||||||
Vector2.Transform(ref charPos, ref trans, out charPos);
|
Vector2.Transform(ref charPos, ref trans, out charPos);
|
||||||
|
|
||||||
this.DrawChar(batch, cString, charPos, color, rotation, scale, effects, layerDepth);
|
this.DrawChar(batch, cString, charPos, color, rotation, scale, effects, layerDepth);
|
||||||
offset.X += cW;
|
offset.X += cSize.X;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,10 @@ namespace MLEM.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SpriteFont SetDefaults(SpriteFont font) {
|
private static SpriteFont SetDefaults(SpriteFont font) {
|
||||||
|
#if FNA
|
||||||
|
// none of the copying is available with FNA
|
||||||
|
return font;
|
||||||
|
#else
|
||||||
// we copy the font here to set the default character to a space
|
// we copy the font here to set the default character to a space
|
||||||
return new SpriteFont(
|
return new SpriteFont(
|
||||||
font.Texture,
|
font.Texture,
|
||||||
|
@ -52,6 +56,7 @@ namespace MLEM.Font {
|
||||||
font.Spacing,
|
font.Spacing,
|
||||||
font.Glyphs.Select(g => new Vector3(g.LeftSideBearing, g.Width, g.RightSideBearing)).ToList(),
|
font.Glyphs.Select(g => new Vector3(g.LeftSideBearing, g.Width, g.RightSideBearing)).ToList(),
|
||||||
' ');
|
' ');
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ namespace MLEM.Formatting.Codes {
|
||||||
// don't underline spaces at the end of lines
|
// don't underline spaces at the end of lines
|
||||||
if (c == ' ' && token.DisplayString.Length > indexInToken + 1 && token.DisplayString[indexInToken + 1] == '\n')
|
if (c == ' ' && token.DisplayString.Length > indexInToken + 1 && token.DisplayString[indexInToken + 1] == '\n')
|
||||||
return false;
|
return false;
|
||||||
var (w, h) = font.MeasureString(cString) * scale;
|
var size = font.MeasureString(cString) * scale;
|
||||||
var t = h * this.thickness;
|
var t = size.Y * this.thickness;
|
||||||
batch.Draw(batch.GetBlankTexture(), new RectangleF(pos.X, pos.Y + this.yOffset * h - t, w, t), color);
|
batch.Draw(batch.GetBlankTexture(), new RectangleF(pos.X, pos.Y + this.yOffset * size.Y - t, size.X, t), color);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ namespace MLEM.Graphics {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This method allows for a tiled texture to be drawn in an auto-tiling mode.
|
/// This method allows for a tiled texture to be drawn in an auto-tiling mode.
|
||||||
/// This allows, for example, a grass patch on a tilemap to have nice looking edges that transfer over into a path without any hard edges between tiles.
|
/// This allows, for example, a grass patch on a tilemap to have nice looking edges that transfer over into a path without any hard edges between tiles.
|
||||||
///
|
///
|
||||||
/// This method is a more complex version of <see cref="DrawAutoTile"/> that overlays separate border textures on a background texture region, which also allows for non-rectangular texture areas to be used easily.
|
/// This method is a more complex version of <see cref="DrawAutoTile"/> that overlays separate border textures on a background texture region, which also allows for non-rectangular texture areas to be used easily.
|
||||||
/// For auto-tiling in this way to work, the overlay sections have to be laid out as follows: 16 sections aligned horizontally within the texture file, with the following information:
|
/// For auto-tiling in this way to work, the overlay sections have to be laid out as follows: 16 sections aligned horizontally within the texture file, with the following information:
|
||||||
/// <list type="number">
|
/// <list type="number">
|
||||||
/// <item><description>The texture used for straight, horizontal borders, with the borders facing away from the center, split up into four parts: top left, then top right, then bottom left, then bottom right</description></item>
|
/// <item><description>The texture used for straight, horizontal borders, with the borders facing away from the center, split up into four parts: top left, then top right, then bottom left, then bottom right</description></item>
|
||||||
|
@ -138,8 +138,8 @@ namespace MLEM.Graphics {
|
||||||
var xUr = up && right ? connectsTo(1, -1) ? 0 : 4 : right ? 1 : up ? 3 : 2;
|
var xUr = up && right ? connectsTo(1, -1) ? 0 : 4 : right ? 1 : up ? 3 : 2;
|
||||||
var xDl = down && left ? connectsTo(-1, 1) ? 0 : 4 : left ? 1 : down ? 3 : 2;
|
var xDl = down && left ? connectsTo(-1, 1) ? 0 : 4 : left ? 1 : down ? 3 : 2;
|
||||||
var xDr = down && right ? connectsTo(1, 1) ? 0 : 4 : right ? 1 : down ? 3 : 2;
|
var xDr = down && right ? connectsTo(1, 1) ? 0 : 4 : right ? 1 : down ? 3 : 2;
|
||||||
var (w, h) = textureRegion.Size;
|
var (w, h) = (textureRegion.Width, textureRegion.Height);
|
||||||
var (w2, h2) = new Point(w / 2, h / 2);
|
var (w2, h2) = (w / 2, h / 2);
|
||||||
return (
|
return (
|
||||||
new Vector2(pos.X, pos.Y), new Rectangle(textureRegion.X + xUl * w, textureRegion.Y, w2, h2),
|
new Vector2(pos.X, pos.Y), new Rectangle(textureRegion.X + xUl * w, textureRegion.Y, w2, h2),
|
||||||
new Vector2(pos.X + w2 * scale.X, pos.Y), new Rectangle(textureRegion.X + w2 + xUr * w, textureRegion.Y, w2, h2),
|
new Vector2(pos.X + w2 * scale.X, pos.Y), new Rectangle(textureRegion.X + w2 + xUr * w, textureRegion.Y, w2, h2),
|
||||||
|
@ -156,7 +156,7 @@ namespace MLEM.Graphics {
|
||||||
var xUr = up && right ? connectsTo(1, -1) ? -1 : 13 : right ? 1 : up ? 9 : 5;
|
var xUr = up && right ? connectsTo(1, -1) ? -1 : 13 : right ? 1 : up ? 9 : 5;
|
||||||
var xDl = down && left ? connectsTo(-1, 1) ? -1 : 14 : left ? 2 : down ? 10 : 6;
|
var xDl = down && left ? connectsTo(-1, 1) ? -1 : 14 : left ? 2 : down ? 10 : 6;
|
||||||
var xDr = down && right ? connectsTo(1, 1) ? -1 : 15 : right ? 3 : down ? 11 : 7;
|
var xDr = down && right ? connectsTo(1, 1) ? -1 : 15 : right ? 3 : down ? 11 : 7;
|
||||||
var (w, h) = textureRegion.Size;
|
var (w, h) = (textureRegion.Width, textureRegion.Height);
|
||||||
return (
|
return (
|
||||||
xUl < 0 ? Rectangle.Empty : new Rectangle(textureRegion.X + xUl * w, textureRegion.Y, w, h),
|
xUl < 0 ? Rectangle.Empty : new Rectangle(textureRegion.X + xUl * w, textureRegion.Y, w, h),
|
||||||
xUr < 0 ? Rectangle.Empty : new Rectangle(textureRegion.X + xUr * w, textureRegion.Y, w, h),
|
xUr < 0 ? Rectangle.Empty : new Rectangle(textureRegion.X + xUr * w, textureRegion.Y, w, h),
|
||||||
|
|
|
@ -3,7 +3,7 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace MLEM.Graphics {
|
namespace MLEM.Graphics {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sprite batch context is a set of information for a <see cref="SpriteBatch"/> to use, which encapsulates all of the information usually passed directly to <see cref="SpriteBatch.Begin"/>.
|
/// A sprite batch context is a set of information for a <see cref="SpriteBatch"/> to use, which encapsulates all of the information usually passed directly to <c>SpriteBatch.Begin</c>.
|
||||||
/// To use a sprite batch context effectively, the extension methods in <see cref="SpriteBatchContextExtensions"/> should be used.
|
/// To use a sprite batch context effectively, the extension methods in <see cref="SpriteBatchContextExtensions"/> should be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct SpriteBatchContext {
|
public struct SpriteBatchContext {
|
||||||
|
@ -17,7 +17,7 @@ namespace MLEM.Graphics {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BlendState BlendState;
|
public BlendState BlendState;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// State of the sampler.
|
/// State of the sampler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SamplerState SamplerState;
|
public SamplerState SamplerState;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Extensions;
|
||||||
|
|
||||||
namespace MLEM.Graphics {
|
namespace MLEM.Graphics {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -174,18 +176,18 @@ namespace MLEM.Graphics {
|
||||||
for (var i = 0; i < this.FilledBuffers; i++) {
|
for (var i = 0; i < this.FilledBuffers; i++) {
|
||||||
var buffer = this.vertexBuffers[i];
|
var buffer = this.vertexBuffers[i];
|
||||||
var texture = this.textures[i];
|
var texture = this.textures[i];
|
||||||
var tris = Math.Min(this.items.Count * 4 - totalIndex, buffer.VertexCount) / 4 * 2;
|
var verts = Math.Min(this.items.Count * 4 - totalIndex, buffer.VertexCount);
|
||||||
|
|
||||||
this.graphicsDevice.SetVertexBuffer(buffer);
|
this.graphicsDevice.SetVertexBuffer(buffer);
|
||||||
if (effect != null) {
|
if (effect != null) {
|
||||||
foreach (var pass in effect.CurrentTechnique.Passes) {
|
foreach (var pass in effect.CurrentTechnique.Passes) {
|
||||||
pass.Apply();
|
pass.Apply();
|
||||||
this.graphicsDevice.Textures[0] = texture;
|
this.graphicsDevice.Textures[0] = texture;
|
||||||
this.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, tris);
|
this.DrawPrimitives(verts);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.graphicsDevice.Textures[0] = texture;
|
this.graphicsDevice.Textures[0] = texture;
|
||||||
this.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, tris);
|
this.DrawPrimitives(verts);
|
||||||
}
|
}
|
||||||
|
|
||||||
totalIndex += buffer.VertexCount;
|
totalIndex += buffer.VertexCount;
|
||||||
|
@ -290,10 +292,11 @@ namespace MLEM.Graphics {
|
||||||
if ((effects & SpriteEffects.FlipHorizontally) != 0)
|
if ((effects & SpriteEffects.FlipHorizontally) != 0)
|
||||||
(texBr.X, texTl.X) = (texTl.X, texBr.X);
|
(texBr.X, texTl.X) = (texTl.X, texBr.X);
|
||||||
|
|
||||||
|
var destSize = new Vector2(destinationRectangle.Width, destinationRectangle.Height);
|
||||||
if (rotation == 0) {
|
if (rotation == 0) {
|
||||||
return this.Add(texture, destinationRectangle.Location.ToVector2() - origin, destinationRectangle.Size.ToVector2(), color, texTl, texBr, layerDepth);
|
return this.Add(texture, destinationRectangle.Location.ToVector2() - origin, destSize, color, texTl, texBr, layerDepth);
|
||||||
} else {
|
} else {
|
||||||
return this.Add(texture, destinationRectangle.Location.ToVector2(), -origin, destinationRectangle.Size.ToVector2(), (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth);
|
return this.Add(texture, destinationRectangle.Location.ToVector2(), -origin, destSize, (float) Math.Sin(rotation), (float) Math.Cos(rotation), color, texTl, texBr, layerDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +442,14 @@ namespace MLEM.Graphics {
|
||||||
this.textures.Insert(index, texture);
|
this.textures.Insert(index, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawPrimitives(int vertices) {
|
||||||
|
#if FNA
|
||||||
|
this.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices, 0, vertices / 4 * 2);
|
||||||
|
#else
|
||||||
|
this.graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices / 4 * 2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A struct that represents an item added to a <see cref="StaticSpriteBatch"/> using <c>Add</c> or any of its overloads.
|
/// A struct that represents an item added to a <see cref="StaticSpriteBatch"/> using <c>Add</c> or any of its overloads.
|
||||||
/// An item returned after adding can be removed using <see cref="Remove"/>.
|
/// An item returned after adding can be removed using <see cref="Remove"/>.
|
||||||
|
@ -463,5 +474,58 @@ namespace MLEM.Graphics {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FNA
|
||||||
|
private class SpriteEffect : Effect {
|
||||||
|
|
||||||
|
private EffectParameter matrixParam;
|
||||||
|
private Viewport lastViewport;
|
||||||
|
private Matrix projection;
|
||||||
|
|
||||||
|
public Matrix? TransformMatrix { get; set; }
|
||||||
|
|
||||||
|
public SpriteEffect(GraphicsDevice device) : base(device, SpriteEffect.LoadEffectCode()) {
|
||||||
|
this.CacheEffectParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpriteEffect(SpriteEffect cloneSource) : base(cloneSource) {
|
||||||
|
this.CacheEffectParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Effect Clone() {
|
||||||
|
return new SpriteEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CacheEffectParameters() {
|
||||||
|
this.matrixParam = this.Parameters["MatrixTransform"];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApply() {
|
||||||
|
var vp = this.GraphicsDevice.Viewport;
|
||||||
|
if (vp.Width != this.lastViewport.Width || vp.Height != this.lastViewport.Height) {
|
||||||
|
Matrix.CreateOrthographicOffCenter(0, vp.Width, vp.Height, 0, 0, -1, out this.projection);
|
||||||
|
this.projection.M41 += -0.5f * this.projection.M11;
|
||||||
|
this.projection.M42 += -0.5f * this.projection.M22;
|
||||||
|
this.lastViewport = vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.TransformMatrix.HasValue) {
|
||||||
|
this.matrixParam.SetValue(this.TransformMatrix.GetValueOrDefault() * this.projection);
|
||||||
|
} else {
|
||||||
|
this.matrixParam.SetValue(this.projection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] LoadEffectCode() {
|
||||||
|
using (var stream = typeof(Effect).Assembly.GetManifestResourceStream("Microsoft.Xna.Framework.Graphics.Effect.Resources.SpriteEffect.fxb")) {
|
||||||
|
using (var memory = new MemoryStream()) {
|
||||||
|
stream.CopyTo(memory);
|
||||||
|
return memory.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@ namespace MLEM.Input {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class InputHandler : GameComponent {
|
public class InputHandler : GameComponent {
|
||||||
|
|
||||||
|
#if FNA
|
||||||
|
private const int MaximumGamePadCount = 4;
|
||||||
|
#else
|
||||||
|
private static readonly int MaximumGamePadCount = GamePad.MaximumGamePadCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains all of the gestures that have finished during the last update call.
|
/// Contains all of the gestures that have finished during the last update call.
|
||||||
/// To easily query these gestures, use <see cref="GetGesture"/> or <see cref="GetViewportGesture"/>.
|
/// To easily query these gestures, use <see cref="GetGesture"/> or <see cref="GetViewportGesture"/>.
|
||||||
|
@ -80,11 +86,11 @@ namespace MLEM.Input {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the touch state from the last update call
|
/// Contains the touch state from the last update call
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TouchCollection LastTouchState { get; private set; }
|
public TouchCollection LastTouchState { get; private set; } = new TouchCollection(Array.Empty<TouchLocation>());
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the current touch state
|
/// Contains the current touch state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TouchCollection TouchState { get; private set; }
|
public TouchCollection TouchState { get; private set; } = new TouchCollection(Array.Empty<TouchLocation>());
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the <see cref="LastTouchState"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
/// Contains the <see cref="LastTouchState"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -109,7 +115,7 @@ namespace MLEM.Input {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the position of the mouse from the last update call, extracted from <see cref="LastMouseState"/>
|
/// Contains the position of the mouse from the last update call, extracted from <see cref="LastMouseState"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Point LastMousePosition => this.LastMouseState.Position;
|
public Point LastMousePosition => new Point(this.LastMouseState.X, this.LastMouseState.Y);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the <see cref="LastMousePosition"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
/// Contains the <see cref="LastMousePosition"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -117,7 +123,7 @@ namespace MLEM.Input {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the current position of the mouse, extracted from <see cref="MouseState"/>
|
/// Contains the current position of the mouse, extracted from <see cref="MouseState"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Point MousePosition => this.MouseState.Position;
|
public Point MousePosition => new Point(this.MouseState.X, this.MouseState.Y);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the <see cref="MousePosition"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
/// Contains the <see cref="MousePosition"/>, but with the <see cref="GraphicsDevice.Viewport"/> taken into account.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -139,11 +145,11 @@ namespace MLEM.Input {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public KeyboardState KeyboardState { get; private set; }
|
public KeyboardState KeyboardState { get; private set; }
|
||||||
|
|
||||||
private readonly GamePadState[] lastGamepads = new GamePadState[GamePad.MaximumGamePadCount];
|
private readonly GamePadState[] lastGamepads = new GamePadState[MaximumGamePadCount];
|
||||||
private readonly GamePadState[] gamepads = new GamePadState[GamePad.MaximumGamePadCount];
|
private readonly GamePadState[] gamepads = new GamePadState[MaximumGamePadCount];
|
||||||
private readonly DateTime[] lastGamepadButtonRepeats = new DateTime[GamePad.MaximumGamePadCount];
|
private readonly DateTime[] lastGamepadButtonRepeats = new DateTime[MaximumGamePadCount];
|
||||||
private readonly bool[] triggerGamepadButtonRepeat = new bool[GamePad.MaximumGamePadCount];
|
private readonly bool[] triggerGamepadButtonRepeat = new bool[MaximumGamePadCount];
|
||||||
private readonly Buttons?[] heldGamepadButtons = new Buttons?[GamePad.MaximumGamePadCount];
|
private readonly Buttons?[] heldGamepadButtons = new Buttons?[MaximumGamePadCount];
|
||||||
private readonly List<GestureSample> gestures = new List<GestureSample>();
|
private readonly List<GestureSample> gestures = new List<GestureSample>();
|
||||||
private readonly HashSet<(GenericInput, int)> consumedPresses = new HashSet<(GenericInput, int)>();
|
private readonly HashSet<(GenericInput, int)> consumedPresses = new HashSet<(GenericInput, int)>();
|
||||||
|
|
||||||
|
@ -209,7 +215,7 @@ namespace MLEM.Input {
|
||||||
if (this.HandleMouse) {
|
if (this.HandleMouse) {
|
||||||
this.LastMouseState = this.MouseState;
|
this.LastMouseState = this.MouseState;
|
||||||
var state = Mouse.GetState();
|
var state = Mouse.GetState();
|
||||||
if (active && this.Game.GraphicsDevice.Viewport.Bounds.Contains(state.Position)) {
|
if (active && this.Game.GraphicsDevice.Viewport.Bounds.Contains(state.X, state.Y)) {
|
||||||
this.MouseState = state;
|
this.MouseState = state;
|
||||||
foreach (var button in MouseExtensions.MouseButtons) {
|
foreach (var button in MouseExtensions.MouseButtons) {
|
||||||
if (state.GetState(button) == ButtonState.Pressed)
|
if (state.GetState(button) == ButtonState.Pressed)
|
||||||
|
@ -217,18 +223,22 @@ namespace MLEM.Input {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// mouse position and scroll wheel value should be preserved when the mouse is out of bounds
|
// mouse position and scroll wheel value should be preserved when the mouse is out of bounds
|
||||||
|
#if FNA
|
||||||
|
this.MouseState = new MouseState(state.X, state.Y, state.ScrollWheelValue, 0, 0, 0, 0, 0);
|
||||||
|
#else
|
||||||
this.MouseState = new MouseState(state.X, state.Y, state.ScrollWheelValue, 0, 0, 0, 0, 0, state.HorizontalScrollWheelValue);
|
this.MouseState = new MouseState(state.X, state.Y, state.ScrollWheelValue, 0, 0, 0, 0, 0, state.HorizontalScrollWheelValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.HandleGamepads) {
|
if (this.HandleGamepads) {
|
||||||
this.ConnectedGamepads = GamePad.MaximumGamePadCount;
|
this.ConnectedGamepads = MaximumGamePadCount;
|
||||||
for (var i = 0; i < GamePad.MaximumGamePadCount; i++) {
|
for (var i = 0; i < MaximumGamePadCount; i++) {
|
||||||
this.lastGamepads[i] = this.gamepads[i];
|
this.lastGamepads[i] = this.gamepads[i];
|
||||||
this.gamepads[i] = GamePadState.Default;
|
this.gamepads[i] = default;
|
||||||
if (GamePad.GetCapabilities(i).IsConnected) {
|
if (GamePad.GetCapabilities((PlayerIndex) i).IsConnected) {
|
||||||
if (active) {
|
if (active) {
|
||||||
this.gamepads[i] = GamePad.GetState(i);
|
this.gamepads[i] = GamePad.GetState((PlayerIndex) i);
|
||||||
foreach (var button in EnumHelper.Buttons) {
|
foreach (var button in EnumHelper.Buttons) {
|
||||||
if (this.IsGamepadButtonDown(button, i))
|
if (this.IsGamepadButtonDown(button, i))
|
||||||
this.AccumulateDown(button, i);
|
this.AccumulateDown(button, i);
|
||||||
|
@ -263,12 +273,13 @@ namespace MLEM.Input {
|
||||||
this.LastTouchState = this.TouchState;
|
this.LastTouchState = this.TouchState;
|
||||||
this.LastViewportTouchState = this.ViewportTouchState;
|
this.LastViewportTouchState = this.ViewportTouchState;
|
||||||
|
|
||||||
this.TouchState = active ? TouchPanel.GetState() : default;
|
this.TouchState = active ? TouchPanel.GetState() : new TouchCollection(Array.Empty<TouchLocation>());
|
||||||
if (this.TouchState.Count > 0 && this.ViewportOffset != Point.Zero) {
|
if (this.TouchState.Count > 0 && this.ViewportOffset != Point.Zero) {
|
||||||
this.ViewportTouchState = new List<TouchLocation>();
|
this.ViewportTouchState = new List<TouchLocation>();
|
||||||
foreach (var touch in this.TouchState) {
|
foreach (var touch in this.TouchState) {
|
||||||
touch.TryGetPreviousLocation(out var previous);
|
touch.TryGetPreviousLocation(out var previous);
|
||||||
this.ViewportTouchState.Add(new TouchLocation(touch.Id, touch.State, touch.Position + this.ViewportOffset.ToVector2(), previous.State, previous.Position + this.ViewportOffset.ToVector2()));
|
var offset = new Vector2(this.ViewportOffset.X, this.ViewportOffset.Y);
|
||||||
|
this.ViewportTouchState.Add(new TouchLocation(touch.Id, touch.State, touch.Position + offset, previous.State, previous.Position + offset));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.ViewportTouchState = this.TouchState;
|
this.ViewportTouchState = this.TouchState;
|
||||||
|
@ -548,7 +559,7 @@ namespace MLEM.Input {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether the given key is considered pressed.
|
/// Returns whether the given key is considered pressed.
|
||||||
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
|
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call. If <see cref="InvertPressBehavior"/> is true, this behavior is inverted.
|
||||||
/// This has the same behavior as <see cref="IsGamepadButtonPressed"/>, but ignores gamepad repeat events.
|
/// This has the same behavior as <see cref="IsGamepadButtonPressed"/>, but ignores gamepad repeat events.
|
||||||
/// If <see cref="HandleGamepadRepeats"/> is false, this method does the same as <see cref="IsGamepadButtonPressed"/>.
|
/// If <see cref="HandleGamepadRepeats"/> is false, this method does the same as <see cref="IsGamepadButtonPressed"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="button">The button to query</param>
|
/// <param name="button">The button to query</param>
|
||||||
|
@ -613,7 +624,8 @@ namespace MLEM.Input {
|
||||||
/// <returns>True if a gesture of the type was found, otherwise false</returns>
|
/// <returns>True if a gesture of the type was found, otherwise false</returns>
|
||||||
public bool GetViewportGesture(GestureType type, out GestureSample sample) {
|
public bool GetViewportGesture(GestureType type, out GestureSample sample) {
|
||||||
if (this.GetGesture(type, out var original)) {
|
if (this.GetGesture(type, out var original)) {
|
||||||
sample = new GestureSample(original.GestureType, original.Timestamp, original.Position + this.ViewportOffset.ToVector2(), original.Position2 + this.ViewportOffset.ToVector2(), original.Delta, original.Delta2);
|
var offset = new Vector2(this.ViewportOffset.X, this.ViewportOffset.Y);
|
||||||
|
sample = new GestureSample(original.GestureType, original.Timestamp, original.Position + offset, original.Position2 + offset, original.Delta, original.Delta2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
sample = default;
|
sample = default;
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace MLEM.Input {
|
||||||
public int CaretPos {
|
public int CaretPos {
|
||||||
get => this.caretPos;
|
get => this.caretPos;
|
||||||
set {
|
set {
|
||||||
var val = MathHelper.Clamp(value, 0, this.text.Length);
|
var val = (int) MathHelper.Clamp(value, 0F, this.text.Length);
|
||||||
if (this.caretPos != val) {
|
if (this.caretPos != val) {
|
||||||
this.caretPos = val;
|
this.caretPos = val;
|
||||||
this.caretBlinkTimer = 0;
|
this.caretBlinkTimer = 0;
|
||||||
|
@ -226,12 +226,14 @@ namespace MLEM.Input {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A method that should be called when the given text should be entered into this text input.
|
/// A method that should be called when the given text should be entered into this text input.
|
||||||
/// This method is designed to be used with the <see cref="GameWindow.TextInput"/> event.
|
/// This method is designed to be used with <see cref="MlemPlatform.AddTextInputListener"/> or the TextInput event provided by MonoGame and FNA.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key that was pressed.</param>
|
/// <param name="key">The key that was pressed.</param>
|
||||||
/// <param name="character">The character that the <paramref name="key"/> represents.</param>
|
/// <param name="character">The character that the <paramref name="key"/> represents.</param>
|
||||||
/// <returns>Whether text was successfully input.</returns>
|
/// <returns>Whether text was successfully input.</returns>
|
||||||
public bool OnTextInput(Keys key, char character) {
|
public bool OnTextInput(Keys key, char character) {
|
||||||
|
// FNA's text input event doesn't supply keys, so we handle this in Update
|
||||||
|
#if !FNA
|
||||||
if (key == Keys.Back) {
|
if (key == Keys.Back) {
|
||||||
if (this.CaretPos > 0) {
|
if (this.CaretPos > 0) {
|
||||||
this.CaretPos--;
|
this.CaretPos--;
|
||||||
|
@ -246,6 +248,9 @@ namespace MLEM.Input {
|
||||||
return this.InsertText(character);
|
return this.InsertText(character);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
#else
|
||||||
|
return this.InsertText(character);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -254,26 +259,37 @@ namespace MLEM.Input {
|
||||||
/// <param name="time">The current game time.</param>
|
/// <param name="time">The current game time.</param>
|
||||||
/// <param name="input">The input handler to use for input querying.</param>
|
/// <param name="input">The input handler to use for input querying.</param>
|
||||||
public void Update(GameTime time, InputHandler input) {
|
public void Update(GameTime time, InputHandler input) {
|
||||||
|
// FNA's text input event doesn't supply keys, so we handle this here
|
||||||
|
#if FNA
|
||||||
|
if (this.CaretPos > 0 && input.TryConsumePressed(Keys.Back)) {
|
||||||
|
this.CaretPos--;
|
||||||
|
this.RemoveText(this.CaretPos, 1);
|
||||||
|
} else if (this.CaretPos < this.text.Length && input.TryConsumePressed(Keys.Delete)) {
|
||||||
|
this.RemoveText(this.CaretPos, 1);
|
||||||
|
} else if (this.Multiline && input.TryConsumePressed(Keys.Enter)) {
|
||||||
|
this.InsertText('\n');
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (this.CaretPos > 0 && input.TryConsumePressed(Keys.Left)) {
|
if (this.CaretPos > 0 && input.TryConsumePressed(Keys.Left)) {
|
||||||
this.CaretPos--;
|
this.CaretPos--;
|
||||||
} else if (this.CaretPos < this.text.Length && input.TryConsumePressed(Keys.Right)) {
|
} else if (this.CaretPos < this.text.Length && input.TryConsumePressed(Keys.Right)) {
|
||||||
this.CaretPos++;
|
this.CaretPos++;
|
||||||
} else if (this.Multiline && input.IsKeyPressedAvailable(Keys.Up) && this.MoveCaretToLine(this.CaretLine - 1)) {
|
} else if (this.Multiline && input.IsKeyPressedAvailable(Keys.Up) && this.MoveCaretToLine(this.CaretLine - 1)) {
|
||||||
input.TryConsumeKeyPressed(Keys.Up);
|
input.TryConsumePressed(Keys.Up);
|
||||||
} else if (this.Multiline && input.IsKeyPressedAvailable(Keys.Down) && this.MoveCaretToLine(this.CaretLine + 1)) {
|
} else if (this.Multiline && input.IsKeyPressedAvailable(Keys.Down) && this.MoveCaretToLine(this.CaretLine + 1)) {
|
||||||
input.TryConsumeKeyPressed(Keys.Down);
|
input.TryConsumePressed(Keys.Down);
|
||||||
} else if (this.CaretPos != 0 && input.TryConsumeKeyPressed(Keys.Home)) {
|
} else if (this.CaretPos != 0 && input.TryConsumePressed(Keys.Home)) {
|
||||||
this.CaretPos = 0;
|
this.CaretPos = 0;
|
||||||
} else if (this.CaretPos != this.text.Length && input.TryConsumeKeyPressed(Keys.End)) {
|
} else if (this.CaretPos != this.text.Length && input.TryConsumePressed(Keys.End)) {
|
||||||
this.CaretPos = this.text.Length;
|
this.CaretPos = this.text.Length;
|
||||||
} else if (input.IsModifierKeyDown(ModifierKey.Control)) {
|
} else if (input.IsModifierKeyDown(ModifierKey.Control)) {
|
||||||
if (input.IsKeyPressedAvailable(Keys.V)) {
|
if (input.IsKeyPressedAvailable(Keys.V)) {
|
||||||
var clip = this.PasteFromClipboardFunction?.Invoke();
|
var clip = this.PasteFromClipboardFunction?.Invoke();
|
||||||
if (clip != null) {
|
if (clip != null) {
|
||||||
this.InsertText(clip, true);
|
this.InsertText(clip, true);
|
||||||
input.TryConsumeKeyPressed(Keys.V);
|
input.TryConsumePressed(Keys.V);
|
||||||
}
|
}
|
||||||
} else if (input.TryConsumeKeyPressed(Keys.C)) {
|
} else if (input.TryConsumePressed(Keys.C)) {
|
||||||
// until there is text selection, just copy the whole content
|
// until there is text selection, just copy the whole content
|
||||||
this.CopyToClipboardFunction?.Invoke(this.Text);
|
this.CopyToClipboardFunction?.Invoke(this.Text);
|
||||||
}
|
}
|
||||||
|
|
32
MLEM/MLEM.FNA.csproj
Normal file
32
MLEM/MLEM.FNA.csproj
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>MLEM Library for Extending FNA provides extension methods and additional features for FNA</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -182,8 +182,8 @@ namespace MLEM.Misc {
|
||||||
/// <param name="dir">The direction whose angle to get</param>
|
/// <param name="dir">The direction whose angle to get</param>
|
||||||
/// <returns>The direction's angle</returns>
|
/// <returns>The direction's angle</returns>
|
||||||
public static float Angle(this Direction2 dir) {
|
public static float Angle(this Direction2 dir) {
|
||||||
var (x, y) = dir.Offset();
|
var off = dir.Offset();
|
||||||
return (float) Math.Atan2(y, x);
|
return (float) Math.Atan2(off.Y, off.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -57,9 +57,9 @@ namespace MLEM.Misc {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A delegate method that can be used for <see cref="MlemPlatform.AddTextInputListener"/>
|
/// A delegate method that can be used for <see cref="MlemPlatform.AddTextInputListener"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The object that sent the event. The <see cref="MlemPlatform"/> used in most cases.</param>
|
/// <param name="sender">The object that sent the event. The <see cref="GameWindow"/> or <see cref="MlemPlatform"/> used in most cases.</param>
|
||||||
/// <param name="key">The key that was pressed</param>
|
/// <param name="key">The key that was pressed. Note that this is always <see cref="Keys.None"/> on FNA.</param>
|
||||||
/// <param name="character">The character that corresponds to that key</param>
|
/// <param name="character">The character that corresponds to that key.</param>
|
||||||
public delegate void TextInputCallback(object sender, Keys key, char character);
|
public delegate void TextInputCallback(object sender, Keys key, char character);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -78,10 +78,10 @@ namespace MLEM.Misc {
|
||||||
private readonly Action<GameWindow, EventHandler<T>> addListener;
|
private readonly Action<GameWindow, EventHandler<T>> addListener;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new DesktopGL-based platform
|
/// Creates a new DesktopGL-based platform.
|
||||||
/// See <see cref="MlemPlatform.DesktopGl{T}"/> class documentation for more detailed information.
|
/// See <see cref="MlemPlatform.DesktopGl{T}"/> class documentation for more detailed information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="addListener">The function that is used to add a text input listener</param>
|
/// <param name="addListener">The function that is used to add a text input listener.</param>
|
||||||
public DesktopGl(Action<GameWindow, EventHandler<T>> addListener) {
|
public DesktopGl(Action<GameWindow, EventHandler<T>> addListener) {
|
||||||
this.addListener = addListener;
|
this.addListener = addListener;
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,44 @@ namespace MLEM.Misc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The MLEM Desktop platform for FNA.
|
||||||
|
/// This platform uses the built-in FNA TextInputEXT event, which makes this listener work with any keyboard localization natively.
|
||||||
|
/// This platform is initialized as follows:
|
||||||
|
/// <code>
|
||||||
|
/// MlemPlatform.Current = new MlemPlatform.DesktopFna(a => TextInputEXT.TextInput += a);
|
||||||
|
/// </code>
|
||||||
|
/// </summary>
|
||||||
|
public class DesktopFna : MlemPlatform {
|
||||||
|
|
||||||
|
private readonly Action<Action<char>> addListener;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new Desktop for FNA platform.
|
||||||
|
/// See <see cref="MlemPlatform.DesktopFna"/> class documentation for more detailed information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="addListener">The function that is used to add a text input listener.</param>
|
||||||
|
public DesktopFna(Action<Action<char>> addListener) {
|
||||||
|
this.addListener = addListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task<string> OpenOnScreenKeyboard(string title, string description, string defaultText, bool usePasswordMode) {
|
||||||
|
return Task.FromResult<string>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void AddTextInputListener(GameWindow window, TextInputCallback callback) {
|
||||||
|
this.addListener(c => callback(this, Keys.None, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OpenLinkOrFile(string link) {
|
||||||
|
Process.Start(new ProcessStartInfo(link) {UseShellExecute = true});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The MLEM platform for mobile platforms as well as consoles.
|
/// The MLEM platform for mobile platforms as well as consoles.
|
||||||
/// This platform opens an on-screen keyboard using the <see cref="Microsoft.Xna.Framework.Input"/> <c>KeyboardInput</c> class on mobile devices.
|
/// This platform opens an on-screen keyboard using the <see cref="Microsoft.Xna.Framework.Input"/> <c>KeyboardInput</c> class on mobile devices.
|
||||||
|
|
|
@ -105,12 +105,12 @@ namespace MLEM.Misc {
|
||||||
this.Height = size.Y;
|
this.Height = size.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Contains(float, float)"/>
|
/// <inheritdoc cref="Rectangle.Contains(int, int)"/>
|
||||||
public bool Contains(float x, float y) {
|
public bool Contains(float x, float y) {
|
||||||
return this.X <= x && x < this.X + this.Width && this.Y <= y && y < this.Y + this.Height;
|
return this.X <= x && x < this.X + this.Width && this.Y <= y && y < this.Y + this.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Contains(Vector2)"/>
|
/// <inheritdoc cref="Rectangle.Contains(Point)"/>
|
||||||
public bool Contains(Vector2 value) {
|
public bool Contains(Vector2 value) {
|
||||||
return this.Contains(value.X, value.Y);
|
return this.Contains(value.X, value.Y);
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ namespace MLEM.Misc {
|
||||||
return (((17 * 23 + this.X.GetHashCode()) * 23 + this.Y.GetHashCode()) * 23 + this.Width.GetHashCode()) * 23 + this.Height.GetHashCode();
|
return (((17 * 23 + this.X.GetHashCode()) * 23 + this.Y.GetHashCode()) * 23 + this.Width.GetHashCode()) * 23 + this.Height.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Inflate(float,float)"/>
|
/// <inheritdoc cref="Rectangle.Inflate(int,int)"/>
|
||||||
public void Inflate(float horizontalAmount, float verticalAmount) {
|
public void Inflate(float horizontalAmount, float verticalAmount) {
|
||||||
this.X -= horizontalAmount;
|
this.X -= horizontalAmount;
|
||||||
this.Y -= verticalAmount;
|
this.Y -= verticalAmount;
|
||||||
|
@ -153,13 +153,13 @@ namespace MLEM.Misc {
|
||||||
return value.Left < this.Right && this.Left < value.Right && value.Top < this.Bottom && this.Top < value.Bottom;
|
return value.Left < this.Right && this.Left < value.Right && value.Top < this.Bottom && this.Top < value.Bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Offset(float, float)"/>
|
/// <inheritdoc cref="Rectangle.Offset(int, int)"/>
|
||||||
public void Offset(float offsetX, float offsetY) {
|
public void Offset(float offsetX, float offsetY) {
|
||||||
this.X += offsetX;
|
this.X += offsetX;
|
||||||
this.Y += offsetY;
|
this.Y += offsetY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Offset(Vector2)"/>
|
/// <inheritdoc cref="Rectangle.Offset(Point)"/>
|
||||||
public void Offset(Vector2 amount) {
|
public void Offset(Vector2 amount) {
|
||||||
this.X += amount.X;
|
this.X += amount.X;
|
||||||
this.Y += amount.Y;
|
this.Y += amount.Y;
|
||||||
|
@ -173,7 +173,7 @@ namespace MLEM.Misc {
|
||||||
/// <returns>The squared distance between the two rectangles.</returns>
|
/// <returns>The squared distance between the two rectangles.</returns>
|
||||||
public float DistanceSquared(RectangleF value) {
|
public float DistanceSquared(RectangleF value) {
|
||||||
// we calculate the distance based on the quadrants that the other rectangle is in using 8 cases:
|
// we calculate the distance based on the quadrants that the other rectangle is in using 8 cases:
|
||||||
// 1 7 4
|
// 1 7 4
|
||||||
// 3 T 6
|
// 3 T 6
|
||||||
// 2 8 5
|
// 2 8 5
|
||||||
var valueIsAbove = value.Bottom < this.Top;
|
var valueIsAbove = value.Bottom < this.Top;
|
||||||
|
@ -215,7 +215,13 @@ namespace MLEM.Misc {
|
||||||
return "{X:" + this.X + " Y:" + this.Y + " Width:" + this.Width + " Height:" + this.Height + "}";
|
return "{X:" + this.X + " Y:" + this.Y + " Width:" + this.Width + " Height:" + this.Height + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Rectangle.Deconstruct"/>
|
/// <summary>
|
||||||
|
/// Deconstruction method for <see cref="RectangleF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <param name="y"></param>
|
||||||
|
/// <param name="width"></param>
|
||||||
|
/// <param name="height"></param>
|
||||||
public void Deconstruct(out float x, out float y, out float width, out float height) {
|
public void Deconstruct(out float x, out float y, out float width, out float height) {
|
||||||
x = this.X;
|
x = this.X;
|
||||||
y = this.Y;
|
y = this.Y;
|
||||||
|
|
|
@ -158,7 +158,8 @@ namespace MLEM.Textures {
|
||||||
for (var x = 0F; x < rect.Width; x += width) {
|
for (var x = 0F; x < rect.Width; x += width) {
|
||||||
for (var y = 0F; y < rect.Height; y += height) {
|
for (var y = 0F; y < rect.Height; y += height) {
|
||||||
var size = new Vector2(Math.Min(rect.Width - x, width), Math.Min(rect.Height - y, height));
|
var size = new Vector2(Math.Min(rect.Width - x, width), Math.Min(rect.Height - y, height));
|
||||||
batch.Draw(texture.Region.Texture, new RectangleF(rect.Location + new Vector2(x, y), size), new Rectangle(src.Location, (size / patchScale).CeilCopy().ToPoint()), color, rotation, origin, effects, layerDepth);
|
var srcSize = (size / patchScale).CeilCopy().ToPoint();
|
||||||
|
batch.Draw(texture.Region.Texture, new RectangleF(rect.Location + new Vector2(x, y), size), new Rectangle(src.X, src.Y, srcSize.X, srcSize.Y), color, rotation, origin, effects, layerDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace MLEM.Textures {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of this texture region
|
/// The size of this texture region
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Point Size => this.Area.Size;
|
public Point Size => new Point(this.Area.Width, this.Area.Height);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The width of this texture region
|
/// The width of this texture region
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -51,8 +51,8 @@ namespace MLEM.Textures {
|
||||||
/// The <see cref="Pivot"/> of this texture region, but in absolute pixels rather than percentage.
|
/// The <see cref="Pivot"/> of this texture region, but in absolute pixels rather than percentage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector2 PivotPixels {
|
public Vector2 PivotPixels {
|
||||||
get => this.Pivot * this.Size.ToVector2();
|
get => this.Pivot * new Vector2(this.Size.X, this.Size.Y);
|
||||||
set => this.Pivot = value / this.Size.ToVector2();
|
set => this.Pivot = value / new Vector2(this.Size.X, this.Size.Y);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this texture region. By default, this name is <see cref="string.Empty"/>.
|
/// The name of this texture region. By default, this name is <see cref="string.Empty"/>.
|
||||||
|
@ -91,14 +91,14 @@ namespace MLEM.Textures {
|
||||||
/// <param name="texture">The texture to use</param>
|
/// <param name="texture">The texture to use</param>
|
||||||
/// <param name="uv">The top left corner of this area</param>
|
/// <param name="uv">The top left corner of this area</param>
|
||||||
/// <param name="size">The size of this area</param>
|
/// <param name="size">The size of this area</param>
|
||||||
public TextureRegion(Texture2D texture, Point uv, Point size) : this(texture, new Rectangle(uv, size)) {}
|
public TextureRegion(Texture2D texture, Point uv, Point size) : this(texture, new Rectangle(uv.X, uv.Y, size.X, size.Y)) {}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new texture region which is a sub-region of the given texture region
|
/// Creates a new texture region which is a sub-region of the given texture region
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="region">The texture region to create a sub-region of</param>
|
/// <param name="region">The texture region to create a sub-region of</param>
|
||||||
/// <param name="area">The new texture region area</param>
|
/// <param name="area">The new texture region area</param>
|
||||||
public TextureRegion(TextureRegion region, Rectangle area) : this(region, area.Location, area.Size) {}
|
public TextureRegion(TextureRegion region, Rectangle area) : this(region, area.Location, new Point(area.Width, area.Height)) {}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new texture region which is a sub-region of the given texture region
|
/// Creates a new texture region which is a sub-region of the given texture region
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace MLEM.Textures {
|
||||||
/// Returns the <see cref="TextureRegion"/> at this texture atlas' given region position
|
/// Returns the <see cref="TextureRegion"/> at this texture atlas' given region position
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="point">The region's x and y location</param>
|
/// <param name="point">The region's x and y location</param>
|
||||||
public TextureRegion this[Point point] => this[new Rectangle(point, new Point(1, 1))];
|
public TextureRegion this[Point point] => this[new Rectangle(point.X, point.Y, 1, 1)];
|
||||||
/// <inheritdoc cref="this[Point]"/>
|
/// <inheritdoc cref="this[Point]"/>
|
||||||
public TextureRegion this[int x, int y] => this[new Point(x, y)];
|
public TextureRegion this[int x, int y] => this[new Point(x, y)];
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/main/Media/Banner.png)
|
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/main/Media/Banner.png)
|
||||||
|
|
||||||
**MLEM Library for Extending MonoGame** is an addition to the game framework [MonoGame](https://www.monogame.net/) that provides extension methods, quality of life improvements and additional features like a ui system and easy input handling.
|
**MLEM Library for Extending MonoGame and FNA** is an addition to the game frameworks [MonoGame](https://www.monogame.net/) and [FNA](https://fna-xna.github.io/) that provides extension methods, quality of life improvements and additional features like a ui system and easy input handling.
|
||||||
|
|
||||||
# What next?
|
# What next?
|
||||||
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
||||||
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de)
|
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de/?q=mlem)
|
||||||
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
||||||
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
||||||
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/main/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/main/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/main/Demos.Android)
|
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/main/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/main/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/main/Demos.Android)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<PackageReference Include="MonoGame.Extended.Content.Pipeline" Version="3.8.0" />
|
<PackageReference Include="MonoGame.Extended.Content.Pipeline" Version="3.8.0" />
|
||||||
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0" />
|
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0" />
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
||||||
<PackageReference Include="FontStashSharp.MonoGame" Version="1.0.4" />
|
<PackageReference Include="FontStashSharp.MonoGame" Version="1.1.5" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
BIN
Tests/FNA/FAudio.dll
Normal file
BIN
Tests/FNA/FAudio.dll
Normal file
Binary file not shown.
BIN
Tests/FNA/FNA3D.dll
Normal file
BIN
Tests/FNA/FNA3D.dll
Normal file
Binary file not shown.
BIN
Tests/FNA/SDL2.dll
Normal file
BIN
Tests/FNA/SDL2.dll
Normal file
Binary file not shown.
BIN
Tests/FNA/libFAudio.0.dylib
Normal file
BIN
Tests/FNA/libFAudio.0.dylib
Normal file
Binary file not shown.
BIN
Tests/FNA/libFAudio.so.0
Normal file
BIN
Tests/FNA/libFAudio.so.0
Normal file
Binary file not shown.
BIN
Tests/FNA/libFNA3D.0.dylib
Normal file
BIN
Tests/FNA/libFNA3D.0.dylib
Normal file
Binary file not shown.
BIN
Tests/FNA/libFNA3D.so.0
Normal file
BIN
Tests/FNA/libFNA3D.so.0
Normal file
Binary file not shown.
BIN
Tests/FNA/libMoltenVK.dylib
Normal file
BIN
Tests/FNA/libMoltenVK.dylib
Normal file
Binary file not shown.
BIN
Tests/FNA/libSDL2-2.0.0.dylib
Normal file
BIN
Tests/FNA/libSDL2-2.0.0.dylib
Normal file
Binary file not shown.
BIN
Tests/FNA/libSDL2-2.0.so.0
Normal file
BIN
Tests/FNA/libSDL2-2.0.so.0
Normal file
Binary file not shown.
BIN
Tests/FNA/libtheorafile.dll
Normal file
BIN
Tests/FNA/libtheorafile.dll
Normal file
Binary file not shown.
BIN
Tests/FNA/libtheorafile.dylib
Normal file
BIN
Tests/FNA/libtheorafile.dylib
Normal file
Binary file not shown.
BIN
Tests/FNA/libtheorafile.so
Normal file
BIN
Tests/FNA/libtheorafile.so
Normal file
Binary file not shown.
BIN
Tests/FNA/libvulkan.1.dylib
Normal file
BIN
Tests/FNA/libvulkan.1.dylib
Normal file
Binary file not shown.
38
Tests/Tests.FNA.csproj
Normal file
38
Tests/Tests.FNA.csproj
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<VSTestLogger>nunit</VSTestLogger>
|
||||||
|
<RootNamespace>Tests</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Data\MLEM.Data.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
|
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="FNA/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<Link>%(Filename)%(Extension)</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
|
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
13
build.cake
13
build.cake
|
@ -9,13 +9,13 @@ var config = Argument("configuration", "Release");
|
||||||
|
|
||||||
Task("Prepare").Does(() => {
|
Task("Prepare").Does(() => {
|
||||||
DotNetCoreRestore("MLEM.sln");
|
DotNetCoreRestore("MLEM.sln");
|
||||||
|
|
||||||
if (branch != "release") {
|
if (branch != "release") {
|
||||||
var buildNum = EnvironmentVariable("BUILD_NUMBER");
|
var buildNum = EnvironmentVariable("BUILD_NUMBER");
|
||||||
if (buildNum != null)
|
if (buildNum != null)
|
||||||
version += "-" + buildNum;
|
version += "-" + buildNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteFiles("**/*.nupkg");
|
DeleteFiles("**/*.nupkg");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,13 +27,16 @@ Task("Build").IsDependentOn("Prepare").Does(() =>{
|
||||||
foreach (var project in GetFiles("**/MLEM*.csproj"))
|
foreach (var project in GetFiles("**/MLEM*.csproj"))
|
||||||
DotNetCoreBuild(project.FullPath, settings);
|
DotNetCoreBuild(project.FullPath, settings);
|
||||||
DotNetCoreBuild("Demos/Demos.csproj", settings);
|
DotNetCoreBuild("Demos/Demos.csproj", settings);
|
||||||
|
DotNetCoreBuild("Demos/Demos.FNA.csproj", settings);
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("Test").IsDependentOn("Build").Does(() => {
|
Task("Test").IsDependentOn("Build").Does(() => {
|
||||||
DotNetCoreTest("Tests/Tests.csproj", new DotNetCoreTestSettings {
|
var settings = new DotNetCoreTestSettings {
|
||||||
Configuration = config,
|
Configuration = config,
|
||||||
Collectors = {"XPlat Code Coverage"}
|
Collectors = {"XPlat Code Coverage"}
|
||||||
});
|
};
|
||||||
|
DotNetCoreTest("Tests/Tests.csproj", settings);
|
||||||
|
DotNetCoreTest("Tests/Tests.FNA.csproj", settings);
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("Pack").IsDependentOn("Test").Does(() => {
|
Task("Pack").IsDependentOn("Test").Does(() => {
|
||||||
|
@ -71,4 +74,4 @@ Task("Document").Does(() => {
|
||||||
Task("Default").IsDependentOn("Pack");
|
Task("Default").IsDependentOn("Pack");
|
||||||
Task("Publish").IsDependentOn("Push");
|
Task("Publish").IsDependentOn("Push");
|
||||||
|
|
||||||
RunTarget(target);
|
RunTarget(target);
|
||||||
|
|
Loading…
Reference in a new issue