├── .config └── dotnet-tools.json ├── .editorconfig ├── .githooks └── pre-push ├── .github ├── FUNDING.yml └── workflows │ ├── enforce-changelog.yml │ ├── main.yml │ └── web.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Demos.Android ├── .config │ └── dotnet-tools.json ├── Activity1.cs ├── AndroidManifest.xml ├── Demos.Android.csproj └── Resources │ ├── Drawable │ └── Icon.png │ └── Values │ └── Strings.xml ├── Demos.DesktopGL ├── .config │ └── dotnet-tools.json ├── Demos.DesktopGL.FNA.csproj ├── Demos.DesktopGL.KNI.csproj ├── Demos.DesktopGL.csproj ├── Icon.bmp ├── Icon.ico └── Program.cs ├── Demos.Web ├── App.razor ├── Demos.Web.KNI.csproj ├── MainLayout.razor ├── MainLayout.razor.css ├── Pages │ ├── Index.razor │ └── Index.razor.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── _Imports.razor └── wwwroot │ ├── Content │ └── .gitignore │ ├── css │ ├── app.css │ └── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── favicon.ico │ ├── index.html │ ├── js │ ├── decode.js │ └── decode.min.js │ └── kni.png ├── Demos ├── AnimationDemo.cs ├── Content │ ├── Content.mgcb │ ├── Fonts │ │ ├── CAYETANI.ttf │ │ ├── CAYETANO.ttf │ │ ├── CAYTANOB.ttf │ │ ├── JetBrainsMono-Regular.ttf │ │ ├── MonospacedFont.spritefont │ │ ├── Roboto.spritefont │ │ ├── RobotoBold.spritefont │ │ ├── RobotoBold.ttf │ │ ├── RobotoItalic.spritefont │ │ ├── RobotoItalic.ttf │ │ ├── RobotoRegular.ttf │ │ ├── TestFont.spritefont │ │ ├── TestFontBold.spritefont │ │ └── TestFontItalic.spritefont │ ├── Markdown.md │ └── Textures │ │ ├── Anim.png │ │ ├── Test.png │ │ └── Tree.png ├── Demo.cs ├── Demos.FNA.csproj ├── Demos.KNI.csproj ├── Demos.csproj ├── EasingsDemo.cs ├── GameImpl.cs ├── PathfindingDemo.cs ├── TextFormattingDemo.cs └── UiDemo.cs ├── Docs ├── .gitignore ├── articles │ ├── font_extensions.md │ ├── input.md │ ├── raw_content.md │ ├── sprite_animations.md │ ├── startup.md │ ├── text_formatting.md │ ├── tiled_extensions.md │ ├── toc.yml │ └── ui.md ├── docfx.json ├── favicon.ico ├── index.md ├── overrides │ ├── conceptual.extension.js │ └── public │ │ └── main.js └── toc.yml ├── FNA.Settings.props ├── LICENSE ├── MLEM.Data ├── Content │ ├── ContentExtensions.cs │ ├── JsonReader.cs │ ├── RawContentManager.cs │ ├── RawContentReader.cs │ ├── SongReader.cs │ ├── SoundEffectReader.cs │ ├── Texture2DReader.cs │ └── XmlReader.cs ├── DataTextureAtlas.cs ├── Json │ ├── Direction2Converter.cs │ ├── JsonConverters.cs │ ├── JsonTypeSafeGenericDataHolder.cs │ ├── JsonTypeSafeWrapper.cs │ ├── PointConverter.cs │ ├── RectangleConverter.cs │ ├── RectangleFConverter.cs │ ├── StaticJsonConverter.cs │ └── Vector2Converter.cs ├── MLEM.Data.FNA.csproj ├── MLEM.Data.KNI.csproj ├── MLEM.Data.csproj └── RuntimeTexturePacker.cs ├── MLEM.Extended ├── Font │ ├── GenericBitmapFont.cs │ └── GenericStashFont.cs ├── Graphics │ ├── SpriteBatchExtensions.cs │ └── TextureExtensions.cs ├── MLEM.Extended.FNA.csproj ├── MLEM.Extended.KNI.csproj ├── MLEM.Extended.csproj ├── Maths │ ├── NumberExtensions.cs │ └── RandomExtensions.cs └── Tiled │ ├── IndividualTiledMapRenderer.cs │ ├── LayerPosition.cs │ ├── LayerPositionF.cs │ ├── TiledExtensions.cs │ └── TiledMapCollisions.cs ├── MLEM.FNA.sln ├── MLEM.KNI.sln ├── MLEM.Startup ├── CoroutineEvents.cs ├── MLEM.Startup.FNA.csproj ├── MLEM.Startup.KNI.csproj ├── MLEM.Startup.csproj └── MlemGame.cs ├── MLEM.Templates ├── MLEM.Templates.csproj └── content │ ├── MLEM.Templates.DesktopGL │ ├── .config │ │ └── dotnet-tools.json │ ├── .template.config │ │ └── template.json │ ├── Content │ │ └── Content.mgcb │ ├── GameImpl.cs │ ├── Icon.bmp │ ├── Icon.ico │ ├── Program.cs │ └── TemplateNamespace.csproj │ └── MLEM.Templates.Portable │ ├── .template.config │ └── template.json │ ├── Content │ └── Content.mgcb │ ├── GameImpl.cs │ └── TemplateNamespace.csproj ├── MLEM.Ui ├── Anchor.cs ├── Elements │ ├── Button.cs │ ├── Checkbox.cs │ ├── Dropdown.cs │ ├── Element.cs │ ├── ElementHelper.cs │ ├── Group.cs │ ├── Image.cs │ ├── Panel.cs │ ├── Paragraph.cs │ ├── ProgressBar.cs │ ├── RadioButton.cs │ ├── ScissorGroup.cs │ ├── ScrollBar.cs │ ├── Slider.cs │ ├── SpriteAnimationImage.cs │ ├── SquishingGroup.cs │ ├── TextField.cs │ ├── Tooltip.cs │ └── VerticalSpace.cs ├── MLEM.Ui.FNA.csproj ├── MLEM.Ui.KNI.csproj ├── MLEM.Ui.csproj ├── Parsers │ ├── UiMarkdownParser.cs │ └── UiParser.cs ├── Style │ ├── StyleProp.cs │ ├── UiStyle.cs │ └── UntexturedStyle.cs ├── UiAnimation.cs ├── UiControls.cs ├── UiLayouter.cs ├── UiMetrics.cs └── UiSystem.cs ├── MLEM.sln ├── MLEM ├── Animations │ ├── SpriteAnimation.cs │ └── SpriteAnimationGroup.cs ├── Cameras │ └── Camera.cs ├── Font │ ├── CodePointSource.cs │ ├── GenericFont.cs │ └── GenericSpriteFont.cs ├── Formatting │ ├── Codes │ │ ├── AnimatedCode.cs │ │ ├── Code.cs │ │ ├── ColorCode.cs │ │ ├── FontCode.cs │ │ ├── ImageCode.cs │ │ ├── LinkCode.cs │ │ ├── OutlineCode.cs │ │ ├── ShadowCode.cs │ │ ├── SimpleEndCode.cs │ │ ├── SubSupCode.cs │ │ ├── UnderlineCode.cs │ │ └── WobblyCode.cs │ ├── TextAlignment.cs │ ├── TextFormatter.cs │ ├── Token.cs │ └── TokenizedString.cs ├── Graphics │ ├── AutoTiling.cs │ ├── ColorExtensions.cs │ ├── GraphicsExtensions.cs │ ├── SpriteBatchContext.cs │ ├── SpriteBatchExtensions.cs │ └── StaticSpriteBatch.cs ├── Input │ ├── GamepadExtensions.cs │ ├── GenericInput.cs │ ├── InputHandler.cs │ ├── Keybind.cs │ ├── KeysExtensions.cs │ ├── MouseExtensions.cs │ └── TextInput.cs ├── MLEM.FNA.csproj ├── MLEM.KNI.csproj ├── MLEM.csproj ├── Maths │ ├── Direction2.cs │ ├── Easings.cs │ ├── NumberExtensions.cs │ ├── Padding.cs │ ├── RandomExtensions.cs │ ├── RectangleF.cs │ ├── SeedSource.cs │ └── SingleRandom.cs ├── Misc │ ├── CollectionExtensions.cs │ ├── GenericDataHolder.cs │ └── MlemPlatform.cs ├── Pathfinding │ ├── AStar.cs │ ├── AStar2.cs │ └── AStar3.cs ├── Sound │ ├── SoundEffectInfo.cs │ ├── SoundEffectInstanceHandler.cs │ └── SoundExtensions.cs └── Textures │ ├── NinePatch.cs │ ├── TextureExtensions.cs │ ├── TextureRegion.cs │ └── UniformTextureAtlas.cs ├── Media ├── Banner.png ├── Formatting.png ├── Logo.png ├── Logo.svg └── Ui.gif ├── README.md ├── Sandbox ├── .config │ └── dotnet-tools.json ├── Content │ ├── Content.mgcb │ ├── Fonts │ │ ├── Cadman_Roman.otf │ │ ├── RegularTexture.png │ │ ├── Symbola-Emoji.ttf │ │ └── TestFont.spritefont │ ├── Test.json │ └── Textures │ │ ├── Furniture.atlas │ │ ├── Furniture.png │ │ └── Test.png ├── GameImpl.cs ├── Program.cs └── Sandbox.csproj ├── Tests ├── CameraTests.cs ├── CollectionTests.cs ├── Content │ ├── ConsecutiveSingleRandoms.txt │ ├── DistributedSingleRandoms.txt │ ├── TestFont.xnb │ ├── TestFontKni.xnb │ └── Texture.atlas ├── DataTests.cs ├── DataTextureAtlasTests.cs ├── DirectionTests.cs ├── FontTests.cs ├── KeybindTests.cs ├── NumberTests.cs ├── PathfindingTests.cs ├── SingleRandomTests.cs ├── TestGame.cs ├── Tests.FNA.csproj ├── Tests.FNA.runsettings ├── Tests.KNI.csproj ├── Tests.KNI.runsettings ├── Tests.csproj ├── Tests.runsettings ├── TexturePackerTests.cs └── UiTests.cs ├── ThirdParty └── Native │ ├── FAudio.dll │ ├── FNA3D.dll │ ├── SDL2.dll │ ├── libFAudio.0.dylib │ ├── libFAudio.so.0 │ ├── libFNA3D.0.dylib │ ├── libFNA3D.so.0 │ ├── libMoltenVK.dylib │ ├── libSDL2-2.0.0.dylib │ ├── libSDL2-2.0.so.0 │ ├── libtheorafile.dll │ ├── libtheorafile.dylib │ ├── libtheorafile.so │ └── libvulkan.1.dylib └── build.cake /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "cake.tool": { 6 | "version": "3.0.0", 7 | "commands": [ 8 | "dotnet-cake" 9 | ] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.githooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'pre-push' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } 3 | git lfs pre-push "$@" 4 | 5 | if ! git diff origin --name-status | grep -E -q "M\s+CHANGELOG.md"; then 6 | echo "The changelog was not updated. Please document your changes in CHANGELOG.md before pushing." 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: Ellpeck 2 | ko_fi: Ellpeck 3 | custom: https://ellpeck.de/support 4 | -------------------------------------------------------------------------------- /.github/workflows/enforce-changelog.yml: -------------------------------------------------------------------------------- 1 | on: pull_request 2 | jobs: 3 | enforce-changelog: 4 | runs-on: ubuntu-latest 5 | steps: 6 | - uses: dangoslen/changelog-enforcer@v3 7 | with: 8 | changeLogPath: CHANGELOG.md 9 | missingUpdateErrorMessage: | 10 | The changelog was not updated. Please document your changes in CHANGELOG.md. 11 | Run `git config core.hooksPath .githooks` to enable a git hook that ensures you updated the changelog before pushing. 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | jobs: 3 | build-publish: 4 | runs-on: ubuntu-latest 5 | steps: 6 | - name: Clone repository 7 | uses: actions/checkout@v4 8 | with: 9 | submodules: recursive 10 | - name: Setup .NET 11 | uses: actions/setup-dotnet@v3 12 | with: 13 | dotnet-version: '8.0.x' 14 | - name: Setup Java 15 | uses: actions/setup-java@v4 16 | with: 17 | java-version: '17' 18 | distribution: 'temurin' 19 | - name: Setup Android SDK 20 | uses: android-actions/setup-android@v3 21 | - name: Restore tools 22 | run: dotnet tool restore 23 | - name: Run Build 24 | run: dotnet cake --target Build --ref ${{ github.ref }} --buildNum ${{ github.run_number }} 25 | - name: Run Test 26 | uses: coactions/setup-xvfb@v1 27 | with: 28 | run: dotnet cake --target Test --ref ${{ github.ref }} --buildNum ${{ github.run_number }} 29 | - name: Run Publish 30 | run: dotnet cake --target Publish --ref ${{ github.ref }} --buildNum ${{ github.run_number }} 31 | env: 32 | NUGET_KEY: ${{ secrets.NUGET_KEY }} 33 | BAGET_KEY: ${{ secrets.BAGET_KEY }} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | bin 3 | obj 4 | packages 5 | *.user 6 | tools 7 | TestResults* 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "FNA"] 2 | path = ThirdParty/FNA 3 | url = https://github.com/FNA-XNA/FNA 4 | [submodule "FontStashSharp"] 5 | path = ThirdParty/FontStashSharp 6 | url = https://github.com/FontStashSharp/FontStashSharp 7 | [submodule "ThirdParty/MonoGame.Extended"] 8 | path = ThirdParty/MonoGame.Extended 9 | url = https://github.com/craftworkgames/MonoGame.Extended 10 | -------------------------------------------------------------------------------- /Demos.Android/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-mgcb": { 6 | "version": "3.8.1.303", 7 | "commands": [ 8 | "mgcb" 9 | ] 10 | }, 11 | "dotnet-mgcb-editor": { 12 | "version": "3.8.1.303", 13 | "commands": [ 14 | "mgcb-editor" 15 | ] 16 | }, 17 | "dotnet-mgcb-editor-linux": { 18 | "version": "3.8.1.303", 19 | "commands": [ 20 | "mgcb-editor-linux" 21 | ] 22 | }, 23 | "dotnet-mgcb-editor-windows": { 24 | "version": "3.8.1.303", 25 | "commands": [ 26 | "mgcb-editor-windows" 27 | ] 28 | }, 29 | "dotnet-mgcb-editor-mac": { 30 | "version": "3.8.1.303", 31 | "commands": [ 32 | "mgcb-editor-mac" 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Demos.Android/Activity1.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content; 3 | using Android.Content.PM; 4 | using Android.OS; 5 | using Android.Views; 6 | using Microsoft.Xna.Framework; 7 | using Microsoft.Xna.Framework.Input; 8 | using MLEM.Graphics; 9 | using MLEM.Misc; 10 | using Uri = Android.Net.Uri; 11 | 12 | namespace Demos.Android; 13 | 14 | [Activity( 15 | Label = "@string/app_name", 16 | MainLauncher = true, 17 | Icon = "@drawable/icon", 18 | AlwaysRetainTaskState = true, 19 | LaunchMode = LaunchMode.SingleInstance, 20 | ScreenOrientation = ScreenOrientation.UserLandscape, 21 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize 22 | )] 23 | public class Activity1 : AndroidGameActivity { 24 | 25 | private GameImpl game; 26 | private View view; 27 | 28 | protected override void OnCreate(Bundle bundle) { 29 | base.OnCreate(bundle); 30 | // render under notches 31 | if (Build.VERSION.SdkInt >= BuildVersionCodes.P) 32 | this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges; 33 | 34 | MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l)))); 35 | this.game = new GameImpl(); 36 | // reset MlemGame width and height to use device's aspect ratio 37 | this.game.GraphicsDeviceManager.ResetWidthAndHeight(this.game.Window); 38 | // disable mouse handling for android to make emulator behavior more coherent 39 | this.game.OnLoadContent += game => game.InputHandler.HandleMouse = false; 40 | // set the game to fullscreen to cause the status bar to be hidden 41 | this.game.GraphicsDeviceManager.IsFullScreen = true; 42 | this.view = this.game.Services.GetService(typeof(View)) as View; 43 | this.SetContentView(this.view); 44 | this.game.Run(); 45 | } 46 | 47 | public override void OnWindowFocusChanged(bool hasFocus) { 48 | base.OnWindowFocusChanged(hasFocus); 49 | // hide the status bar 50 | if (hasFocus) { 51 | #pragma warning disable CS0618 52 | // TODO this is deprecated, find out how to replace it 53 | this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.ImmersiveSticky | SystemUiFlags.LayoutStable | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen); 54 | #pragma warning restore CS0618 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Demos.Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Demos.Android/Demos.Android.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0-android 4 | 31 5 | Exe 6 | de.ellpeck.mlem.demos.android 7 | 100 8 | 1.0.0 9 | false 10 | false 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Demos.Android/Resources/Drawable/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos.Android/Resources/Drawable/Icon.png -------------------------------------------------------------------------------- /Demos.Android/Resources/Values/Strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MLEM Android Demos 5 | -------------------------------------------------------------------------------- /Demos.DesktopGL/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-mgcb": { 6 | "version": "3.8.1.303", 7 | "commands": [ 8 | "mgcb" 9 | ] 10 | }, 11 | "dotnet-mgcb-editor": { 12 | "version": "3.8.1.303", 13 | "commands": [ 14 | "mgcb-editor" 15 | ] 16 | }, 17 | "dotnet-mgcb-editor-linux": { 18 | "version": "3.8.1.303", 19 | "commands": [ 20 | "mgcb-editor-linux" 21 | ] 22 | }, 23 | "dotnet-mgcb-editor-windows": { 24 | "version": "3.8.1.303", 25 | "commands": [ 26 | "mgcb-editor-windows" 27 | ] 28 | }, 29 | "dotnet-mgcb-editor-mac": { 30 | "version": "3.8.1.303", 31 | "commands": [ 32 | "mgcb-editor-mac" 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Demos.DesktopGL/Demos.DesktopGL.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | Icon.ico 7 | MLEM Desktop Demos 8 | Demos.DesktopGL 9 | $(DefineConstants);FNA 10 | false 11 | 12 | DesktopGL 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | PreserveNewest 34 | %(Filename)%(Extension) 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Demos.DesktopGL/Demos.DesktopGL.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | Icon.ico 7 | MLEM Desktop Demos 8 | Demos.DesktopGL 9 | $(DefineConstants);KNI 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Demos.DesktopGL/Demos.DesktopGL.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | Icon.ico 7 | MLEM Desktop Demos 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Demos.DesktopGL/Icon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos.DesktopGL/Icon.bmp -------------------------------------------------------------------------------- /Demos.DesktopGL/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos.DesktopGL/Icon.ico -------------------------------------------------------------------------------- /Demos.DesktopGL/Program.cs: -------------------------------------------------------------------------------- 1 | using MLEM.Misc; 2 | #if !FNA && !KNI 3 | using Microsoft.Xna.Framework; 4 | #else 5 | using Microsoft.Xna.Framework.Input; 6 | #endif 7 | 8 | namespace Demos.DesktopGL; 9 | 10 | public static class Program { 11 | 12 | public static void Main() { 13 | #if FNA 14 | MlemPlatform.Current = new MlemPlatform.DesktopFna(a => TextInputEXT.TextInput += a); 15 | #else 16 | MlemPlatform.Current = new MlemPlatform.DesktopGl((w, c) => w.TextInput += c); 17 | #endif 18 | using var game = new GameImpl(); 19 | game.Run(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Demos.Web/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Not found 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /Demos.Web/Demos.Web.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | MLEM Web Demos 7 | Demos.Web 8 | $(DefineConstants);KNI 9 | false 10 | BlazorGL 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demos.Web/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 |
5 | @Body 6 |
7 |
8 | -------------------------------------------------------------------------------- /Demos.Web/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page 2 | { 3 | position: relative; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | 8 | main 9 | { 10 | flex: 1; 11 | } 12 | 13 | .sidebar 14 | { 15 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 16 | } 17 | 18 | .top-row 19 | { 20 | background-color: #f7f7f7; 21 | border-bottom: 1px solid #d6d5d5; 22 | justify-content: flex-end; 23 | height: 3.5rem; 24 | display: flex; 25 | align-items: center; 26 | } 27 | 28 | .top-row ::deep a, .top-row ::deep .btn-link 29 | { 30 | white-space: nowrap; 31 | margin-left: 1.5rem; 32 | text-decoration: none; 33 | } 34 | 35 | .top-row ::deep a:hover, .top-row ::deep .btn-link:hover 36 | { 37 | text-decoration: underline; 38 | } 39 | 40 | .top-row ::deep a:first-child 41 | { 42 | overflow: hidden; 43 | text-overflow: ellipsis; 44 | } 45 | 46 | @media (max-width: 640.98px) 47 | { 48 | .top-row:not(.auth) 49 | { 50 | display: none; 51 | } 52 | 53 | .top-row.auth 54 | { 55 | justify-content: space-between; 56 | } 57 | 58 | .top-row ::deep a, .top-row ::deep .btn-link 59 | { 60 | margin-left: 0; 61 | } 62 | } 63 | 64 | @media (min-width: 641px) 65 | { 66 | .page 67 | { 68 | flex-direction: row; 69 | } 70 | 71 | .sidebar 72 | { 73 | width: 250px; 74 | height: 100vh; 75 | position: sticky; 76 | top: 0; 77 | } 78 | 79 | .top-row 80 | { 81 | position: sticky; 82 | top: 0; 83 | z-index: 1; 84 | } 85 | 86 | .top-row.auth ::deep a:first-child 87 | { 88 | flex: 1; 89 | text-align: right; 90 | width: 0; 91 | } 92 | 93 | .top-row, article 94 | { 95 | padding-left: 2rem !important; 96 | padding-right: 1.5rem !important; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Demos.Web/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @page "/index.html" 3 | @inject IJSRuntime JsRuntime 4 | 5 | MLEM Web Demos 6 | 7 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /Demos.Web/Pages/Index.razor.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.JSInterop; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Input; 5 | using MLEM.Formatting; 6 | using MLEM.Misc; 7 | using MLEM.Ui; 8 | using MLEM.Ui.Elements; 9 | 10 | namespace Demos.Web.Pages; 11 | 12 | public partial class Index { 13 | 14 | private GameImpl game; 15 | 16 | protected override async Task OnAfterRenderAsync(bool firstRender) { 17 | await base.OnAfterRenderAsync(firstRender); 18 | if (firstRender) 19 | await this.JsRuntime.InvokeAsync("initRenderJS", DotNetObjectReference.Create(this)); 20 | } 21 | 22 | [JSInvokable] 23 | public void TickDotNet() { 24 | if (this.game == null) { 25 | MlemPlatform.Current = new MlemPlatform.DesktopGl((w, c) => w.TextInput += c); 26 | this.game = new GameImpl(); 27 | this.game.OnLoadContent += g => g.UiSystem.Add("WebDisclaimer", new Paragraph(Anchor.BottomCenter, 1, "The Web version of MLEM's demos is still in development.\nFor the best experience, please try their Desktop and Android versions instead.") { 28 | PositionOffset = new Vector2(0, 1), 29 | Alignment = TextAlignment.Center, 30 | TextScale = 0.075F 31 | }); 32 | this.game.Run(); 33 | } 34 | this.game.Tick(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Demos.Web/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Components.Web; 5 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Demos.Web; 9 | 10 | internal static class Program { 11 | 12 | private static async Task Main(string[] args) { 13 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 14 | builder.RootComponents.Add("#app"); 15 | builder.RootComponents.Add("head::after"); 16 | builder.Services.AddScoped(_ => new HttpClient { 17 | BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 18 | }); 19 | await builder.Build().RunAsync(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Demos.Web/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:56897", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "Demos.Web": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 16 | "applicationUrl": "http://localhost:5259", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demos.Web/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 8 | @using Microsoft.JSInterop 9 | @using nkast.Wasm.Canvas 10 | @using Demos.Web 11 | -------------------------------------------------------------------------------- /Demos.Web/wwwroot/Content/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /Demos.Web/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos.Web/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Demos.Web/wwwroot/kni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos.Web/wwwroot/kni.png -------------------------------------------------------------------------------- /Demos/Content/Fonts/CAYETANI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/CAYETANI.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/CAYETANO.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/CAYETANO.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/CAYTANOB.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/CAYTANOB.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/JetBrainsMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/JetBrainsMono-Regular.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/MonospacedFont.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | JetBrainsMono-Regular.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/Roboto.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | RobotoRegular.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/RobotoBold.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | RobotoBold.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/RobotoBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/RobotoBold.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/RobotoItalic.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | RobotoItalic.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/RobotoItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/RobotoItalic.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/RobotoRegular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Fonts/RobotoRegular.ttf -------------------------------------------------------------------------------- /Demos/Content/Fonts/TestFont.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | CAYETANO.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/TestFontBold.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | CAYTANOB.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Fonts/TestFontItalic.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | CAYETANI.ttf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/Content/Markdown.md: -------------------------------------------------------------------------------- 1 | # H1 2 | ## H2 3 | ### H3 4 | #### H4 5 | ##### H5 6 | ###### H6 7 | 8 | Italics with *asterisks* or _underscores_. 9 | Bold with **asterisks** or __underscores__. 10 | Strikethrough with ~~two tildes~~. 11 | 12 | [I'm an inline-style link](https://www.google.com) 13 | 14 | 15 | Logo: 16 | ![](https://raw.githubusercontent.com/Ellpeck/MLEM/main/Media/Logo.png) 17 | 18 | Wide logo: 19 | ![](https://raw.githubusercontent.com/Ellpeck/MLEM/main/Media/Banner.png) 20 | 21 | Some `inline code` right here 22 | 23 | ```js 24 | function codeBlock() { 25 | 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /Demos/Content/Textures/Anim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Textures/Anim.png -------------------------------------------------------------------------------- /Demos/Content/Textures/Test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Textures/Test.png -------------------------------------------------------------------------------- /Demos/Content/Textures/Tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Demos/Content/Textures/Tree.png -------------------------------------------------------------------------------- /Demos/Demo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | using MLEM.Input; 4 | using MLEM.Startup; 5 | using MLEM.Ui; 6 | using MLEM.Ui.Elements; 7 | 8 | namespace Demos { 9 | public class Demo { 10 | 11 | public readonly MlemGame Game; 12 | public SpriteBatch SpriteBatch => this.Game.SpriteBatch; 13 | public GraphicsDevice GraphicsDevice => this.Game.GraphicsDevice; 14 | public InputHandler InputHandler => this.Game.InputHandler; 15 | public UiSystem UiSystem => this.Game.UiSystem; 16 | public Element UiRoot => this.UiSystem.Get("DemoUi").Element; 17 | 18 | public Demo(MlemGame game) { 19 | this.Game = game; 20 | } 21 | 22 | public virtual void LoadContent() {} 23 | 24 | public virtual void Update(GameTime time) {} 25 | 26 | public virtual void DoDraw(GameTime time) {} 27 | 28 | public virtual void Clear() {} 29 | 30 | public static T LoadContent(string name) { 31 | return MlemGame.LoadContent(name); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Demos/Demos.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | Demos 6 | $(DefineConstants);FNA 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Demos/Demos.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | Demos 6 | $(DefineConstants);KNI 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | 20 | 21 | all 22 | 23 | 24 | all 25 | 26 | 27 | all 28 | 29 | 30 | all 31 | 32 | 33 | all 34 | 35 | 36 | all 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Demos/Demos.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | all 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Demos/EasingsDemo.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using MLEM.Graphics; 6 | using MLEM.Maths; 7 | using MLEM.Startup; 8 | using MLEM.Ui; 9 | using MLEM.Ui.Elements; 10 | 11 | namespace Demos { 12 | public class EasingsDemo : Demo { 13 | 14 | private static readonly FieldInfo[] EasingFields = typeof(Easings) 15 | .GetFields(BindingFlags.Public | BindingFlags.Static).ToArray(); 16 | private static readonly Easings.Easing[] Easings = EasingsDemo.EasingFields 17 | .Select(f => (Easings.Easing) f.GetValue(null)).ToArray(); 18 | private Group group; 19 | private int current; 20 | private float progress; 21 | 22 | public EasingsDemo(MlemGame game) : base(game) {} 23 | 24 | public override void LoadContent() { 25 | base.LoadContent(); 26 | 27 | this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false}; 28 | this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") { 29 | OnPressed = e => { 30 | this.current = (this.current + 1) % EasingsDemo.Easings.Length; 31 | this.progress = 0; 32 | } 33 | }); 34 | this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingsDemo.EasingFields[this.current].Name, true)); 35 | this.UiRoot.AddChild(this.group); 36 | } 37 | 38 | public override void Clear() { 39 | this.group.Parent.RemoveChild(this.group); 40 | } 41 | 42 | public override void DoDraw(GameTime time) { 43 | this.GraphicsDevice.Clear(Color.CornflowerBlue); 44 | base.DoDraw(time); 45 | 46 | this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullCounterClockwise); 47 | var view = this.GraphicsDevice.Viewport; 48 | 49 | // graph the easing function 50 | var graphEase = EasingsDemo.Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3); 51 | for (var x = 0; x < view.Width; x++) { 52 | var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4); 53 | this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Green); 54 | } 55 | 56 | // draw a little dot to show what it would look like 57 | this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1; 58 | var dotEase = EasingsDemo.Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4); 59 | var pos = new RectangleF(view.Width / 2 - 4, view.Height - 20 - dotEase(this.progress), 8, 8); 60 | this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red); 61 | 62 | this.SpriteBatch.End(); 63 | } 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | api -------------------------------------------------------------------------------- /Docs/articles/font_extensions.md: -------------------------------------------------------------------------------- 1 | # Font Extensions 2 | 3 | The **MLEM** base package features several additional font manipulation methods, including line splitting and text truncating. These abilities can be accessed through generic fonts. 4 | 5 | ## Generic fonts 6 | MLEM features the `GenericFont` class along with a `GenericSpriteFont` implementation. This is used by the **MLEM.Ui** package, but it can also be used separately to have more control over font rendering. 7 | 8 | Additionally, the **MLEM.Extended** package provides the following generic fonts: 9 | - `GenericBitmapFont`, which uses [MonoGame.Extended](http://www.monogameextended.net/)'s `BitmapFont` 10 | - `GenericStashFont`, which uses [FontStashSharp](https://github.com/rds1983/FontStashSharp)'s fonts 11 | 12 | ### Creating a generic font 13 | To create a generic font, simply create an instance of the desired generic font class when loading your game: 14 | ```cs 15 | // Using MonoGame SpriteFonts 16 | var spriteFont = new GenericSpriteFont(this.Content.Load("Fonts/ExampleFont")); 17 | ``` 18 | 19 | ## Line splitting 20 | Using generic fonts, a long line of text can be split into multiple lines based on a maximum width in pixels. The split text that is returned is delimited by `\n` (newline characters). 21 | ```cs 22 | var split = spriteFont.SplitString("This is a really long line of text [...]", width: 100, scale: 1); 23 | spriteFont.DrawString(this.SpriteBatch, split, new Vector2(10, 10), Color.White); 24 | ``` 25 | 26 | Alternatively, the `SplitStringSeparate` method returns a collection of strings, where each entry represents a place where a split has been introduced. Using this method, you can differentiate between pre-existing newline characters and newly introduced ones. 27 | ```cs 28 | var split = spriteFont.SplitStringSeparate("This is a line of text that contains\nnewline characters!", width: 10, scale: 1); 29 | // returns something like ["This is a line of ", "text that contains\nnewline characters!"] 30 | ``` 31 | 32 | ## Truncating 33 | Using generic fonts, a long line of text can also be truncated to fit a certain width in pixels. The remaining text that doesn't fit will simply be chopped off of the end (or start) of the string. 34 | ```cs 35 | // Truncate from the front 36 | var truncFront = spriteFont.TruncateString("This is a really long line of text [...]", width: 100, fromBack: false, scale: 1); 37 | // Truncate from the back 38 | var truncBack = spriteFont.TruncateString("This is a really long line of text [...]", width: 100, fromBack: true, scale: 1); 39 | ``` 40 | -------------------------------------------------------------------------------- /Docs/articles/sprite_animations.md: -------------------------------------------------------------------------------- 1 | # Sprite Animations 2 | 3 | The **MLEM** package contains a simple sprite animation system that features different-length frames as well as conditioned animations and grouping. 4 | 5 | ## Using animations 6 | You can create an animation like so: 7 | ```cs 8 | var texture = this.Content.Load("Textures/TestSprite"); 9 | 10 | // Two-frame animation using a frame time of 0.5 seconds 11 | var anim1 = new SpriteAnimation(timePerFrame: 0.5F, 12 | new TextureRegion(texture, 0, 0, 16, 16), new TextureRegion(texture, 16, 0, 16, 16)); 13 | 14 | // Three-frame animation with varying frame times 15 | var anim2 = new SpriteAnimation( 16 | new AnimationFrame(new TextureRegion(texture, 0, 0, 16, 16), 0.25F), 17 | new AnimationFrame(new TextureRegion(texture, 16, 0, 16, 16), 0.5F), 18 | new AnimationFrame(new TextureRegion(texture, 32, 0, 16, 16), 0.3F) 19 | ); 20 | ``` 21 | 22 | Additionally, you have to update the animation every update frame in your game's `Update` method: 23 | ```cs 24 | anim1.Update(gameTime); 25 | ``` 26 | 27 | You can draw the animation's current frame as follows: 28 | ```cs 29 | this.SpriteBatch.Draw(anim1.CurrentRegion, new Vector2(10, 10), Color.White); 30 | ``` 31 | 32 | ## Using animation groups 33 | Animation groups consist of multiple animations. Each animation in a group has a condition that determines if it should currently be playing. 34 | 35 | You can create an animation group and add animations to it like so: 36 | ```cs 37 | var group = new SpriteAnimationGroup(); 38 | // Animation 1 should always play 39 | group.Add(anim1, () => true, priority: 0); 40 | // Animation 2 should play if the game has been running for 10 seconds or more 41 | // Since its priority is higher than anim1's, it will be the one that plays when its condition is true 42 | group.Add(anim2, () => gameTime.TotalGameTime.TotalSeconds >= 10, priority: 1); 43 | ``` 44 | 45 | As with regular animations, an animation group also has to be updated each update frame: 46 | ```cs 47 | group.Update(gameTime); 48 | ``` 49 | 50 | You can draw the group's current frame as follows: 51 | ```cs 52 | this.SpriteBatch.Draw(group.CurrentRegion, new Vector2(10, 10), Color.White); 53 | ``` 54 | -------------------------------------------------------------------------------- /Docs/articles/startup.md: -------------------------------------------------------------------------------- 1 | # MLEM.Startup 2 | 3 | **MLEM.Startup** is a simple package that contains a `MlemGame` class which extends MonoGame's `Game`. This class contains additional properties that most games created with MonoGame and MLEM will have: 4 | - An [InputHandler](xref:MLEM.Input.InputHandler) 5 | - A `SpriteBatch` and `GraphicsDeviceManager` 6 | - A [UiSystem](ui.md) 7 | - Some delegate callbacks for loading, updating and drawing that allow additional code to be executed from outside the game class 8 | 9 | Additionally, it comes with the [Coroutine](https://www.nuget.org/packages/Coroutine) package preinstalled. The Coroutine package allows creating and running operations alongside the regular game loop without asynchrony. It comes with a `CoroutineEvents` class that contains two types of events that are automatically invoked by `MlemGame`. For more information on how this is useful, see [the Coroutine README](https://github.com/Ellpeck/Coroutine/blob/main/README.md). 10 | 11 | You are not required to use MLEM.Startup when using MLEM, but it can be especially helpful for small projects, like game jam games. You can also check out `MlemGame`'s [source](https://github.com/Ellpeck/MLEM/blob/main/MLEM.Startup/MlemGame.cs) to see how its bootstrapping is implemented. 12 | -------------------------------------------------------------------------------- /Docs/articles/tiled_extensions.md: -------------------------------------------------------------------------------- 1 | # Tiled Extensions 2 | 3 | If you're using [MonoGame.Extended](https://github.com/craftworkgames/MonoGame.Extended)'s [Tiled](https://www.mapeditor.org/) map editor support, you can use the **MLEM.Extended** package alongside that to enhance your tilemap experience. 4 | 5 | ## Extensions 6 | There are several extensions to tiled maps, tilesets and tiles, including, but not limited to: 7 | - The ability to get a tileset tile from a tile easily 8 | - The ability to get tile and tile map properties easily 9 | - Getting multiple tiles and objects at a location or in an area 10 | 11 | All of these extension methods can be found in the [TiledExtensions](https://github.com/Ellpeck/MLEM/blob/main/MLEM.Extended/Tiled/TiledExtensions.cs) class. 12 | 13 | ## Tiled map collisions 14 | MLEM.Extended includes a very easy way to set up collisions within your tiled maps through the use of [tile collisions](https://doc.mapeditor.org/en/stable/manual/editing-tilesets/#tile-collision-editor). 15 | 16 | To get this set up, you simply have to add bounding rectangles to your tilesets within the Tiled editor. Then, you can query collisions like so: 17 | ```cs 18 | // Creating the collision system for a tiled map 19 | var collisions = new TiledMapCollisions(myMap); 20 | 21 | // Getting a list of collisions for an area 22 | var tiles = collisions.GetCollidingTiles(new RectangleF(2, 2, 3.5F, 3.5F)); 23 | 24 | // Checking if an area is colliding 25 | var colliding = collisions.IsColliding(new RectangleF(4, 4, 1, 1)); 26 | ``` 27 | 28 | ### Collision coordinate system 29 | The coordinate system of these tiled collisions functions based on *percentages* rather than absolute pixel coordinates. The collision system sees each tile as being *one unit by one unit* big. 30 | 31 | This means that, to check if the tile at tile coordinate `6, 10` contains any collisions, the following rectangle has to be used: 32 | ```cs 33 | var tiles = collisions.GetCollidingTiles(new RectangleF(6, 10, 1, 1)); 34 | ``` 35 | If the tile at that location is `16x16` pixels big, and it has a single collision box at pixels `4, 4` that is `8x8` pixels big, then the following code prints out its percentaged coordinates: `X: 0.25, Y: 0.25, Width: 0.5, Height: 0.5`. 36 | ```cs 37 | foreach (var tile in tiles) 38 | Console.WriteLine(tile.Collisions[0]); 39 | ``` 40 | -------------------------------------------------------------------------------- /Docs/articles/toc.yml: -------------------------------------------------------------------------------- 1 | - name: MLEM 2 | - name: Font Extensions 3 | href: font_extensions.md 4 | - name: Text Formatting 5 | href: text_formatting.md 6 | - name: Input Handler 7 | href: input.md 8 | - name: Sprite Animations 9 | href: sprite_animations.md 10 | 11 | - name: MLEM.Ui 12 | - name: Introduction to MLEM.Ui 13 | href: ui.md 14 | 15 | - name: MLEM.Extended 16 | - name: Tiled Extensions 17 | href: tiled_extensions.md 18 | 19 | - name: MLEM.Data 20 | - name: Raw Content Manager 21 | href: raw_content.md 22 | 23 | - name: MLEM.Startup 24 | - name: MLEM.Startup 25 | href: startup.md 26 | -------------------------------------------------------------------------------- /Docs/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "src": "../", 7 | "files": [ 8 | "**/MLEM**.csproj" 9 | ], 10 | "exclude": [ 11 | "**.FNA.**", 12 | "**.KNI.**" 13 | ] 14 | } 15 | ], 16 | "dest": "api", 17 | "properties": { 18 | "TargetFramework": "net8.0" 19 | } 20 | } 21 | ], 22 | "build": { 23 | "content": [ 24 | { 25 | "files": [ 26 | "articles/**.md", 27 | "articles/**/toc.yml", 28 | "toc.yml", 29 | "*.md", 30 | "api/**.yml" 31 | ] 32 | }, 33 | { 34 | "files": [ 35 | "CHANGELOG.md" 36 | ], 37 | "src": ".." 38 | } 39 | ], 40 | "resource": [ 41 | { 42 | "files": [ 43 | "favicon.ico" 44 | ] 45 | }, 46 | { 47 | "files": [ 48 | "*" 49 | ], 50 | "src": "../Media" 51 | } 52 | ], 53 | "globalMetadata": { 54 | "_appTitle": "MLEM Documentation", 55 | "_appLogoPath": "Logo.svg", 56 | "_appFooter": "© 2019-2024 EllpeckImpressumPrivacyStatus", 57 | "_enableSearch": true 58 | }, 59 | "dest": "_site", 60 | "template": [ 61 | "default", 62 | "modern", 63 | "overrides" 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Docs/favicon.ico -------------------------------------------------------------------------------- /Docs/index.md: -------------------------------------------------------------------------------- 1 | [!INCLUDE [](../README.md)] 2 | -------------------------------------------------------------------------------- /Docs/overrides/conceptual.extension.js: -------------------------------------------------------------------------------- 1 | exports.preTransform = function (model) { 2 | if (model._path.includes("index")) { 3 | // reduce header levels by 1 to allow for TOC navigation 4 | for (let i = 5; i >= 1; i--) 5 | model.conceptual = model.conceptual.replaceAll(` 2 | 3 | 4 | AnyCPU 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2024 Ellpeck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MLEM.Data/Content/JsonReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Newtonsoft.Json; 4 | 5 | namespace MLEM.Data.Content { 6 | /// 7 | public class JsonReader : RawContentReader { 8 | 9 | /// 10 | public override bool CanRead(Type t) { 11 | return true; 12 | } 13 | 14 | /// 15 | public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) { 16 | using (var reader = new JsonTextReader(new StreamReader(stream))) 17 | return manager.GetJsonSerializer().Deserialize(reader); 18 | } 19 | 20 | /// 21 | public override string[] GetFileExtensions() { 22 | return new[] {"json", "json5", "jsonc"}; 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MLEM.Data/Content/RawContentReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.Xna.Framework.Content; 4 | 5 | namespace MLEM.Data.Content { 6 | /// 7 | /// Represents a way for any kind of raw content file to be read using a 8 | /// 9 | public abstract class RawContentReader { 10 | 11 | /// 12 | /// Returns if the given type can be loaded by this content reader 13 | /// 14 | /// The type of asset 15 | /// If the type can be loaded by this content reader 16 | public abstract bool CanRead(Type t); 17 | 18 | /// 19 | /// Reads the content file from disk and returns it. 20 | /// 21 | /// The that is loading the asset 22 | /// The full path to the asset, starting from the 23 | /// A stream that leads to this asset 24 | /// The type of asset to load 25 | /// If this asset is being reloaded, this value contains the previous version of the asset. 26 | /// The loaded asset 27 | public abstract object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing); 28 | 29 | /// 30 | /// Represents the list of file extensions that this reader can read from. 31 | /// 32 | /// The list of valid extensions 33 | public abstract string[] GetFileExtensions(); 34 | 35 | } 36 | 37 | /// 38 | public abstract class RawContentReader : RawContentReader { 39 | 40 | /// 41 | public override bool CanRead(Type t) { 42 | return typeof(T).IsAssignableFrom(t); 43 | } 44 | 45 | /// 46 | public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) { 47 | return this.Read(manager, assetPath, stream, (T) existing); 48 | } 49 | 50 | /// 51 | /// Reads the content file that is represented by our generic type from disk. 52 | /// 53 | /// The that is loading the asset 54 | /// The full path to the asset, starting from the 55 | /// A stream that leads to this asset 56 | /// If this asset is being reloaded, this value contains the previous version of the asset. 57 | /// The loaded asset 58 | protected abstract T Read(RawContentManager manager, string assetPath, Stream stream, T existing); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /MLEM.Data/Content/SongReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.Xna.Framework.Media; 4 | 5 | namespace MLEM.Data.Content { 6 | /// 7 | public class SongReader : RawContentReader { 8 | 9 | /// 10 | protected override Song Read(RawContentManager manager, string assetPath, Stream stream, Song existing) { 11 | return Song.FromUri(Path.GetFileNameWithoutExtension(assetPath), new Uri(assetPath)); 12 | } 13 | 14 | /// 15 | public override string[] GetFileExtensions() { 16 | return new[] {"ogg", "wav", "mp3"}; 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MLEM.Data/Content/SoundEffectReader.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.Xna.Framework.Audio; 3 | 4 | namespace MLEM.Data.Content { 5 | /// 6 | public class SoundEffectReader : RawContentReader { 7 | 8 | /// 9 | protected override SoundEffect Read(RawContentManager manager, string assetPath, Stream stream, SoundEffect existing) { 10 | return SoundEffect.FromStream(stream); 11 | } 12 | 13 | /// 14 | public override string[] GetFileExtensions() { 15 | return new[] {"wav"}; 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MLEM.Data/Content/Texture2DReader.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Textures; 5 | 6 | namespace MLEM.Data.Content { 7 | /// 8 | public class Texture2DReader : RawContentReader { 9 | 10 | /// 11 | protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) { 12 | #if !FNA && !KNI 13 | if (existing != null) { 14 | existing.Reload(stream); 15 | return existing; 16 | } 17 | #endif 18 | 19 | // premultiply the texture's color to be in line with the pipeline's texture reader 20 | using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream)) 21 | return texture.PremultipliedCopy(); 22 | } 23 | 24 | /// 25 | public override string[] GetFileExtensions() { 26 | return new[] {"png", "bmp", "gif", "jpg", "tif", "dds"}; 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MLEM.Data/Content/XmlReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Xml.Serialization; 4 | 5 | namespace MLEM.Data.Content { 6 | /// 7 | public class XmlReader : RawContentReader { 8 | 9 | /// 10 | public override bool CanRead(Type t) { 11 | return true; 12 | } 13 | 14 | /// 15 | #if NET6_0_OR_GREATER 16 | [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026", 17 | Justification = "RawContentManager does not support XmlReader in a trimmed or AOT context, so this method is not expected to be called.")] 18 | #endif 19 | public override object Read(RawContentManager manager, string assetPath, Stream stream, Type t, object existing) { 20 | return new XmlSerializer(t).Deserialize(stream); 21 | } 22 | 23 | /// 24 | public override string[] GetFileExtensions() { 25 | return new[] {"xml"}; 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MLEM.Data/Json/Direction2Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MLEM.Maths; 3 | using Newtonsoft.Json; 4 | 5 | namespace MLEM.Data.Json { 6 | /// 7 | /// Converts a to and from JSON 8 | /// 9 | public class Direction2Converter : JsonConverter { 10 | 11 | /// Writes the JSON representation of the object. 12 | /// The to write to. 13 | /// The value. 14 | /// The calling serializer. 15 | public override void WriteJson(JsonWriter writer, Direction2 value, JsonSerializer serializer) { 16 | writer.WriteValue(value.ToString()); 17 | } 18 | 19 | /// Reads the JSON representation of the object. 20 | /// The to read from. 21 | /// Type of the object. 22 | /// The existing value of object being read. If there is no existing value then null will be used. 23 | /// The existing value has a value. 24 | /// The calling serializer. 25 | /// The object value. 26 | public override Direction2 ReadJson(JsonReader reader, Type objectType, Direction2 existingValue, bool hasExistingValue, JsonSerializer serializer) { 27 | Enum.TryParse(reader.Value.ToString(), out var dir); 28 | return dir; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MLEM.Data/Json/JsonConverters.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace MLEM.Data.Json { 4 | /// 5 | /// A helper class that stores all of the types that are part of MLEM.Data. 6 | /// 7 | public class JsonConverters { 8 | 9 | /// 10 | /// An array of all of the s that are part of MLEM.Data 11 | /// 12 | public static readonly JsonConverter[] Converters = { 13 | new Direction2Converter(), 14 | new PointConverter(), 15 | new RectangleConverter(), 16 | new RectangleFConverter(), 17 | new Vector2Converter() 18 | }; 19 | 20 | /// 21 | /// Adds all of the objects that are part of MLEM.Data to the given 22 | /// 23 | /// The serializer to add the converters to 24 | /// The given serializer, for chaining 25 | public static JsonSerializer AddAll(JsonSerializer serializer) { 26 | foreach (var converter in JsonConverters.Converters) 27 | serializer.Converters.Add(converter); 28 | return serializer; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MLEM.Data/Json/JsonTypeSafeGenericDataHolder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MLEM.Misc; 3 | using Newtonsoft.Json; 4 | 5 | namespace MLEM.Data.Json { 6 | /// 7 | /// An represents an object that can hold generic key-value based data. 8 | /// This class uses for each object stored to ensure that objects with a custom get deserialized as an instance of their original type if is not set to . 9 | /// Note that, using , adding instances directly is also possible. 10 | /// 11 | #if NET7_0_OR_GREATER 12 | [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The native code for instantiation of JsonTypeSafeWrapper instances might not be available at runtime.")] 13 | #endif 14 | public class JsonTypeSafeGenericDataHolder : IGenericDataHolder { 15 | 16 | private static readonly string[] EmptyStrings = new string[0]; 17 | 18 | [JsonProperty] 19 | private Dictionary data; 20 | 21 | /// 22 | public void SetData(string key, T data) { 23 | if (EqualityComparer.Default.Equals(data, default)) { 24 | if (this.data != null) 25 | this.data.Remove(key); 26 | } else { 27 | if (this.data == null) 28 | this.data = new Dictionary(); 29 | this.data[key] = JsonTypeSafeWrapper.Of(data); 30 | } 31 | } 32 | 33 | /// 34 | public T GetData(string key) { 35 | if (this.data != null && this.data.TryGetValue(key, out var val)) 36 | return (T) val.Value; 37 | return default; 38 | } 39 | 40 | /// 41 | public IEnumerable GetDataKeys() { 42 | if (this.data == null) 43 | return JsonTypeSafeGenericDataHolder.EmptyStrings; 44 | return this.data.Keys; 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MLEM.Data/Json/PointConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Microsoft.Xna.Framework; 4 | using Newtonsoft.Json; 5 | 6 | namespace MLEM.Data.Json { 7 | /// 8 | /// Converts a to and from JSON 9 | /// 10 | public class PointConverter : JsonConverter { 11 | 12 | /// Writes the JSON representation of the object. 13 | /// The to write to. 14 | /// The value. 15 | /// The calling serializer. 16 | public override void WriteJson(JsonWriter writer, Point value, JsonSerializer serializer) { 17 | writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture)); 18 | } 19 | 20 | /// Reads the JSON representation of the object. 21 | /// The to read from. 22 | /// Type of the object. 23 | /// The existing value of object being read. If there is no existing value then null will be used. 24 | /// The existing value has a value. 25 | /// The calling serializer. 26 | /// The object value. 27 | public override Point ReadJson(JsonReader reader, Type objectType, Point existingValue, bool hasExistingValue, JsonSerializer serializer) { 28 | var value = reader.Value.ToString().Split(' '); 29 | return new Point(int.Parse(value[0], CultureInfo.InvariantCulture), int.Parse(value[1], CultureInfo.InvariantCulture)); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MLEM.Data/Json/RectangleConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Microsoft.Xna.Framework; 4 | using Newtonsoft.Json; 5 | 6 | namespace MLEM.Data.Json { 7 | /// 8 | /// Converts a to and from JSON 9 | /// 10 | public class RectangleConverter : JsonConverter { 11 | 12 | /// Writes the JSON representation of the object. 13 | /// The to write to. 14 | /// The value. 15 | /// The calling serializer. 16 | public override void WriteJson(JsonWriter writer, Rectangle value, JsonSerializer serializer) { 17 | writer.WriteValue( 18 | value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " + 19 | value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture)); 20 | } 21 | 22 | /// Reads the JSON representation of the object. 23 | /// The to read from. 24 | /// Type of the object. 25 | /// The existing value of object being read. If there is no existing value then null will be used. 26 | /// The existing value has a value. 27 | /// The calling serializer. 28 | /// The object value. 29 | public override Rectangle ReadJson(JsonReader reader, Type objectType, Rectangle existingValue, bool hasExistingValue, JsonSerializer serializer) { 30 | var value = reader.Value.ToString().Split(' '); 31 | return new Rectangle( 32 | int.Parse(value[0], CultureInfo.InvariantCulture), int.Parse(value[1], CultureInfo.InvariantCulture), 33 | int.Parse(value[2], CultureInfo.InvariantCulture), int.Parse(value[3], CultureInfo.InvariantCulture)); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MLEM.Data/Json/RectangleFConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using MLEM.Maths; 4 | using Newtonsoft.Json; 5 | 6 | namespace MLEM.Data.Json { 7 | /// 8 | /// Converts a to and from JSON 9 | /// 10 | public class RectangleFConverter : JsonConverter { 11 | 12 | /// Writes the JSON representation of the object. 13 | /// The to write to. 14 | /// The value. 15 | /// The calling serializer. 16 | public override void WriteJson(JsonWriter writer, RectangleF value, JsonSerializer serializer) { 17 | writer.WriteValue( 18 | value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture) + " " + 19 | value.Width.ToString(CultureInfo.InvariantCulture) + " " + value.Height.ToString(CultureInfo.InvariantCulture)); 20 | } 21 | 22 | /// Reads the JSON representation of the object. 23 | /// The to read from. 24 | /// Type of the object. 25 | /// The existing value of object being read. If there is no existing value then null will be used. 26 | /// The existing value has a value. 27 | /// The calling serializer. 28 | /// The object value. 29 | public override RectangleF ReadJson(JsonReader reader, Type objectType, RectangleF existingValue, bool hasExistingValue, JsonSerializer serializer) { 30 | var value = reader.Value.ToString().Split(' '); 31 | return new RectangleF( 32 | float.Parse(value[0], CultureInfo.InvariantCulture), float.Parse(value[1], CultureInfo.InvariantCulture), 33 | float.Parse(value[2], CultureInfo.InvariantCulture), float.Parse(value[3], CultureInfo.InvariantCulture)); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MLEM.Data/Json/Vector2Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Microsoft.Xna.Framework; 4 | using Newtonsoft.Json; 5 | 6 | namespace MLEM.Data.Json { 7 | /// 8 | /// Converts a to and from JSON 9 | /// 10 | public class Vector2Converter : JsonConverter { 11 | 12 | /// Writes the JSON representation of the object. 13 | /// The to write to. 14 | /// The value. 15 | /// The calling serializer. 16 | public override void WriteJson(JsonWriter writer, Vector2 value, JsonSerializer serializer) { 17 | writer.WriteValue(value.X.ToString(CultureInfo.InvariantCulture) + " " + value.Y.ToString(CultureInfo.InvariantCulture)); 18 | } 19 | 20 | /// Reads the JSON representation of the object. 21 | /// The to read from. 22 | /// Type of the object. 23 | /// The existing value of object being read. If there is no existing value then null will be used. 24 | /// The existing value has a value. 25 | /// The calling serializer. 26 | /// The object value. 27 | public override Vector2 ReadJson(JsonReader reader, Type objectType, Vector2 existingValue, bool hasExistingValue, JsonSerializer serializer) { 28 | var value = reader.Value.ToString().Split(' '); 29 | return new Vector2(float.Parse(value[0], CultureInfo.InvariantCulture), float.Parse(value[1], CultureInfo.InvariantCulture)); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MLEM.Data/MLEM.Data.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM.Data 8 | $(DefineConstants);FNA 9 | NU1701 10 | 11 | 12 | 13 | Ellpeck 14 | Simple loading and processing of textures and other data for FNA, including the ability to load non-XNB content files easily 15 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 16 | fna ellpeck mlem utility extensions data serialize 17 | https://mlem.ellpeck.de/ 18 | https://github.com/Ellpeck/MLEM 19 | MIT 20 | Logo.png 21 | README.md 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | 35 | all 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /MLEM.Data/MLEM.Data.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM.Data 8 | $(DefineConstants);KNI 9 | NU1701 10 | 11 | 12 | 13 | Ellpeck 14 | Simple loading and processing of textures and other data for KNI, including the ability to load non-XNB content files easily 15 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 16 | kni ellpeck mlem utility extensions data serialize 17 | https://mlem.ellpeck.de/ 18 | https://github.com/Ellpeck/MLEM 19 | MIT 20 | Logo.png 21 | README.md 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | 35 | all 36 | 37 | 38 | all 39 | 40 | 41 | all 42 | 43 | 44 | all 45 | 46 | 47 | all 48 | 49 | 50 | all 51 | 52 | 53 | all 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /MLEM.Data/MLEM.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | NU1701 8 | 9 | 10 | 11 | Ellpeck 12 | Simple loading and processing of textures and other data for MonoGame, including the ability to load non-XNB content files easily 13 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 14 | monogame ellpeck mlem utility extensions data serialize 15 | https://mlem.ellpeck.de/ 16 | https://github.com/Ellpeck/MLEM 17 | MIT 18 | Logo.png 19 | README.md 20 | 21 | 22 | 23 | 24 | 25 | 26 | all 27 | 28 | 29 | all 30 | 31 | 32 | all 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /MLEM.Extended/Font/GenericBitmapFont.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | using MLEM.Font; 4 | using MonoGame.Extended.BitmapFonts; 5 | 6 | namespace MLEM.Extended.Font { 7 | /// 8 | public class GenericBitmapFont : GenericFont { 9 | 10 | /// 11 | /// The that is being wrapped by this generic font 12 | /// 13 | public readonly BitmapFont Font; 14 | /// 15 | public override GenericFont Bold { get; } 16 | /// 17 | public override GenericFont Italic { get; } 18 | /// 19 | public override float LineHeight => this.Font.LineHeight; 20 | 21 | /// 22 | /// Creates a new generic font using . 23 | /// Optionally, a bold and italic version of the font can be supplied. 24 | /// 25 | /// The font to wrap 26 | /// A bold version of the font 27 | /// An italic version of the font 28 | public GenericBitmapFont(BitmapFont font, BitmapFont bold = null, BitmapFont italic = null) { 29 | this.Font = font; 30 | this.Bold = bold != null ? new GenericBitmapFont(bold) : this; 31 | this.Italic = italic != null ? new GenericBitmapFont(italic) : this; 32 | } 33 | 34 | /// 35 | protected override float MeasureCharacter(int codePoint) { 36 | var region = this.Font.GetCharacter(codePoint); 37 | return region != null ? new Vector2(region.XAdvance, region.TextureRegion.Height).X : 0; 38 | } 39 | 40 | /// 41 | public override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) { 42 | batch.DrawString(this.Font, character, position, color, rotation, Vector2.Zero, scale, effects, layerDepth); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MLEM.Extended/Font/GenericStashFont.cs: -------------------------------------------------------------------------------- 1 | using FontStashSharp; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Font; 5 | 6 | namespace MLEM.Extended.Font { 7 | /// 8 | public class GenericStashFont : GenericFont { 9 | 10 | /// 11 | /// The that is being wrapped by this generic font 12 | /// 13 | public readonly SpriteFontBase Font; 14 | 15 | /// 16 | public override GenericFont Bold { get; } 17 | /// 18 | public override GenericFont Italic { get; } 19 | /// 20 | public override float LineHeight => this.Font.LineHeight; 21 | 22 | /// 23 | /// The character spacing that will be passed to the underlying . 24 | /// 25 | public float CharacterSpacing { get; set; } 26 | /// 27 | /// The line spacing that will be passed to the underlying . 28 | /// 29 | public float LineSpacing { get; set; } 30 | 31 | /// 32 | /// Creates a new generic font using . 33 | /// Optionally, a bold and italic version of the font can be supplied. 34 | /// 35 | /// The font to wrap 36 | /// A bold version of the font 37 | /// An italic version of the font 38 | public GenericStashFont(SpriteFontBase font, SpriteFontBase bold = null, SpriteFontBase italic = null) { 39 | this.Font = font; 40 | this.Bold = bold != null ? new GenericStashFont(bold) : this; 41 | this.Italic = italic != null ? new GenericStashFont(italic) : this; 42 | } 43 | 44 | /// 45 | protected override float MeasureCharacter(int codePoint) { 46 | return this.Font.MeasureString(CodePointSource.ToString(codePoint), null, this.CharacterSpacing, this.LineSpacing).X; 47 | } 48 | 49 | /// 50 | public override void DrawCharacter(SpriteBatch batch, int codePoint, string character, Vector2 position, Color color, float rotation, Vector2 scale, SpriteEffects effects, float layerDepth) { 51 | this.Font.DrawText(batch, character, position, color, rotation, Vector2.Zero, scale, layerDepth, this.CharacterSpacing, this.LineSpacing); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /MLEM.Extended/Graphics/TextureExtensions.cs: -------------------------------------------------------------------------------- 1 | using MLEM.Maths; 2 | using MLEM.Textures; 3 | using MonoGame.Extended.Graphics; 4 | using NinePatch = MLEM.Textures.NinePatch; 5 | using ExtNinePatch = MonoGame.Extended.Graphics.NinePatch; 6 | 7 | namespace MLEM.Extended.Graphics { 8 | /// 9 | /// A set of extensions for converting texture-related types between MLEM and MonoGame.Extended. 10 | /// 11 | public static class TextureExtensions { 12 | 13 | /// 14 | /// Converts a MLEM to a MonoGame.Extended . 15 | /// 16 | /// The nine patch to convert 17 | /// The converted nine patch 18 | public static ExtNinePatch ToExtended(this NinePatch patch) { 19 | return patch.Region.ToExtended().CreateNinePatch(patch.Padding.Left.Floor(), patch.Padding.Top.Floor(), patch.Padding.Right.Floor(), patch.Padding.Bottom.Floor()); 20 | } 21 | 22 | /// 23 | /// Converts a MLEM to a MonoGame.Extended . 24 | /// 25 | /// The nine patch to convert 26 | /// The converted nine patch 27 | public static Texture2DRegion ToExtended(this TextureRegion region) { 28 | return new Texture2DRegion(region.Texture, region.U, region.V, region.Width, region.Height, region.Name); 29 | } 30 | 31 | /// 32 | /// Converts a MonoGame.Extended to a MLEM . 33 | /// 34 | /// The nine patch to convert 35 | /// The converted nine patch 36 | public static TextureRegion ToMlem(this Texture2DRegion region) { 37 | return new TextureRegion(region.Texture, region.Bounds) {Name = region.Name}; 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MLEM.Extended/MLEM.Extended.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM.Extended 8 | $(DefineConstants);FNA 9 | NU1702 10 | 11 | 12 | 13 | Ellpeck 14 | MLEM Library for Extending FNA extension that ties in with other FNA libraries 15 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 16 | fna ellpeck mlem utility extensions extended 17 | https://mlem.ellpeck.de/ 18 | https://github.com/Ellpeck/MLEM 19 | MIT 20 | Logo.png 21 | README.md 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | all 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /MLEM.Extended/MLEM.Extended.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | 8 | 9 | 10 | Ellpeck 11 | MLEM Library for Extending MonoGame extension that ties in with MonoGame.Extended and other MonoGame libraries 12 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 13 | monogame ellpeck mlem utility extensions monogame.extended extended 14 | https://mlem.ellpeck.de/ 15 | https://github.com/Ellpeck/MLEM 16 | MIT 17 | Logo.png 18 | README.md 19 | 20 | 21 | 22 | 23 | 24 | 25 | all 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /MLEM.Extended/Maths/RandomExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework; 3 | using MonoGame.Extended; 4 | 5 | namespace MLEM.Extended.Maths { 6 | /// 7 | /// A set of extension methods for dealing with 8 | /// 9 | public static class RandomExtensions { 10 | 11 | /// 12 | /// Returns a random number in the given range. 13 | /// 14 | /// The random to use for generation 15 | /// The range in which numbers will be generated 16 | /// A number in the given range 17 | public static int Range(this Random random, Range range) { 18 | return random.Next(range.Min, range.Max); 19 | } 20 | 21 | /// 22 | /// Returns a random number in the given range. 23 | /// 24 | /// The random to use for generation 25 | /// The range in which numbers will be generated 26 | /// A number in the given range 27 | public static float Range(this Random random, Range range) { 28 | return random.NextSingle(range.Min, range.Max); 29 | } 30 | 31 | /// 32 | /// Returns a random vector whose x and y values are in the given range. 33 | /// 34 | /// The random to use for generation 35 | /// The minimum value for each coordinate 36 | /// The maximum value for each coordinate 37 | /// A random vector in the given range 38 | public static Vector2 NextVector2(this Random random, float min, float max) { 39 | return new Vector2(random.NextSingle(min, max), random.NextSingle(min, max)); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MLEM.Startup/CoroutineEvents.cs: -------------------------------------------------------------------------------- 1 | using Coroutine; 2 | 3 | namespace MLEM.Startup { 4 | /// 5 | /// This class contains a set of events for the coroutine system that are automatically fired in . 6 | /// 7 | public static class CoroutineEvents { 8 | 9 | /// 10 | /// This event is fired in , before is called. 11 | /// 12 | public static readonly Event PreUpdate = new Event(); 13 | /// 14 | /// This event is fired in , after is called. 15 | /// 16 | public static readonly Event Update = new Event(); 17 | /// 18 | /// This event is fired in , before is called. 19 | /// 20 | public static readonly Event PreDraw = new Event(); 21 | /// 22 | /// This event is fired in , after is called. 23 | /// 24 | public static readonly Event Draw = new Event(); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MLEM.Startup/MLEM.Startup.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452;netstandard2.0;net8.0 5 | true 6 | true 7 | true 8 | MLEM.Startup 9 | $(DefineConstants);FNA 10 | 11 | 12 | 13 | Ellpeck 14 | MLEM Library for Extending FNA combined with some other useful libraries into a quick Game startup class 15 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 16 | fna ellpeck mlem utility extensions 17 | https://mlem.ellpeck.de/ 18 | https://github.com/Ellpeck/MLEM 19 | MIT 20 | Logo.png 21 | README.md 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /MLEM.Startup/MLEM.Startup.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452;netstandard2.0;net8.0 5 | true 6 | true 7 | true 8 | MLEM.Startup 9 | $(DefineConstants);KNI 10 | 11 | 12 | 13 | Ellpeck 14 | MLEM Library for Extending KNI combined with some other useful libraries into a quick Game startup class 15 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 16 | kni ellpeck mlem utility extensions 17 | https://mlem.ellpeck.de/ 18 | https://github.com/Ellpeck/MLEM 19 | MIT 20 | Logo.png 21 | README.md 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | 32 | 33 | all 34 | 35 | 36 | all 37 | 38 | 39 | all 40 | 41 | 42 | all 43 | 44 | 45 | all 46 | 47 | 48 | all 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /MLEM.Startup/MLEM.Startup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452;netstandard2.0;net8.0 5 | true 6 | true 7 | true 8 | 9 | 10 | 11 | Ellpeck 12 | MLEM Library for Extending MonoGame combined with some other useful libraries into a quick Game startup class 13 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 14 | monogame ellpeck mlem utility extensions 15 | https://mlem.ellpeck.de/ 16 | https://github.com/Ellpeck/MLEM 17 | MIT 18 | Logo.png 19 | README.md 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MLEM.Templates/MLEM.Templates.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452;netstandard2.0;net8.0 5 | true 6 | false 7 | content 8 | true 9 | NU5128 10 | 11 | 12 | 13 | Template 14 | MLEM Templates 15 | Ellpeck 16 | MLEM Library for Extending MonoGame cross-platform project templates 17 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 18 | dotnet-new templates monogame ellpeck mlem utility extensions 19 | https://mlem.ellpeck.de/ 20 | https://github.com/Ellpeck/MLEM 21 | Logo.png 22 | README.md 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-mgcb": { 6 | "version": "3.8.1.303", 7 | "commands": [ 8 | "mgcb" 9 | ] 10 | }, 11 | "dotnet-mgcb-editor": { 12 | "version": "3.8.1.303", 13 | "commands": [ 14 | "mgcb-editor" 15 | ] 16 | }, 17 | "dotnet-mgcb-editor-linux": { 18 | "version": "3.8.1.303", 19 | "commands": [ 20 | "mgcb-editor-linux" 21 | ] 22 | }, 23 | "dotnet-mgcb-editor-windows": { 24 | "version": "3.8.1.303", 25 | "commands": [ 26 | "mgcb-editor-windows" 27 | ] 28 | }, 29 | "dotnet-mgcb-editor-mac": { 30 | "version": "3.8.1.303", 31 | "commands": [ 32 | "mgcb-editor-mac" 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "author": "Ellpeck", 4 | "classifications": ["MLEM", "MonoGame"], 5 | "groupIdentity": "MLEM.Templates.DesktopGL", 6 | "identity": "MLEM.Templates.DesktopGL", 7 | "name": "MLEM DesktopGL", 8 | "shortName": "mlemdesktopgl", 9 | "sourceName": "TemplateNamespace", 10 | "preferNameDirectory": true, 11 | "tags": { 12 | "language": "C#", 13 | "type": "project" 14 | }, 15 | "primaryOutputs": [ 16 | { 17 | "path": "TemplateNamespace.csproj" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/Content/Content.mgcb: -------------------------------------------------------------------------------- 1 | 2 | #----------------------------- Global Properties ----------------------------# 3 | 4 | /outputDir:bin 5 | /intermediateDir:obj 6 | /platform:DesktopGL 7 | /config: 8 | /profile:Reach 9 | /compress:False 10 | 11 | #-------------------------------- References --------------------------------# 12 | 13 | 14 | #---------------------------------- Content ---------------------------------# 15 | 16 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/GameImpl.cs: -------------------------------------------------------------------------------- 1 | using MLEM.Startup; 2 | 3 | namespace TemplateNamespace; 4 | 5 | public class GameImpl : MlemGame { 6 | 7 | public static GameImpl Instance { get; private set; } 8 | 9 | public GameImpl() { 10 | Instance = this; 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/Icon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/MLEM.Templates/content/MLEM.Templates.DesktopGL/Icon.bmp -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/MLEM.Templates/content/MLEM.Templates.DesktopGL/Icon.ico -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Misc; 3 | 4 | namespace TemplateNamespace; 5 | 6 | public static class Program { 7 | 8 | public static void Main() { 9 | MlemPlatform.Current = new MlemPlatform.DesktopGl((w, c) => w.TextInput += c); 10 | using var game = new GameImpl(); 11 | game.Run(); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.DesktopGL/TemplateNamespace.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | false 7 | false 8 | Icon.ico 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.Portable/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "author": "Ellpeck", 4 | "classifications": ["MLEM", "MonoGame"], 5 | "groupIdentity": "MLEM.Templates.Portable", 6 | "identity": "MLEM.Templates.Portable", 7 | "name": "MLEM Portable", 8 | "shortName": "mlemportable", 9 | "sourceName": "TemplateNamespace", 10 | "preferNameDirectory": true, 11 | "tags": { 12 | "language": "C#", 13 | "type": "project" 14 | }, 15 | "primaryOutputs": [ 16 | { 17 | "path": "TemplateNamespace.csproj" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.Portable/Content/Content.mgcb: -------------------------------------------------------------------------------- 1 | 2 | #----------------------------- Global Properties ----------------------------# 3 | 4 | /outputDir:bin 5 | /intermediateDir:obj 6 | /platform:DesktopGL 7 | /config: 8 | /profile:Reach 9 | /compress:False 10 | 11 | #-------------------------------- References --------------------------------# 12 | 13 | 14 | #---------------------------------- Content ---------------------------------# 15 | 16 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.Portable/GameImpl.cs: -------------------------------------------------------------------------------- 1 | using MLEM.Startup; 2 | 3 | namespace TemplateNamespace; 4 | 5 | public class GameImpl : MlemGame { 6 | 7 | public static GameImpl Instance { get; private set; } 8 | 9 | public GameImpl() { 10 | Instance = this; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /MLEM.Templates/content/MLEM.Templates.Portable/TemplateNamespace.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | all 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /MLEM.Ui/Elements/Group.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | using MLEM.Graphics; 4 | 5 | namespace MLEM.Ui.Elements { 6 | /// 7 | /// A group element to be used inside of a . 8 | /// A group is an element that has no rendering or interaction on its own, but that can aid with automatic placement of child elements. 9 | /// If a grouping whose children scroll, and which has a , is desired, a with its set to can be used. 10 | /// 11 | public class Group : Element { 12 | 13 | /// 14 | /// Creates a new group with the given settings 15 | /// 16 | /// The group's anchor 17 | /// The group's size 18 | /// Whether the group's height should be based on its children's height, see . 19 | public Group(Anchor anchor, Vector2 size, bool setHeightBasedOnChildren = true) : this(anchor, size, false, setHeightBasedOnChildren) {} 20 | 21 | /// 22 | /// Creates a new group with the given settings 23 | /// 24 | /// The group's anchor 25 | /// The group's size 26 | /// Whether the group's width should be based on its children's width, see . 27 | /// Whether the group's height should be based on its children's height, see . 28 | public Group(Anchor anchor, Vector2 size, bool setWidthBasedOnChildren, bool setHeightBasedOnChildren) : base(anchor, size) { 29 | this.SetWidthBasedOnChildren = setWidthBasedOnChildren; 30 | this.SetHeightBasedOnChildren = setHeightBasedOnChildren; 31 | this.CanBeSelected = false; 32 | } 33 | 34 | /// 35 | public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) { 36 | // since the group never accesses its own area when drawing, we have to update it manually 37 | this.UpdateAreaIfDirty(); 38 | base.Draw(time, batch, alpha, context); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MLEM.Ui/Elements/RadioButton.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Ui.Style; 3 | 4 | namespace MLEM.Ui.Elements { 5 | /// 6 | /// A radio button element to use inside of a . 7 | /// A radio button is a variation of a that causes all other radio buttons in the same to be deselected upon selection. 8 | /// 9 | public class RadioButton : Checkbox { 10 | 11 | /// 12 | /// The group that this radio button has. 13 | /// All other radio buttons in the same that have the same group will be deselected when this radio button is selected. 14 | /// 15 | public string Group; 16 | 17 | /// 18 | /// Creates a new radio button with the given settings 19 | /// 20 | /// The radio button's anchor 21 | /// The radio button's size 22 | /// The label to display next to the radio button 23 | /// If the radio button should be checked by default 24 | /// The group that the radio button has 25 | public RadioButton(Anchor anchor, Vector2 size, string label, bool defaultChecked = false, string group = "") : 26 | base(anchor, size, label, defaultChecked) { 27 | this.Group = group; 28 | 29 | // don't += because we want to override the checking/unchecking behavior of Checkbox 30 | this.OnPressed = element => { 31 | this.Checked = true; 32 | this.Root.Element.AndChildren(e => { 33 | if (e != this && e is RadioButton r && r.Group == this.Group) 34 | r.Checked = false; 35 | }); 36 | }; 37 | } 38 | 39 | /// 40 | protected override void InitStyle(UiStyle style) { 41 | base.InitStyle(style); 42 | this.Texture = this.Texture.OrStyle(style.RadioTexture); 43 | this.HoveredTexture = this.HoveredTexture.OrStyle(style.RadioHoveredTexture); 44 | this.HoveredColor = this.HoveredColor.OrStyle(style.RadioHoveredColor); 45 | this.Checkmark = this.Checkmark.OrStyle(style.RadioCheckmark); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MLEM.Ui/Elements/Slider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Maths; 3 | 4 | namespace MLEM.Ui.Elements { 5 | /// 6 | /// A slider element for use inside of a . 7 | /// A slider is a horizontal whose value can additionally be controlled using the and . 8 | /// 9 | public class Slider : ScrollBar { 10 | 11 | /// 12 | /// Creates a new slider with the given settings 13 | /// 14 | /// The slider's anchor 15 | /// The slider's size 16 | /// The size of the slider's scroller indicator 17 | /// The slider's maximum value 18 | public Slider(Anchor anchor, Vector2 size, int scrollerSize, float maxValue) : 19 | base(anchor, size, scrollerSize, maxValue, true) { 20 | this.CanBeSelected = true; 21 | this.GetGamepadNextElement = (dir, next) => { 22 | if (dir == Direction2.Left || dir == Direction2.Right) 23 | return null; 24 | return next; 25 | }; 26 | } 27 | 28 | /// 29 | public override void Update(GameTime time) { 30 | base.Update(time); 31 | 32 | if (this.IsSelectedActive) { 33 | if (this.CurrentValue > 0 && this.Controls.LeftButtons.TryConsumePressed(this.Input, this.Controls.GamepadIndex)) { 34 | this.CurrentValue -= this.StepPerScroll; 35 | } else if (this.CurrentValue < this.MaxValue && this.Controls.RightButtons.TryConsumePressed(this.Input, this.Controls.GamepadIndex)) { 36 | this.CurrentValue += this.StepPerScroll; 37 | } 38 | } 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MLEM.Ui/Elements/SpriteAnimationImage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Animations; 3 | 4 | namespace MLEM.Ui.Elements { 5 | /// 6 | /// A sprite animation image for use inside of a . 7 | /// A sprite animation image is an that displays a or . 8 | /// 9 | public class SpriteAnimationImage : Image { 10 | 11 | /// 12 | /// The sprite animation group that is displayed by this image 13 | /// 14 | public SpriteAnimationGroup Group; 15 | 16 | /// 17 | /// Creates a new sprite animation image with the given settings 18 | /// 19 | /// The image's anchor 20 | /// The image's size 21 | /// The sprite animation group to display 22 | /// Whether this image element should scale to the texture 23 | public SpriteAnimationImage(Anchor anchor, Vector2 size, SpriteAnimationGroup group, bool scaleToImage = false) : 24 | base(anchor, size, group.CurrentRegion, scaleToImage) { 25 | this.Group = group; 26 | } 27 | 28 | /// 29 | /// Creates a new sprite animation image with the given settings 30 | /// 31 | /// The image's anchor 32 | /// The image's size 33 | /// The sprite group to display 34 | /// Whether this image element should scale to the texture 35 | public SpriteAnimationImage(Anchor anchor, Vector2 size, SpriteAnimation animation, bool scaleToImage = false) : this(anchor, size, new SpriteAnimationGroup().Add(animation, () => true), scaleToImage) {} 36 | 37 | /// 38 | public override void Update(GameTime time) { 39 | base.Update(time); 40 | this.Group.Update(time); 41 | this.Texture = this.Group.CurrentRegion; 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MLEM.Ui/Elements/VerticalSpace.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | 3 | namespace MLEM.Ui.Elements { 4 | /// 5 | /// A vertical space element for use inside of a . 6 | /// A vertical space is an invisible element that can be used to add vertical space between paragraphs or other elements. 7 | /// 8 | public class VerticalSpace : Element { 9 | 10 | /// 11 | /// Creates a new vertical space with the given settings 12 | /// 13 | /// The height of the vertical space 14 | public VerticalSpace(float height) : base(Anchor.AutoCenter, new Vector2(1, height)) { 15 | this.CanBeSelected = false; 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MLEM.Ui/MLEM.Ui.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM.Ui 8 | $(DefineConstants);FNA 9 | 10 | 11 | 12 | Ellpeck 13 | A mouse, keyboard, gamepad and touch ready Ui system for FNA that features automatic anchoring, sizing and several ready-to-use element types 14 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 15 | fna ellpeck mlem ui user interface graphical gui system mouse keyboard gamepad touch 16 | https://mlem.ellpeck.de/ 17 | https://github.com/Ellpeck/MLEM 18 | MIT 19 | Logo.png 20 | README.md 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MLEM.Ui/MLEM.Ui.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM.Ui 8 | $(DefineConstants);KNI 9 | 10 | 11 | 12 | Ellpeck 13 | A mouse, keyboard, gamepad and touch ready Ui system for KNI that features automatic anchoring, sizing and several ready-to-use element types 14 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 15 | kni ellpeck mlem ui user interface graphical gui system mouse keyboard gamepad touch 16 | https://mlem.ellpeck.de/ 17 | https://github.com/Ellpeck/MLEM 18 | MIT 19 | Logo.png 20 | README.md 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | all 35 | 36 | 37 | all 38 | 39 | 40 | all 41 | 42 | 43 | all 44 | 45 | 46 | all 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /MLEM.Ui/MLEM.Ui.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | 8 | 9 | 10 | Ellpeck 11 | A mouse, keyboard, gamepad and touch ready Ui system for MonoGame that features automatic anchoring, sizing and several ready-to-use element types 12 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 13 | monogame ellpeck mlem ui user interface graphical gui system mouse keyboard gamepad touch 14 | https://mlem.ellpeck.de/ 15 | https://github.com/Ellpeck/MLEM 16 | MIT 17 | Logo.png 18 | README.md 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | all 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /MLEM.Ui/Style/UntexturedStyle.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | using MLEM.Graphics; 4 | 5 | namespace MLEM.Ui.Style { 6 | /// 7 | /// The default, untextured . 8 | /// Note that, as MLEM does not provide any texture or font assets, this default style is made up of single-color textures that were generated using . 9 | /// 10 | public class UntexturedStyle : UiStyle { 11 | 12 | /// 13 | /// Creates a new untextured style with textures generated by the given sprite batch 14 | /// 15 | /// The sprite batch to generate the textures with 16 | public UntexturedStyle(SpriteBatch batch) { 17 | this.SelectionIndicator = batch.GenerateNinePatch(Color.Transparent, Color.Red); 18 | this.ButtonTexture = batch.GenerateNinePatch(Color.CadetBlue, Color.Black); 19 | this.PanelTexture = batch.GenerateNinePatch(Color.Gray, Color.Black); 20 | this.TextFieldTexture = batch.GenerateNinePatch(Color.MediumBlue, Color.Black); 21 | this.ScrollBarBackground = batch.GenerateNinePatch(Color.LightBlue, Color.Black); 22 | this.ScrollBarScrollerTexture = batch.GenerateNinePatch(Color.Blue, Color.Black); 23 | this.CheckboxTexture = batch.GenerateNinePatch(Color.LightBlue, Color.Black); 24 | this.CheckboxCheckmark = batch.GenerateNinePatch(Color.Blue, Color.Black).Region; 25 | this.RadioTexture = batch.GenerateNinePatch(Color.AliceBlue, Color.Black); 26 | this.RadioCheckmark = batch.GenerateNinePatch(Color.CornflowerBlue, Color.Black).Region; 27 | this.TooltipBackground = batch.GenerateNinePatch(Color.Black * 0.65F, Color.Black * 0.65F); 28 | this.ProgressBarTexture = batch.GenerateNinePatch(Color.RoyalBlue, Color.Black); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/AnimatedCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace MLEM.Formatting.Codes { 4 | /// 5 | public class AnimatedCode : Code { 6 | 7 | /// 8 | public AnimatedCode(Match match, Regex regex) : base(match, regex) {} 9 | 10 | /// 11 | public override bool EndsHere(Code other) { 12 | return other is AnimatedCode; 13 | } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/ColorCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace MLEM.Formatting.Codes { 5 | /// 6 | public class ColorCode : Code { 7 | 8 | private readonly Color? color; 9 | 10 | /// 11 | public ColorCode(Match match, Regex regex, Color? color) : base(match, regex) { 12 | this.color = color; 13 | } 14 | 15 | /// 16 | public override Color? GetColor(Color defaultPick) { 17 | return this.color; 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/FontCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using MLEM.Font; 4 | 5 | namespace MLEM.Formatting.Codes { 6 | /// 7 | public class FontCode : Code { 8 | 9 | private readonly Func font; 10 | 11 | /// 12 | public FontCode(Match match, Regex regex, Func font) : base(match, regex) { 13 | this.font = font; 14 | } 15 | 16 | /// 17 | public override GenericFont GetFont(GenericFont defaultPick) { 18 | return this.font?.Invoke(defaultPick); 19 | } 20 | 21 | /// 22 | public override bool EndsHere(Code other) { 23 | // turning a string bold/italic should only end when that specific code is ended using SimpleEndCode 24 | return false; 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/LinkCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using MLEM.Font; 6 | 7 | namespace MLEM.Formatting.Codes { 8 | /// 9 | public class LinkCode : UnderlineCode { 10 | 11 | private readonly Func isSelected; 12 | private readonly Func color; 13 | 14 | /// 15 | public LinkCode(Match match, Regex regex, float thickness, float yOffset, Func isSelected, Func color) : 16 | base(match, regex, thickness, yOffset) { 17 | this.isSelected = isSelected; 18 | this.color = color; 19 | } 20 | 21 | /// 22 | public LinkCode(Match match, Regex regex, float thickness, float yOffset, Func isSelected, Color? color = null) : 23 | this(match, regex, thickness, yOffset, isSelected, d => color) {} 24 | 25 | /// 26 | /// Returns true if this link formatting code is currently selected or hovered over, based on the selection function. 27 | /// 28 | /// True if this code is currently selected 29 | public virtual bool IsSelected() { 30 | foreach (var token in this.Tokens) { 31 | if (this.isSelected(token)) 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | /// 38 | public override Color? GetColor(Color defaultPick) { 39 | return this.color.Invoke(defaultPick); 40 | } 41 | 42 | /// 43 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 44 | // since we inherit from UnderlineCode, we can just call base if selected 45 | return this.IsSelected() && base.DrawCharacter(time, batch, codePoint, character, token, indexInToken, stringPos, ref charPosOffset, font, ref color, ref scale, ref rotation, ref origin, depth, effects, stringPos, charSize); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/OutlineCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Font; 5 | using MLEM.Graphics; 6 | using MLEM.Maths; 7 | 8 | namespace MLEM.Formatting.Codes { 9 | /// 10 | public class OutlineCode : Code { 11 | 12 | private readonly Color color; 13 | private readonly float thickness; 14 | private readonly bool diagonals; 15 | 16 | /// 17 | public OutlineCode(Match match, Regex regex, Color color, float thickness, bool diagonals) : base(match, regex) { 18 | this.color = color; 19 | this.thickness = thickness; 20 | this.diagonals = diagonals; 21 | } 22 | 23 | /// 24 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 25 | foreach (var dir in this.diagonals ? Direction2Helper.AllExceptNone : Direction2Helper.Adjacent) { 26 | var offset = Vector2.Normalize(dir.Offset().ToVector2()) * this.thickness; 27 | var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + offset, rotation, origin, scale, effects, stringSize, charSize); 28 | font.DrawCharacter(batch, codePoint, character, finalPos, this.color.CopyAlpha(color), rotation, scale, effects, depth); 29 | } 30 | return false; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/ShadowCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Font; 5 | using MLEM.Graphics; 6 | 7 | namespace MLEM.Formatting.Codes { 8 | /// 9 | public class ShadowCode : Code { 10 | 11 | private readonly Color color; 12 | private readonly Vector2 offset; 13 | 14 | /// 15 | public ShadowCode(Match match, Regex regex, Color color, Vector2 offset) : base(match, regex) { 16 | this.color = color; 17 | this.offset = offset; 18 | } 19 | 20 | /// 21 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 22 | var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + this.offset, rotation, origin, scale, effects, stringSize, charSize); 23 | font.DrawCharacter(batch, codePoint, character, finalPos, this.color.CopyAlpha(color), rotation, scale, effects, depth); 24 | // we return false since we still want regular drawing to occur 25 | return false; 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/SimpleEndCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace MLEM.Formatting.Codes { 4 | /// 5 | public class SimpleEndCode : Code { 6 | 7 | private readonly Regex codeToEnd; 8 | 9 | /// 10 | public SimpleEndCode(Match match, Regex regex, string codeNameToEnd) : base(match, regex) { 11 | this.codeToEnd = new Regex($@"<{codeNameToEnd}(\W.*)?>"); 12 | } 13 | 14 | /// 15 | public override bool EndsOther(Code other) { 16 | return this.codeToEnd.IsMatch(other.Regex.ToString()); 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/SubSupCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Font; 5 | 6 | namespace MLEM.Formatting.Codes { 7 | /// 8 | public class SubSupCode : Code { 9 | 10 | private readonly float offset; 11 | 12 | /// 13 | public SubSupCode(Match match, Regex regex, float offset) : base(match, regex) { 14 | this.offset = offset; 15 | } 16 | 17 | /// 18 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 19 | charPosOffset.Y += this.offset * font.LineHeight * scale.Y; 20 | return false; 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/UnderlineCode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Font; 5 | using MLEM.Graphics; 6 | using MLEM.Maths; 7 | 8 | namespace MLEM.Formatting.Codes { 9 | /// 10 | public class UnderlineCode : Code { 11 | 12 | private readonly float thickness; 13 | private readonly float yOffset; 14 | 15 | /// 16 | public UnderlineCode(Match match, Regex regex, float thickness, float yOffset) : base(match, regex) { 17 | this.thickness = thickness; 18 | this.yOffset = yOffset; 19 | } 20 | 21 | /// 22 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 23 | // don't underline spaces at the end of lines 24 | if (codePoint == ' ' && token.DisplayString.Length > indexInToken + 1 && token.DisplayString[indexInToken + 1] == '\n') 25 | return false; 26 | var finalPos = font.TransformSingleCharacter(stringPos, charPosOffset + new Vector2(0, (this.yOffset - this.thickness) * charSize.Y), rotation, origin, scale, effects, stringSize, charSize); 27 | batch.Draw(batch.GetBlankTexture(), new RectangleF(finalPos.X, finalPos.Y, charSize.X * scale.X, this.thickness * charSize.Y * scale.Y), null, color, rotation, Vector2.Zero, SpriteEffects.None, depth); 28 | return false; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MLEM/Formatting/Codes/WobblyCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using MLEM.Font; 6 | 7 | namespace MLEM.Formatting.Codes { 8 | /// 9 | public class WobblyCode : AnimatedCode { 10 | 11 | private readonly float modifier; 12 | private readonly float heightModifier; 13 | /// 14 | /// The time that this wobbly animation has been running for. 15 | /// To reset its animation progress, reset this value. 16 | /// 17 | public TimeSpan TimeIntoAnimation; 18 | 19 | /// 20 | public WobblyCode(Match match, Regex regex, float modifier, float heightModifier) : base(match, regex) { 21 | this.modifier = modifier; 22 | this.heightModifier = heightModifier; 23 | } 24 | 25 | /// 26 | public override void Update(GameTime time) { 27 | this.TimeIntoAnimation += time.ElapsedGameTime; 28 | } 29 | 30 | /// 31 | public override bool DrawCharacter(GameTime time, SpriteBatch batch, int codePoint, string character, Token token, int indexInToken, Vector2 stringPos, ref Vector2 charPosOffset, GenericFont font, ref Color color, ref Vector2 scale, ref float rotation, ref Vector2 origin, float depth, SpriteEffects effects, Vector2 stringSize, Vector2 charSize) { 32 | charPosOffset += new Vector2(0, (float) Math.Sin(token.Index + indexInToken + this.TimeIntoAnimation.TotalSeconds * this.modifier) * font.LineHeight * this.heightModifier * scale.Y); 33 | // we return false since we still want regular drawing to occur, we just changed the position 34 | return false; 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MLEM/Formatting/TextAlignment.cs: -------------------------------------------------------------------------------- 1 | namespace MLEM.Formatting { 2 | /// 3 | /// An enumeration that represents a set of alignment options for objects and MLEM.Ui paragraphs. 4 | /// 5 | public enum TextAlignment { 6 | 7 | /// 8 | /// Left alignment, which is also the default value 9 | /// 10 | Left, 11 | /// 12 | /// Center alignment 13 | /// 14 | Center, 15 | /// 16 | /// Right alignment. 17 | /// In this alignment option, trailing spaces are ignored to ensure that visual alignment is consistent. 18 | /// 19 | Right 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MLEM/Input/GamepadExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Input; 3 | 4 | namespace MLEM.Input { 5 | /// 6 | /// A set of extension methods for dealing with , and . 7 | /// 8 | public static class GamepadExtensions { 9 | 10 | /// 11 | /// Returns the given 's value as an analog value between 0 and 1, where 1 is fully down and 0 is not down at all. 12 | /// For non-analog buttons, like or , only 0 and 1 will be returned and no inbetween values are possible. 13 | /// 14 | /// The gamepad state to query. 15 | /// The button to query. 16 | /// The button's state as an analog value. 17 | public static float GetAnalogValue(this GamePadState state, Buttons button) { 18 | switch (button) { 19 | case Buttons.LeftThumbstickDown: 20 | return -MathHelper.Clamp(state.ThumbSticks.Left.Y, -1, 0); 21 | case Buttons.LeftThumbstickUp: 22 | return MathHelper.Clamp(state.ThumbSticks.Left.Y, 0, 1); 23 | case Buttons.LeftThumbstickLeft: 24 | return -MathHelper.Clamp(state.ThumbSticks.Left.X, -1, 0); 25 | case Buttons.LeftThumbstickRight: 26 | return MathHelper.Clamp(state.ThumbSticks.Left.X, 0, 1); 27 | case Buttons.RightTrigger: 28 | return state.Triggers.Right; 29 | case Buttons.LeftTrigger: 30 | return state.Triggers.Left; 31 | case Buttons.RightThumbstickDown: 32 | return -MathHelper.Clamp(state.ThumbSticks.Right.Y, -1, 0); 33 | case Buttons.RightThumbstickUp: 34 | return MathHelper.Clamp(state.ThumbSticks.Right.Y, 0, 1); 35 | case Buttons.RightThumbstickLeft: 36 | return -MathHelper.Clamp(state.ThumbSticks.Right.X, -1, 0); 37 | case Buttons.RightThumbstickRight: 38 | return MathHelper.Clamp(state.ThumbSticks.Right.X, 0, 1); 39 | default: 40 | return state.IsButtonDown(button) ? 1 : 0; 41 | } 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MLEM/Input/MouseExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework.Input; 3 | 4 | namespace MLEM.Input { 5 | /// 6 | /// A set of extension methods for dealing with and 7 | /// 8 | public static class MouseExtensions { 9 | 10 | /// 11 | /// All enum values of 12 | /// 13 | public static readonly MouseButton[] MouseButtons = {MouseButton.Left, MouseButton.Middle, MouseButton.Right, MouseButton.Extra1, MouseButton.Extra2}; 14 | 15 | /// 16 | /// Returns the of the given mouse button. 17 | /// 18 | /// The mouse's current state 19 | /// The button whose state to query 20 | /// The state of the button 21 | /// If a mouse button out of range is passed 22 | public static ButtonState GetState(this MouseState state, MouseButton button) { 23 | switch (button) { 24 | case MouseButton.Left: 25 | return state.LeftButton; 26 | case MouseButton.Middle: 27 | return state.MiddleButton; 28 | case MouseButton.Right: 29 | return state.RightButton; 30 | case MouseButton.Extra1: 31 | return state.XButton1; 32 | case MouseButton.Extra2: 33 | return state.XButton2; 34 | default: 35 | throw new ArgumentException(nameof(button)); 36 | } 37 | } 38 | 39 | } 40 | 41 | /// 42 | /// This enum is a list of possible mouse buttons. 43 | /// It serves as a wrapper around 's button properties. 44 | /// 45 | public enum MouseButton { 46 | 47 | /// 48 | /// The left mouse button, or 49 | /// 50 | Left, 51 | /// 52 | /// The middle mouse button, or 53 | /// 54 | Middle, 55 | /// 56 | /// The right mouse button, or 57 | /// 58 | Right, 59 | /// 60 | /// The first extra mouse button, or 61 | /// 62 | Extra1, 63 | /// 64 | /// The second extra mouse button, or 65 | /// 66 | Extra2 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /MLEM/MLEM.FNA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM 8 | $(DefineConstants);FNA 9 | 10 | 11 | 12 | Ellpeck 13 | The MLEM base package, which provides various small addons and abstractions for FNA, including a text formatting system and simple input handling 14 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 15 | fna ellpeck mlem utility extensions 16 | https://mlem.ellpeck.de/ 17 | https://github.com/Ellpeck/MLEM 18 | MIT 19 | Logo.png 20 | README.md 21 | 22 | 23 | 24 | 25 | all 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /MLEM/MLEM.KNI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | MLEM 8 | $(DefineConstants);KNI 9 | 10 | 11 | 12 | Ellpeck 13 | The MLEM base package, which provides various small addons and abstractions for KNI, including a text formatting system and simple input handling 14 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 15 | kni ellpeck mlem utility extensions 16 | https://mlem.ellpeck.de/ 17 | https://github.com/Ellpeck/MLEM 18 | MIT 19 | Logo.png 20 | README.md 21 | 22 | 23 | 24 | 25 | all 26 | 27 | 28 | all 29 | 30 | 31 | all 32 | 33 | 34 | all 35 | 36 | 37 | all 38 | 39 | 40 | all 41 | 42 | 43 | all 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /MLEM/MLEM.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net452;netstandard2.0;net8.0 4 | true 5 | true 6 | true 7 | 8 | 9 | 10 | Ellpeck 11 | The MLEM base package, which provides various small addons and abstractions for MonoGame, including a text formatting system and simple input handling 12 | See the full changelog at https://mlem.ellpeck.de/CHANGELOG.html 13 | monogame ellpeck mlem utility extensions 14 | https://mlem.ellpeck.de/ 15 | https://github.com/Ellpeck/MLEM 16 | MIT 17 | Logo.png 18 | README.md 19 | 20 | 21 | 22 | 23 | all 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /MLEM/Misc/GenericDataHolder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace MLEM.Misc { 4 | /// 5 | /// Represents an object that can hold generic key-value based data. 6 | /// A lot of MLEM components extend this class to allow for users to add additional data to them easily. 7 | /// This implemention uses an underlying that only keeps track of non-default values. 8 | /// 9 | public class GenericDataHolder : IGenericDataHolder { 10 | 11 | private static readonly string[] EmptyStrings = new string[0]; 12 | private Dictionary data; 13 | 14 | /// 15 | public void SetData(string key, T data) { 16 | if (EqualityComparer.Default.Equals(data, default)) { 17 | if (this.data != null) 18 | this.data.Remove(key); 19 | } else { 20 | if (this.data == null) 21 | this.data = new Dictionary(); 22 | this.data[key] = data; 23 | } 24 | } 25 | 26 | /// 27 | public T GetData(string key) { 28 | if (this.data != null && this.data.TryGetValue(key, out var val)) 29 | return (T) val; 30 | return default; 31 | } 32 | 33 | /// 34 | public IEnumerable GetDataKeys() { 35 | if (this.data == null) 36 | return GenericDataHolder.EmptyStrings; 37 | return this.data.Keys; 38 | } 39 | 40 | } 41 | 42 | /// 43 | /// Represents an object that can hold generic key-value based data. 44 | /// A lot of MLEM components extend this class to allow for users to add additional data to them easily. 45 | /// 46 | public interface IGenericDataHolder { 47 | 48 | /// 49 | /// Store a piece of generic data on this object. 50 | /// 51 | /// The key to store the data by 52 | /// The data to store in the object 53 | void SetData(string key, T data); 54 | 55 | /// 56 | /// Returns a piece of generic data of the given type on this object. 57 | /// 58 | /// The key that the data is stored by 59 | /// The type of the data stored 60 | /// The data, or default if it doesn't exist 61 | T GetData(string key); 62 | 63 | /// 64 | /// Returns all of the generic data that this object stores. 65 | /// 66 | /// The generic data on this object 67 | IEnumerable GetDataKeys(); 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MLEM/Pathfinding/AStar2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework; 4 | using MLEM.Maths; 5 | 6 | namespace MLEM.Pathfinding { 7 | /// 8 | /// A 2-dimensional implementation of that uses for positions, and the manhattan distance as its heuristic. 9 | /// 10 | public class AStar2 : AStar { 11 | 12 | private readonly bool includeDiagonals; 13 | 14 | /// 15 | public AStar2(GetCost defaultCostFunction, bool includeDiagonals, float defaultCost = 1, int defaultMaxTries = 10000, CollectAdditionalNeighbors defaultAdditionalNeighbors = null) : 16 | base(defaultCostFunction, defaultCost, defaultMaxTries, defaultAdditionalNeighbors) { 17 | this.includeDiagonals = includeDiagonals; 18 | } 19 | 20 | /// 21 | protected override float GetHeuristicDistance(Point start, Point position) { 22 | return Math.Abs(position.X - start.X) + Math.Abs(position.Y - start.Y); 23 | } 24 | 25 | /// 26 | protected override void CollectNeighbors(Point position, ISet neighbors) { 27 | foreach (var dir in Direction2Helper.Adjacent) 28 | neighbors.Add(position + dir.Offset()); 29 | 30 | if (this.includeDiagonals) { 31 | foreach (var dir in Direction2Helper.Diagonals) 32 | neighbors.Add(position + dir.Offset()); 33 | } 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MLEM/Pathfinding/AStar3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace MLEM.Pathfinding { 6 | /// 7 | /// A 3-dimensional implementation of that uses for positions, and the manhattan distance as its heuristic. 8 | /// 9 | public class AStar3 : AStar { 10 | 11 | private readonly bool includeDiagonals; 12 | 13 | /// 14 | public AStar3(GetCost defaultCostFunction, bool includeDiagonals, float defaultCost = 1, int defaultMaxTries = 10000, CollectAdditionalNeighbors defaultAdditionalNeighbors = null) : 15 | base(defaultCostFunction, defaultCost, defaultMaxTries, defaultAdditionalNeighbors) { 16 | this.includeDiagonals = includeDiagonals; 17 | } 18 | 19 | /// 20 | protected override float GetHeuristicDistance(Vector3 start, Vector3 position) { 21 | return Math.Abs(position.X - start.X) + Math.Abs(position.Y - start.Y) + Math.Abs(position.Z - start.Z); 22 | } 23 | 24 | /// 25 | protected override void CollectNeighbors(Vector3 position, ISet neighbors) { 26 | if (this.includeDiagonals) { 27 | for (var x = -1; x <= 1; x++) { 28 | for (var y = -1; y <= 1; y++) { 29 | for (var z = -1; z <= 1; z++) { 30 | if (x == 0 && y == 0 && z == 0) 31 | continue; 32 | neighbors.Add(position + new Vector3(x, y, z)); 33 | } 34 | } 35 | } 36 | } else { 37 | neighbors.Add(position + new Vector3(1, 0, 0)); 38 | neighbors.Add(position + new Vector3(-1, 0, 0)); 39 | neighbors.Add(position + new Vector3(0, 1, 0)); 40 | neighbors.Add(position + new Vector3(0, -1, 0)); 41 | neighbors.Add(position + new Vector3(0, 0, 1)); 42 | neighbors.Add(position + new Vector3(0, 0, -1)); 43 | } 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MLEM/Sound/SoundExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework.Audio; 2 | 3 | namespace MLEM.Sound { 4 | /// 5 | /// A set of extensions for dealing with and 6 | /// 7 | public static class SoundExtensions { 8 | 9 | /// 10 | /// Creates a new from the given , allowing optional instance data to be supplied as part of the method call 11 | /// 12 | /// The sound effect to create an instance from 13 | /// The value to set the returned instance's to. Defaults to 1. 14 | /// The value to set the returned instance's to. Defaults to 0. 15 | /// The value to set the returned instance's to. Defaults to 0. 16 | /// The value to set the returned instance's to. Defaults to false. 17 | /// 18 | public static SoundEffectInstance CreateInstance(this SoundEffect effect, float volume = 1, float pitch = 0, float pan = 0, bool isLooped = false) { 19 | var instance = effect.CreateInstance(); 20 | instance.Volume = volume; 21 | instance.Pitch = pitch; 22 | instance.Pan = pan; 23 | instance.IsLooped = isLooped; 24 | return instance; 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Media/Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Media/Banner.png -------------------------------------------------------------------------------- /Media/Formatting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Media/Formatting.png -------------------------------------------------------------------------------- /Media/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Media/Logo.png -------------------------------------------------------------------------------- /Media/Ui.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Media/Ui.gif -------------------------------------------------------------------------------- /Sandbox/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-mgcb": { 6 | "version": "3.8.1.303", 7 | "commands": [ 8 | "mgcb" 9 | ] 10 | }, 11 | "dotnet-mgcb-editor": { 12 | "version": "3.8.1.303", 13 | "commands": [ 14 | "mgcb-editor" 15 | ] 16 | }, 17 | "dotnet-mgcb-editor-linux": { 18 | "version": "3.8.1.303", 19 | "commands": [ 20 | "mgcb-editor-linux" 21 | ] 22 | }, 23 | "dotnet-mgcb-editor-windows": { 24 | "version": "3.8.1.303", 25 | "commands": [ 26 | "mgcb-editor-windows" 27 | ] 28 | }, 29 | "dotnet-mgcb-editor-mac": { 30 | "version": "3.8.1.303", 31 | "commands": [ 32 | "mgcb-editor-mac" 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sandbox/Content/Content.mgcb: -------------------------------------------------------------------------------- 1 | 2 | #----------------------------- Global Properties ----------------------------# 3 | 4 | /outputDir:bin 5 | /intermediateDir:obj 6 | /platform:DesktopGL 7 | /config: 8 | /profile:Reach 9 | /compress:False 10 | 11 | #-------------------------------- References --------------------------------# 12 | 13 | #---------------------------------- Content ---------------------------------# 14 | 15 | #begin Fonts/Cadman_Roman.otf 16 | /copy:Fonts/Cadman_Roman.otf 17 | 18 | #begin Fonts/Symbola-Emoji.ttf 19 | /copy:Fonts/Symbola-Emoji.ttf 20 | 21 | #begin Fonts/RegularTexture.png 22 | /importer:TextureImporter 23 | /processor:TextureProcessor 24 | /processorParam:ColorKeyColor=255,0,255,255 25 | /processorParam:ColorKeyEnabled=True 26 | /processorParam:GenerateMipmaps=False 27 | /processorParam:PremultiplyAlpha=True 28 | /processorParam:ResizeToPowerOfTwo=False 29 | /processorParam:MakeSquare=False 30 | /processorParam:TextureFormat=Color 31 | /build:Fonts/RegularTexture.png 32 | 33 | #begin Fonts/TestFont.spritefont 34 | /importer:FontDescriptionImporter 35 | /processor:FontDescriptionProcessor 36 | /processorParam:PremultiplyAlpha=True 37 | /processorParam:TextureFormat=Compressed 38 | /build:Fonts/TestFont.spritefont 39 | 40 | #begin Test.json 41 | /copy:Test.json 42 | 43 | #begin Textures/Furniture.atlas 44 | /copy:Textures/Furniture.atlas 45 | 46 | #begin Textures/Furniture.png 47 | /importer:TextureImporter 48 | /processor:TextureProcessor 49 | /processorParam:ColorKeyColor=255,0,255,255 50 | /processorParam:ColorKeyEnabled=True 51 | /processorParam:GenerateMipmaps=False 52 | /processorParam:PremultiplyAlpha=True 53 | /processorParam:ResizeToPowerOfTwo=False 54 | /processorParam:MakeSquare=False 55 | /processorParam:TextureFormat=Color 56 | /build:Textures/Furniture.png 57 | 58 | #begin Textures/Test.png 59 | /copy:Textures/Test.png 60 | -------------------------------------------------------------------------------- /Sandbox/Content/Fonts/Cadman_Roman.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Sandbox/Content/Fonts/Cadman_Roman.otf -------------------------------------------------------------------------------- /Sandbox/Content/Fonts/RegularTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Sandbox/Content/Fonts/RegularTexture.png -------------------------------------------------------------------------------- /Sandbox/Content/Fonts/Symbola-Emoji.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Sandbox/Content/Fonts/Symbola-Emoji.ttf -------------------------------------------------------------------------------- /Sandbox/Content/Fonts/TestFont.spritefont: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | 14 | Cadman_Roman.otf 15 | 16 | 20 | 32 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | * 45 | 46 | 53 | 54 | 55 | 56 | ɏ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Sandbox/Content/Test.json: -------------------------------------------------------------------------------- 1 | { 2 | "Vec": "10 20", 3 | "Point": "20 30", 4 | "Rectangle": "1 2 3 4", 5 | "RectangleF": "4 5 6 7", 6 | "Dir": "Left" 7 | } 8 | -------------------------------------------------------------------------------- /Sandbox/Content/Textures/Furniture.atlas: -------------------------------------------------------------------------------- 1 | SimpleDeskUp 2 | loc 0 0 48 32 3 | piv 16 16 4 | 5 | SimpleDeskRight 6 | loc 48 0 48 32 7 | piv 80 16 8 | 9 | Plant 10 | loc 96 0 16 32 11 | 12 | LongTableUp 13 | loc 0 32 64 48 14 | piv 16 48 15 | 16 | LongTableRight LongTableDown LongTableLeft 17 | loc 64 32 64 48 18 | piv 112 48 19 | -------------------------------------------------------------------------------- /Sandbox/Content/Textures/Furniture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Sandbox/Content/Textures/Furniture.png -------------------------------------------------------------------------------- /Sandbox/Content/Textures/Test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Sandbox/Content/Textures/Test.png -------------------------------------------------------------------------------- /Sandbox/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Misc; 3 | 4 | namespace Sandbox; 5 | 6 | internal static class Program { 7 | 8 | private static void Main() { 9 | MlemPlatform.Current = new MlemPlatform.DesktopGl((w, c) => w.TextInput += c); 10 | using var game = new GameImpl(); 11 | game.Run(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Sandbox/Sandbox.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Tests/CameraTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Cameras; 3 | using NUnit.Framework; 4 | 5 | namespace Tests; 6 | 7 | public class CameraTests : GameTestFixture { 8 | 9 | [Test] 10 | public void TestConversions([Range(-4, 4, 4F)] float x, [Range(-4, 4, 4F)] float y) { 11 | var camera = new Camera(this.Game.GraphicsDevice); 12 | var pos = new Vector2(x, y); 13 | var cam = camera.ToCameraPos(pos); 14 | var ret = camera.ToWorldPos(cam); 15 | Assert.AreEqual(pos, ret); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Tests/CollectionTests.cs: -------------------------------------------------------------------------------- 1 | using MLEM.Misc; 2 | using NUnit.Framework; 3 | 4 | namespace Tests; 5 | 6 | public class CollectionTests { 7 | 8 | [Test] 9 | public void TestCombinations() { 10 | var things = new[] { 11 | new[] {'1', '2', '3'}, 12 | new[] {'A', 'B'}, 13 | new[] {'+', '-'} 14 | }; 15 | 16 | var expected = new[] { 17 | new[] {'1', 'A', '+'}, new[] {'1', 'A', '-'}, new[] {'1', 'B', '+'}, new[] {'1', 'B', '-'}, 18 | new[] {'2', 'A', '+'}, new[] {'2', 'A', '-'}, new[] {'2', 'B', '+'}, new[] {'2', 'B', '-'}, 19 | new[] {'3', 'A', '+'}, new[] {'3', 'A', '-'}, new[] {'3', 'B', '+'}, new[] {'3', 'B', '-'} 20 | }; 21 | Assert.AreEqual(things.Combinations(), expected); 22 | 23 | var indices = new[] { 24 | new[] {0, 0, 0}, new[] {0, 0, 1}, new[] {0, 1, 0}, new[] {0, 1, 1}, 25 | new[] {1, 0, 0}, new[] {1, 0, 1}, new[] {1, 1, 0}, new[] {1, 1, 1}, 26 | new[] {2, 0, 0}, new[] {2, 0, 1}, new[] {2, 1, 0}, new[] {2, 1, 1} 27 | }; 28 | Assert.AreEqual(things.IndexCombinations(), indices); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Tests/Content/TestFont.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Tests/Content/TestFont.xnb -------------------------------------------------------------------------------- /Tests/Content/TestFontKni.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/Tests/Content/TestFontKni.xnb -------------------------------------------------------------------------------- /Tests/Content/Texture.atlas: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SimpleDeskUp 5 | loc 0 0 48 32 6 | piv 16 16 7 | 8 | SimpleDeskRight 9 | loc 48 0 48 32 10 | piv 80 16 11 | 12 | Plant 13 | loc 96 0 16 32 14 | 15 | TestRegionNegativePivot 16 | loc 0 32 +16 16 17 | piv -32 +46 18 | 19 | 20 | 21 | "Region with Spaces" 22 | location 1 2 3 4 23 | data SomeData 'Some Value with Spaces' 24 | data "Some Data with Spaces" SomeValue 25 | 26 | 27 | 28 | DataTest 29 | loc 0 0 16 16 30 | dat DataPoint1 ThisIsSomeData 31 | dat DataPoint2 3.5 32 | dat DataPoint3 --- 33 | 34 | LongTableUp 35 | piv 16 48 loc 0 32 64 48 36 | copy Copy1 16 0 37 | cpy Copy2 32 4 38 | 39 | Copy3 from 40 | LongTableUp off 2 4 41 | 42 | 43 | LongTableRight LongTableDown LongTableLeft 44 | location 32 30 64 48 45 | piv 80 46 46 | offset 32 2 47 | -------------------------------------------------------------------------------- /Tests/DataTextureAtlasTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Microsoft.Xna.Framework; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using MLEM.Data; 5 | using MLEM.Textures; 6 | using NUnit.Framework; 7 | 8 | namespace Tests; 9 | 10 | public class TestDataTextureAtlas : GameTestFixture { 11 | 12 | [Test] 13 | public void Test([Values(0, 4)] int regionX, [Values(0, 4)] int regionY) { 14 | using var texture = new Texture2D(this.Game.GraphicsDevice, 1, 1); 15 | var region = new TextureRegion(texture, regionX, regionY, 1, 1); 16 | var atlas = DataTextureAtlas.LoadAtlasData(region, this.Game.RawContent, "Texture.atlas"); 17 | Assert.AreEqual(13, atlas.Regions.Count()); 18 | 19 | // no pivot 20 | var plant = atlas["Plant"]; 21 | Assert.AreEqual(plant.Area, new Rectangle(96 + regionX, 0 + regionY, 16, 32)); 22 | Assert.AreEqual(plant.PivotPixels, Vector2.Zero); 23 | 24 | // no added offset 25 | var table = atlas["LongTableUp"]; 26 | Assert.AreEqual(table.Area, new Rectangle(0 + regionX, 32 + regionY, 64, 48)); 27 | Assert.AreEqual(table.PivotPixels, new Vector2(16, 48 - 32)); 28 | 29 | // added offset 30 | var table2 = atlas["LongTableDown"]; 31 | Assert.AreEqual(table2.Area, new Rectangle(64 + regionX, 32 + regionY, 64, 48)); 32 | Assert.AreEqual(table2.PivotPixels, new Vector2(112 - 64, 48 - 32)); 33 | 34 | // negative pivot 35 | var negativePivot = atlas["TestRegionNegativePivot"]; 36 | Assert.AreEqual(negativePivot.Area, new Rectangle(0 + regionX, 32 + regionY, 16, 16)); 37 | Assert.AreEqual(negativePivot.PivotPixels, new Vector2(-32, 46 - 32)); 38 | 39 | // cpy (pivot pixels should be identical to LongTableUp because they're region-internal) 40 | var copy1 = atlas["Copy1"]; 41 | Assert.AreEqual(copy1.Area, new Rectangle(0 + 16 + regionX, 32 + regionY, 64, 48)); 42 | Assert.AreEqual(copy1.PivotPixels, new Vector2(16, 48 - 32)); 43 | var copy2 = atlas["Copy2"]; 44 | Assert.AreEqual(copy2.Area, new Rectangle(0 + 32 + regionX, 32 + 4 + regionY, 64, 48)); 45 | Assert.AreEqual(copy2.PivotPixels, new Vector2(16, 48 - 32)); 46 | 47 | // frm 48 | var copy3 = atlas["Copy3"]; 49 | Assert.AreEqual(copy3.Area, new Rectangle(0 + 2 + regionX, 32 + 4 + regionY, 64, 48)); 50 | Assert.AreEqual(copy3.PivotPixels, new Vector2(16, 48 - 32)); 51 | 52 | // data 53 | var data = atlas["DataTest"]; 54 | Assert.AreEqual("ThisIsSomeData", data.GetData("DataPoint1")); 55 | Assert.AreEqual("3.5", data.GetData("DataPoint2")); 56 | Assert.AreEqual("---", data.GetData("DataPoint3")); 57 | 58 | // spaces 59 | var spaces = atlas["Region with Spaces"]; 60 | Assert.AreEqual(spaces.Area, new Rectangle(1 + regionX, 2 + regionY, 3, 4)); 61 | Assert.AreEqual(spaces.GetDataKeys().Count(), 2); 62 | Assert.AreEqual(spaces.GetData("SomeData"), "Some Value with Spaces"); 63 | Assert.AreEqual(spaces.GetData("Some Data with Spaces"), "SomeValue"); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Tests/DirectionTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using MLEM.Maths; 3 | using NUnit.Framework; 4 | 5 | namespace Tests; 6 | 7 | public class DirectionTests { 8 | 9 | [Test] 10 | public void TestDirections() { 11 | Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), Direction2.DownRight); 12 | Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), Direction2.DownRight); 13 | Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Direction2.Down); 14 | } 15 | 16 | [Test] 17 | public void Test90Directions() { 18 | Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Direction2.Right); 19 | Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Direction2.Down); 20 | Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Direction2.Down); 21 | } 22 | 23 | [Test] 24 | public void TestRotations() { 25 | // rotate cw 26 | Assert.AreEqual(Direction2.Up.RotateCw(), Direction2.Right); 27 | Assert.AreEqual(Direction2.Up.RotateCw(true), Direction2.UpRight); 28 | Assert.AreEqual(Direction2.Left.RotateCw(), Direction2.Up); 29 | Assert.AreEqual(Direction2.UpLeft.RotateCw(), Direction2.UpRight); 30 | 31 | // rotate ccw 32 | Assert.AreEqual(Direction2.Up.RotateCcw(), Direction2.Left); 33 | Assert.AreEqual(Direction2.Up.RotateCcw(true), Direction2.UpLeft); 34 | Assert.AreEqual(Direction2.Left.RotateCcw(), Direction2.Down); 35 | Assert.AreEqual(Direction2.UpLeft.RotateCcw(), Direction2.DownLeft); 36 | 37 | // rotate 360 degrees 38 | foreach (var dir in Direction2Helper.AllExceptNone) { 39 | Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, false, 4), dir); 40 | Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, true, true, 8), dir); 41 | Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, false, 4), dir); 42 | Assert.AreEqual(DirectionTests.RotateMultipleTimes(dir, false, true, 8), dir); 43 | } 44 | 45 | // rotate by with start Up 46 | Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Right), Direction2.Down); 47 | Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Down), Direction2.Left); 48 | Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Left), Direction2.Up); 49 | Assert.AreEqual(Direction2.Right.RotateBy(Direction2.Up), Direction2.Right); 50 | 51 | // rotate by with start Left 52 | Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Right, Direction2.Left), Direction2.Down); 53 | Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Down, Direction2.Left), Direction2.Left); 54 | Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Left, Direction2.Left), Direction2.Up); 55 | Assert.AreEqual(Direction2.Up.RotateBy(Direction2.Up, Direction2.Left), Direction2.Right); 56 | } 57 | 58 | private static Direction2 RotateMultipleTimes(Direction2 dir, bool clockwise, bool fortyFiveDegrees, int times) { 59 | for (var i = 0; i < times; i++) 60 | dir = clockwise ? dir.RotateCw(fortyFiveDegrees) : dir.RotateCcw(fortyFiveDegrees); 61 | return dir; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Tests/SingleRandomTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Linq; 5 | using MLEM.Maths; 6 | using NUnit.Framework; 7 | 8 | namespace Tests; 9 | 10 | public class SingleRandomTests { 11 | 12 | [Test] 13 | public void TestEquality() { 14 | for (var i = 0; i < 1000000; i++) { 15 | Assert.AreEqual(SingleRandom.Single(i), SingleRandom.Single(new SeedSource().Add(i))); 16 | Assert.AreEqual(SingleRandom.Int(i), SingleRandom.Int(new SeedSource().Add(i))); 17 | 18 | // test if all methods that accept mins and max are identical 19 | Assert.AreEqual(SingleRandom.Int(i), SingleRandom.Int(int.MaxValue, i)); 20 | Assert.AreEqual(SingleRandom.Int(i), SingleRandom.Int(0, int.MaxValue, i)); 21 | Assert.AreEqual(SingleRandom.Single(i), SingleRandom.Single(1F, i)); 22 | Assert.AreEqual(SingleRandom.Single(i), SingleRandom.Single(0F, 1F, i)); 23 | } 24 | } 25 | 26 | [Test] 27 | public void TestBounds() { 28 | for (var i = 0; i < 1000000; i++) { 29 | Assert.That(SingleRandom.Single(i), Is.LessThan(1).And.GreaterThanOrEqualTo(0)); 30 | Assert.That(SingleRandom.Single(127F, i), Is.LessThan(127).And.GreaterThanOrEqualTo(0)); 31 | Assert.That(SingleRandom.Single(12920F, 1203919023F, i), Is.LessThan(1203919023).And.GreaterThanOrEqualTo(12920)); 32 | 33 | Assert.That(SingleRandom.Int(i), Is.LessThan(int.MaxValue).And.GreaterThanOrEqualTo(0)); 34 | Assert.That(SingleRandom.Int(17, i), Is.LessThan(17).And.GreaterThanOrEqualTo(0)); 35 | Assert.That(SingleRandom.Int(19283, 832498394, i), Is.LessThan(832498394).And.GreaterThanOrEqualTo(19283)); 36 | } 37 | } 38 | 39 | [Test] 40 | public void TestAverages() { 41 | var ints = new List(); 42 | var flts = new List(); 43 | for (var i = 0; i < 1000000; i++) { 44 | ints.Add(SingleRandom.Int(i)); 45 | flts.Add(SingleRandom.Single(i)); 46 | } 47 | Assert.AreEqual(0.5, ints.Average() / int.MaxValue, 0.001); 48 | Assert.AreEqual(0.5, flts.Average(), 0.001); 49 | } 50 | 51 | [Test] 52 | public void TestExpectedValues() { 53 | var distributed = File.ReadAllLines("Content/DistributedSingleRandoms.txt"); 54 | for (var i = 0; i < 10000; i++) 55 | Assert.AreEqual(SingleRandom.Single(i * 10000).ToString(CultureInfo.InvariantCulture), distributed[i]); 56 | 57 | var consecutive = File.ReadAllLines("Content/ConsecutiveSingleRandoms.txt"); 58 | for (var i = 0; i < 10000; i++) 59 | Assert.AreEqual(SingleRandom.Single(i).ToString(CultureInfo.InvariantCulture), consecutive[i]); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Tests/TestGame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.CompilerServices; 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | using MLEM.Data.Content; 7 | using MLEM.Font; 8 | using MLEM.Startup; 9 | using NUnit.Framework; 10 | 11 | namespace Tests; 12 | 13 | public class TestGame : MlemGame { 14 | 15 | public RawContentManager RawContent { get; private set; } 16 | 17 | private TestGame() { 18 | #if KNI 19 | // allow textures larger than 4096x4096 for our texture packer tests 20 | this.GraphicsDeviceManager.GraphicsProfile = GraphicsProfile.FL11_0; 21 | #endif 22 | } 23 | 24 | protected override void LoadContent() { 25 | base.LoadContent(); 26 | this.RawContent = new RawContentManager(this.Services, this.Content.RootDirectory); 27 | 28 | // make sure that the viewport is always the same size, since RunOneFrame doesn't ensure window size is correct 29 | this.UiSystem.Viewport = new Rectangle(0, 0, 1280, 720); 30 | // we use precompiled fonts and kni uses a different asset compilation system, so we just have both stored 31 | this.UiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent( 32 | #if KNI 33 | "TestFontKni" 34 | #else 35 | "TestFont" 36 | #endif 37 | )); 38 | // make sure we catch a potential ui stack overflow as part of the tests by ensuring a sufficient execution stack 39 | this.UiSystem.OnElementAreaUpdated += _ => RuntimeHelpers.EnsureSufficientExecutionStack(); 40 | } 41 | 42 | public static TestGame Create() { 43 | var game = new TestGame(); 44 | game.RunOneFrame(); 45 | return game; 46 | } 47 | 48 | } 49 | 50 | public class GameTestFixture { 51 | 52 | protected TestGame Game { get; private set; } 53 | 54 | [SetUp] 55 | public void SetUpGame() { 56 | this.Game = TestGame.Create(); 57 | } 58 | 59 | [TearDown] 60 | public void TearDownGame() { 61 | this.Game?.Dispose(); 62 | this.Game = null; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Tests/Tests.FNA.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | nunit 5 | TestResults.FNA 6 | Tests.FNA.runsettings 7 | Tests 8 | $(DefineConstants);FNA 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | PreserveNewest 38 | %(Filename)%(Extension) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Tests/Tests.FNA.runsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | [MLEM*.FNA]* 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests/Tests.KNI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | nunit 5 | TestResults.KNI 6 | Tests.KNI.runsettings 7 | Tests 8 | $(DefineConstants);KNI 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | PreserveNewest 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Tests/Tests.KNI.runsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | [MLEM*.KNI]* 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | nunit 5 | TestResults 6 | Tests.runsettings 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | PreserveNewest 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Tests/Tests.runsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | [MLEM*]* 8 | [*.FNA]* 9 | [*.KNI]* 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ThirdParty/Native/FAudio.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/FAudio.dll -------------------------------------------------------------------------------- /ThirdParty/Native/FNA3D.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/FNA3D.dll -------------------------------------------------------------------------------- /ThirdParty/Native/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/SDL2.dll -------------------------------------------------------------------------------- /ThirdParty/Native/libFAudio.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libFAudio.0.dylib -------------------------------------------------------------------------------- /ThirdParty/Native/libFAudio.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libFAudio.so.0 -------------------------------------------------------------------------------- /ThirdParty/Native/libFNA3D.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libFNA3D.0.dylib -------------------------------------------------------------------------------- /ThirdParty/Native/libFNA3D.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libFNA3D.so.0 -------------------------------------------------------------------------------- /ThirdParty/Native/libMoltenVK.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libMoltenVK.dylib -------------------------------------------------------------------------------- /ThirdParty/Native/libSDL2-2.0.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libSDL2-2.0.0.dylib -------------------------------------------------------------------------------- /ThirdParty/Native/libSDL2-2.0.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libSDL2-2.0.so.0 -------------------------------------------------------------------------------- /ThirdParty/Native/libtheorafile.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libtheorafile.dll -------------------------------------------------------------------------------- /ThirdParty/Native/libtheorafile.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libtheorafile.dylib -------------------------------------------------------------------------------- /ThirdParty/Native/libtheorafile.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libtheorafile.so -------------------------------------------------------------------------------- /ThirdParty/Native/libvulkan.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ellpeck/MLEM/cba4752711994e27d85881a06734e8662ff3bad5/ThirdParty/Native/libvulkan.1.dylib --------------------------------------------------------------------------------