mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 14:08:34 +01:00
Compare commits
84 commits
a1c5b8e2d6
...
9b090c954f
Author | SHA1 | Date | |
---|---|---|---|
9b090c954f | |||
064dc5607e | |||
663d7148fe | |||
79f7206686 | |||
711f60a97e | |||
48dfa8f1ee | |||
e673ccea61 | |||
ba1058748e | |||
08e28cb95b | |||
288b8352af | |||
d32bc0cbfb | |||
d58c5d8b33 | |||
6f05263980 | |||
6e2c2b3730 | |||
92018eea1e | |||
04c6bb5ff8 | |||
2973bd98e2 | |||
87b575b5c3 | |||
61055148ef | |||
334918103f | |||
42a87471fc | |||
9c370f75e8 | |||
059e26781b | |||
5fcdda80dc | |||
5d7d238630 | |||
aff61508c4 | |||
282a398f3b | |||
6b08e892f7 | |||
aabb1ed5df | |||
1795acb30e | |||
59af00c89a | |||
d0ece92550 | |||
01fb5288ff | |||
7b1da2f1a7 | |||
f53305ce42 | |||
d03116a49a | |||
7d9633d989 | |||
42993f1a0b | |||
0a93fb7da7 | |||
144062fa64 | |||
16053d9d04 | |||
61770d59b1 | |||
93a82bcf36 | |||
fdf04a7e77 | |||
cb496f613f | |||
951f4babd5 | |||
b9f2de8290 | |||
f0f1d7f8ed | |||
fcca5300ae | |||
bd9d3f970b | |||
161d44dbe0 | |||
30bcdc1710 | |||
15b873a8ad | |||
6dc4011ef5 | |||
8968e6025d | |||
03accff6ae | |||
5ba550619d | |||
7ebbe49786 | |||
61439aa521 | |||
874be1fd6e | |||
acd15fea14 | |||
47b58b1942 | |||
16b9e26969 | |||
98118e540a | |||
58b716aabb | |||
63d2353694 | |||
15a57d8db9 | |||
5a1b31e8a3 | |||
435042e1f5 | |||
4c24284a3f | |||
bc0f9d5c0c | |||
610527374e | |||
4a88cca8bf | |||
8adee49e55 | |||
46c77d2444 | |||
6393d879d9 | |||
c78bafd000 | |||
783da33107 | |||
be26a2ebc2 | |||
45afd9ac79 | |||
ad29b46df3 | |||
f445f59078 | |||
902391d278 | |||
62d2b28ec0 |
225 changed files with 4910 additions and 2353 deletions
113
.editorconfig
Normal file
113
.editorconfig
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# Microsoft .NET properties
|
||||||
|
csharp_new_line_before_catch = false
|
||||||
|
csharp_new_line_before_else = false
|
||||||
|
csharp_new_line_before_finally = false
|
||||||
|
csharp_new_line_before_members_in_object_initializers = false
|
||||||
|
csharp_new_line_before_open_brace = none
|
||||||
|
csharp_new_line_between_query_expression_clauses = false
|
||||||
|
csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion
|
||||||
|
csharp_space_after_cast = true
|
||||||
|
csharp_style_var_elsewhere = true:suggestion
|
||||||
|
csharp_style_var_for_built_in_types = true:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
dotnet_naming_rule.private_constants_rule.severity = warning
|
||||||
|
dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style
|
||||||
|
dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
|
||||||
|
dotnet_naming_rule.private_instance_fields_rule.severity = warning
|
||||||
|
dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style
|
||||||
|
dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols
|
||||||
|
dotnet_naming_rule.private_static_fields_rule.severity = warning
|
||||||
|
dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style
|
||||||
|
dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols
|
||||||
|
dotnet_naming_rule.private_static_readonly_rule.severity = warning
|
||||||
|
dotnet_naming_rule.private_static_readonly_rule.style = upper_camel_case_style
|
||||||
|
dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols
|
||||||
|
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
|
||||||
|
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
|
||||||
|
dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
|
||||||
|
dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
|
||||||
|
dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private
|
||||||
|
dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private
|
||||||
|
dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static
|
||||||
|
dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private
|
||||||
|
dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static, readonly
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
dotnet_style_qualification_for_event = true:suggestion
|
||||||
|
dotnet_style_qualification_for_field = true:suggestion
|
||||||
|
dotnet_style_qualification_for_method = true:suggestion
|
||||||
|
dotnet_style_qualification_for_property = true:suggestion
|
||||||
|
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||||
|
|
||||||
|
# ReSharper properties
|
||||||
|
resharper_blank_lines_after_block_statements = 0
|
||||||
|
resharper_blank_lines_around_auto_property = 0
|
||||||
|
resharper_blank_lines_around_local_method = 0
|
||||||
|
resharper_blank_lines_around_property = 0
|
||||||
|
resharper_blank_lines_inside_type = 1
|
||||||
|
resharper_braces_for_dowhile = required_for_multiline
|
||||||
|
resharper_braces_for_fixed = required_for_multiline
|
||||||
|
resharper_braces_for_for = required_for_multiline
|
||||||
|
resharper_braces_for_foreach = required_for_multiline
|
||||||
|
resharper_braces_for_ifelse = required_for_multiline
|
||||||
|
resharper_braces_for_lock = required_for_multiline
|
||||||
|
resharper_braces_for_using = required_for_multiline
|
||||||
|
resharper_braces_for_while = required_for_multiline
|
||||||
|
resharper_braces_redundant = false
|
||||||
|
resharper_csharp_blank_lines_around_field = 0
|
||||||
|
resharper_csharp_blank_lines_around_single_line_invocable = 1
|
||||||
|
resharper_csharp_empty_block_style = together
|
||||||
|
resharper_csharp_keep_blank_lines_in_code = 1
|
||||||
|
resharper_csharp_keep_blank_lines_in_declarations = 1
|
||||||
|
resharper_csharp_max_line_length = unset
|
||||||
|
resharper_csharp_stick_comment = false
|
||||||
|
resharper_csharp_wrap_before_ternary_opsigns = false
|
||||||
|
resharper_csharp_wrap_multiple_declaration_style = wrap_if_long
|
||||||
|
resharper_csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long
|
||||||
|
resharper_csharp_wrap_ternary_expr_style = wrap_if_long
|
||||||
|
resharper_force_attribute_style = join
|
||||||
|
resharper_indent_nested_fixed_stmt = true
|
||||||
|
resharper_indent_nested_foreach_stmt = true
|
||||||
|
resharper_indent_nested_for_stmt = true
|
||||||
|
resharper_indent_nested_lock_stmt = true
|
||||||
|
resharper_indent_nested_usings_stmt = true
|
||||||
|
resharper_indent_nested_while_stmt = true
|
||||||
|
resharper_indent_preprocessor_if = usual_indent
|
||||||
|
resharper_indent_preprocessor_other = usual_indent
|
||||||
|
resharper_keep_existing_declaration_parens_arrangement = false
|
||||||
|
resharper_keep_existing_embedded_arrangement = false
|
||||||
|
resharper_keep_existing_expr_member_arrangement = false
|
||||||
|
resharper_keep_existing_property_patterns_arrangement = false
|
||||||
|
resharper_keep_existing_switch_expression_arrangement = false
|
||||||
|
resharper_parentheses_redundancy_style = remove
|
||||||
|
resharper_place_attribute_on_same_line = false
|
||||||
|
resharper_place_expr_accessor_on_single_line = true
|
||||||
|
resharper_place_expr_method_on_single_line = true
|
||||||
|
resharper_place_expr_property_on_single_line = true
|
||||||
|
resharper_place_simple_accessor_on_single_line = false
|
||||||
|
resharper_place_simple_anonymousmethod_on_single_line = false
|
||||||
|
resharper_place_simple_embedded_statement_on_same_line = false
|
||||||
|
resharper_space_around_arrow_op = true
|
||||||
|
resharper_space_within_empty_braces = false
|
||||||
|
resharper_space_within_single_line_array_initializer_braces = false
|
||||||
|
resharper_static_members_qualify_members = field, property, event, method
|
||||||
|
resharper_wrap_for_stmt_header_style = wrap_if_long
|
||||||
|
resharper_wrap_object_and_collection_initializer_style = wrap_if_long
|
||||||
|
resharper_xmldoc_attribute_indent = align_by_first_attribute
|
||||||
|
resharper_xmldoc_attribute_style = on_single_line
|
||||||
|
resharper_xmldoc_pi_attribute_style = on_single_line
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[submodule "FNA"]
|
||||||
|
path = FNA
|
||||||
|
url = https://github.com/FNA-XNA/FNA
|
||||||
|
[submodule "FontStashSharp"]
|
||||||
|
path = FontStashSharp
|
||||||
|
url = https://github.com/FontStashSharp/FontStashSharp
|
89
CHANGELOG.md
89
CHANGELOG.md
|
@ -2,11 +2,98 @@
|
||||||
MLEM tries to adhere to [semantic versioning](https://semver.org/). Breaking changes are written in **bold**.
|
MLEM tries to adhere to [semantic versioning](https://semver.org/). Breaking changes are written in **bold**.
|
||||||
|
|
||||||
Jump to version:
|
Jump to version:
|
||||||
|
- [6.0.0](#600)
|
||||||
- [5.3.0](#530)
|
- [5.3.0](#530)
|
||||||
- [5.2.0](#520)
|
- [5.2.0](#520)
|
||||||
- [5.1.0](#510)
|
- [5.1.0](#510)
|
||||||
- [5.0.0](#500)
|
- [5.0.0](#500)
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
### MLEM
|
||||||
|
Additions
|
||||||
|
- Added consuming variants of IsPressed methods to InputHandler and Keybind
|
||||||
|
- Added SpriteBatchContext struct and extensions
|
||||||
|
- Added InputHandler.InvertPressBehavior
|
||||||
|
- Added ReverseInput, ReverseOutput and AndThen to Easings
|
||||||
|
- Added an Enum constructor to GenericInput
|
||||||
|
- Added RandomPitchModifier and GetRandomPitch to SoundEffectInfo
|
||||||
|
- Added TextInput class, which is an isolated version of MLEM.Ui's TextField logic
|
||||||
|
- Added MLEM.FNA, which is fully compatible with FNA
|
||||||
|
- Added TryGetUpTime, GetUpTime, TryGetTimeSincePress and GetTimeSincePress to InputHandler
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
- Allow comparing Keybind and Combination based on the amount of modifiers they have
|
||||||
|
- Allow using multiple textures in a StaticSpriteBatch
|
||||||
|
- Added GenericInput support for Buttons.None
|
||||||
|
- Improved the way terminating formatting codes work by introducing SimpleEndCode
|
||||||
|
- Allow RandomExtensions to operate on any ICollection
|
||||||
|
|
||||||
|
Removals
|
||||||
|
- Marked AStar.InfiniteCost as obsolete
|
||||||
|
|
||||||
|
### MLEM.Ui
|
||||||
|
Additions
|
||||||
|
- Added Element.AutoNavGroup which allows forming groups for auto-navigation
|
||||||
|
- Added UiMarkdownParser
|
||||||
|
- Added MLEM.Ui.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
- Ensure that Element.IsMouseOver is always accurate by making it an auto-property
|
||||||
|
- Started using SpriteBatchContext for Draw and DrawTransformed methods
|
||||||
|
- Make use of the new consuming variants in InputHandler and Keybind to consume UiControls inputs
|
||||||
|
- Allow Tooltip to manage more than one paragraph and make it easier to add new lines
|
||||||
|
- Allow adding dropdown elements at a specified index
|
||||||
|
- Turned Tooltip paragraph styling into style properties
|
||||||
|
- Improved ElementHelper.AddTooltip overloads
|
||||||
|
- Don't query a paragraph's text callback in the constructor
|
||||||
|
- Allow manually hiding a paragraph without its text overriding the hidden state
|
||||||
|
- Added optional isKeybindAllowed parameter to KeybindButton
|
||||||
|
- Allow manually setting a RootElement as CanBeActive
|
||||||
|
|
||||||
|
Fixes
|
||||||
|
- Fixed auto-nav tooltip displaying on the selected element even when not in auto-nav mode
|
||||||
|
- Fixed radio buttons not unchecking all other radio buttons with the same root element
|
||||||
|
- Fixed elements not being deselected when removed through RemoveChild
|
||||||
|
- Fixed elements sometimes staying hidden when they shouldn't in scrolling panels
|
||||||
|
- Fixed elements' OnDeselected events not being raised when CanBeSelected is set to false while selected
|
||||||
|
- Fixed gamepad auto-nav angle being incorrect for some elements
|
||||||
|
|
||||||
|
Removals
|
||||||
|
- Marked old Draw and DrawTransformed overloads as obsolete in favor of SpriteBatchContext ones
|
||||||
|
- Marked Tooltip.Paragraph as obsolete in favor of new Paragraphs collection
|
||||||
|
|
||||||
|
### MLEM.Extended
|
||||||
|
Additions
|
||||||
|
- Added LayerPositionF
|
||||||
|
- Added MLEM.Extended.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
- Allow using a StaticSpriteBatch to render an IndividualTiledMapRenderer
|
||||||
|
|
||||||
|
### MLEM.Data
|
||||||
|
Additions
|
||||||
|
- Added the ability to add padding to RuntimeTexturePacker texture regions
|
||||||
|
- Added the ability to pack UniformTextureAtlas and DataTextureAtlas using RuntimeTexturePacker
|
||||||
|
- Added MLEM.Data.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
|
Improvements
|
||||||
|
- Premultiply textures when using RawContentManager
|
||||||
|
- Allow enumerating all region names of a DataTextureAtlas
|
||||||
|
- Cache RuntimeTexturePacker texture data while packing to improve performance
|
||||||
|
- Greatly improved RuntimeTexturePacker performance
|
||||||
|
- Allow specifying multiple names for a DataTextureAtlas region
|
||||||
|
|
||||||
|
Fixes
|
||||||
|
- Fixed SoundEffectReader incorrectly claiming it could read ogg and mp3 files
|
||||||
|
|
||||||
|
### MLEM.Startup
|
||||||
|
Additions
|
||||||
|
- Added MLEM.Startup.FNA, which is fully compatible with FNA
|
||||||
|
|
||||||
|
### MLEM.Templates
|
||||||
|
Improvements
|
||||||
|
- Updated to MonoGame 3.8.1
|
||||||
|
|
||||||
## 5.3.0
|
## 5.3.0
|
||||||
### MLEM
|
### MLEM
|
||||||
Additions
|
Additions
|
||||||
|
@ -287,4 +374,4 @@ Additions
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed some number parsing not using the invariant culture
|
- Fixed some number parsing not using the invariant culture
|
||||||
- Fixed RawContentManager crashing with dynamic assemblies present
|
- Fixed RawContentManager crashing with dynamic assemblies present
|
||||||
|
|
36
Demos.Android/.config/dotnet-tools.json
Normal file
36
Demos.Android/.config/dotnet-tools.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-mgcb": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-linux": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-windows": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-mac": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-mac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,55 +1,55 @@
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using Android.Net;
|
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Input;
|
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using static Android.Views.SystemUiFlags;
|
using Uri = Android.Net.Uri;
|
||||||
|
|
||||||
namespace Demos.Android {
|
namespace Demos.Android;
|
||||||
[Activity(
|
|
||||||
Label = "@string/app_name",
|
|
||||||
MainLauncher = true,
|
|
||||||
Icon = "@drawable/icon",
|
|
||||||
AlwaysRetainTaskState = true,
|
|
||||||
LaunchMode = LaunchMode.SingleInstance,
|
|
||||||
ScreenOrientation = ScreenOrientation.UserLandscape,
|
|
||||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize
|
|
||||||
)]
|
|
||||||
public class Activity1 : AndroidGameActivity {
|
|
||||||
|
|
||||||
private GameImpl game;
|
[Activity(
|
||||||
private View view;
|
Label = "@string/app_name",
|
||||||
|
MainLauncher = true,
|
||||||
|
Icon = "@drawable/icon",
|
||||||
|
AlwaysRetainTaskState = true,
|
||||||
|
LaunchMode = LaunchMode.SingleInstance,
|
||||||
|
ScreenOrientation = ScreenOrientation.UserLandscape,
|
||||||
|
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize
|
||||||
|
)]
|
||||||
|
public class Activity1 : AndroidGameActivity {
|
||||||
|
|
||||||
protected override void OnCreate(Bundle bundle) {
|
private GameImpl game;
|
||||||
base.OnCreate(bundle);
|
private View view;
|
||||||
// render under notches
|
|
||||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
|
||||||
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
|
||||||
|
|
||||||
MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l))));
|
protected override void OnCreate(Bundle bundle) {
|
||||||
this.game = new GameImpl();
|
base.OnCreate(bundle);
|
||||||
// reset MlemGame width and height to use device's aspect ratio
|
// render under notches
|
||||||
this.game.GraphicsDeviceManager.ResetWidthAndHeight(this.game.Window);
|
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||||
// disable mouse handling for android to make emulator behavior more coherent
|
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||||
this.game.OnLoadContent += game => game.InputHandler.HandleMouse = false;
|
|
||||||
// set the game to fullscreen to cause the status bar to be hidden
|
|
||||||
this.game.GraphicsDeviceManager.IsFullScreen = true;
|
|
||||||
this.view = this.game.Services.GetService(typeof(View)) as View;
|
|
||||||
this.SetContentView(this.view);
|
|
||||||
this.game.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnWindowFocusChanged(bool hasFocus) {
|
|
||||||
base.OnWindowFocusChanged(hasFocus);
|
|
||||||
// hide the status bar
|
|
||||||
if (hasFocus)
|
|
||||||
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (ImmersiveSticky | LayoutStable | LayoutHideNavigation | LayoutFullscreen | HideNavigation | Fullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l))));
|
||||||
|
this.game = new GameImpl();
|
||||||
|
// reset MlemGame width and height to use device's aspect ratio
|
||||||
|
this.game.GraphicsDeviceManager.ResetWidthAndHeight(this.game.Window);
|
||||||
|
// disable mouse handling for android to make emulator behavior more coherent
|
||||||
|
this.game.OnLoadContent += game => game.InputHandler.HandleMouse = false;
|
||||||
|
// set the game to fullscreen to cause the status bar to be hidden
|
||||||
|
this.game.GraphicsDeviceManager.IsFullScreen = true;
|
||||||
|
this.view = this.game.Services.GetService(typeof(View)) as View;
|
||||||
|
this.SetContentView(this.view);
|
||||||
|
this.game.Run();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override void OnWindowFocusChanged(bool hasFocus) {
|
||||||
|
base.OnWindowFocusChanged(hasFocus);
|
||||||
|
// hide the status bar
|
||||||
|
if (hasFocus) {
|
||||||
|
#pragma warning disable CS0618
|
||||||
|
// TODO this is deprecated, find out how to replace it
|
||||||
|
this.Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.ImmersiveSticky | SystemUiFlags.LayoutStable | SystemUiFlags.LayoutHideNavigation | SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation | SystemUiFlags.Fullscreen);
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
6
Demos.Android/AndroidManifest.xml
Normal file
6
Demos.Android/AndroidManifest.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.ellpeck.mlem.demos.android" android:versionCode="1" android:versionName="1.0">
|
||||||
|
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="31" />
|
||||||
|
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||||
|
<application android:label="MLEM Android Demos" />
|
||||||
|
</manifest>
|
|
@ -1,104 +1,22 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net6.0-android</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<SupportedOSPlatformVersion>31</SupportedOSPlatformVersion>
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
<OutputType>Exe</OutputType>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<ApplicationId>de.ellpeck.mlem.demos.android</ApplicationId>
|
||||||
<ProjectGuid>{410C0262-131C-4D0E-910D-D01B4F7143E0}</ProjectGuid>
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||||
<OutputType>Library</OutputType>
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>Demos.Android</RootNamespace>
|
|
||||||
<AssemblyName>Demos.Android</AssemblyName>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<AndroidApplication>true</AndroidApplication>
|
|
||||||
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
|
|
||||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
|
||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
|
||||||
<AndroidStoreUncompressedFileExtensions>.m4a</AndroidStoreUncompressedFileExtensions>
|
|
||||||
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
|
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
|
||||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
|
||||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
|
||||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
|
||||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
|
||||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>portable</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;ANDROID</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
|
|
||||||
<AndroidLinkMode>None</AndroidLinkMode>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>portable</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;ANDROID</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
|
||||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
|
||||||
<AotAssemblies>false</AotAssemblies>
|
|
||||||
<EnableLLVM>false</EnableLLVM>
|
|
||||||
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
|
|
||||||
<BundleAssemblies>false</BundleAssemblies>
|
|
||||||
<MandroidI18n />
|
|
||||||
<AndroidPackageFormat>aab</AndroidPackageFormat>
|
|
||||||
<AndroidUseAapt2>true</AndroidUseAapt2>
|
|
||||||
<AndroidCreatePackagePerAbi>false</AndroidCreatePackagePerAbi>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.263" />
|
||||||
<Reference Include="System.Core" />
|
<PackageReference Include="MonoGame.Framework.Android" Version="3.8.1.263" />
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="Mono.Android" />
|
<ProjectReference Include="..\Demos\Demos.csproj" />
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Activity1.cs" />
|
|
||||||
<Compile Include="Resources\Resource.Designer.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<AndroidResource Include="Resources\Drawable\Icon.png" />
|
|
||||||
<AndroidResource Include="Resources\Values\Strings.xml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
||||||
<None Include="..\Demos\Content\*\**" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Properties\AndroidManifest.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Coroutine" Version="2.1.3" />
|
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
|
||||||
<PackageReference Include="MonoGame.Framework.Android" Version="3.8.0.1641" />
|
|
||||||
<PackageReference Include="TextCopy" Version="4.3.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Demos\Demos.csproj">
|
|
||||||
<Project>{1bc4682b-aa14-4937-b5c7-707e20fe88ff}</Project>
|
|
||||||
<Name>Demos</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.csproj">
|
|
||||||
<Project>{997f4739-7bec-4621-b9ca-68deb2d74412}</Project>
|
|
||||||
<Name>MLEM.Startup</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.csproj">
|
|
||||||
<Project>{6f00629a-8b87-4264-8896-19983285e32f}</Project>
|
|
||||||
<Name>MLEM.Ui</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\MLEM\MLEM.csproj">
|
|
||||||
<Project>{1d6ab762-43c4-4775-8924-707c7ec3f142}</Project>
|
|
||||||
<Name>MLEM</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.ellpeck.mlem.demos.android" android:installLocation="auto" android:versionCode="1" android:versionName="1.0">
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
|
||||||
<application android:label="MLEM Android Demos" android:resizeableActivity="true" />
|
|
||||||
</manifest>
|
|
|
@ -1,15 +0,0 @@
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("MLEM Android Demos")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("MLEM Android Demos")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
76
Demos.Android/Resources/Resource.Designer.cs
generated
76
Demos.Android/Resources/Resource.Designer.cs
generated
|
@ -1,76 +0,0 @@
|
||||||
#pragma warning disable 1591
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[assembly: global::Android.Runtime.ResourceDesignerAttribute("Demos.Android.Resource", IsApplication=true)]
|
|
||||||
|
|
||||||
namespace Demos.Android
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
|
|
||||||
public partial class Resource
|
|
||||||
{
|
|
||||||
|
|
||||||
static Resource()
|
|
||||||
{
|
|
||||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateIdValues()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Attribute
|
|
||||||
{
|
|
||||||
|
|
||||||
static Attribute()
|
|
||||||
{
|
|
||||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Attribute()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Drawable
|
|
||||||
{
|
|
||||||
|
|
||||||
// aapt resource value: 0x7F010000
|
|
||||||
public const int Icon = 2130771968;
|
|
||||||
|
|
||||||
static Drawable()
|
|
||||||
{
|
|
||||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class String
|
|
||||||
{
|
|
||||||
|
|
||||||
// aapt resource value: 0x7F020000
|
|
||||||
public const int app_name = 2130837504;
|
|
||||||
|
|
||||||
static String()
|
|
||||||
{
|
|
||||||
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore 1591
|
|
36
Demos.DesktopGL/.config/dotnet-tools.json
Normal file
36
Demos.DesktopGL/.config/dotnet-tools.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-mgcb": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-linux": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-windows": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-mac": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-mac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
Demos.DesktopGL/Demos.DesktopGL.FNA.csproj
Normal file
37
Demos.DesktopGL/Demos.DesktopGL.FNA.csproj
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
<AssemblyName>MLEM Desktop Demos</AssemblyName>
|
||||||
|
<RootNamespace>Demos.DesktopGL</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
<!-- We still use the MG content builder for ease of compatibility between the MG and FNA demo projects -->
|
||||||
|
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Demos\Demos.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
||||||
|
<Content Include="..\Demos\Content\*\**" />
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
<Content Include="FnaNative/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<Link>%(Filename)%(Extension)</Link>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -2,28 +2,32 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
<AssemblyName>MLEM Desktop Demos</AssemblyName>
|
<AssemblyName>MLEM Desktop Demos</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.263" />
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.263" />
|
||||||
|
|
||||||
<ProjectReference Include="..\Demos\Demos.csproj" />
|
<ProjectReference Include="..\Demos\Demos.csproj" />
|
||||||
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.csproj" />
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.csproj" />
|
||||||
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.csproj" />
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.csproj" />
|
||||||
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
<MonoGameContentReference Include="..\Demos\Content\Content.mgcb" />
|
||||||
<Content Include="..\Demos\Content\*\**" />
|
|
||||||
<EmbeddedResource Include="Icon.ico" />
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
<EmbeddedResource Include="Icon.bmp" />
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
|
||||||
|
<Message Text="Restoring dotnet tools" Importance="High" />
|
||||||
|
<Exec Command="dotnet tool restore" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
BIN
Demos.DesktopGL/FnaNative/FAudio.dll
Normal file
BIN
Demos.DesktopGL/FnaNative/FAudio.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/FNA3D.dll
Normal file
BIN
Demos.DesktopGL/FnaNative/FNA3D.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/SDL2.dll
Normal file
BIN
Demos.DesktopGL/FnaNative/SDL2.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libFAudio.0.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libFAudio.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libFAudio.so.0
Normal file
BIN
Demos.DesktopGL/FnaNative/libFAudio.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libFNA3D.0.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libFNA3D.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libFNA3D.so.0
Normal file
BIN
Demos.DesktopGL/FnaNative/libFNA3D.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libMoltenVK.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libMoltenVK.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libSDL2-2.0.0.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libSDL2-2.0.0.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libSDL2-2.0.so.0
Normal file
BIN
Demos.DesktopGL/FnaNative/libSDL2-2.0.so.0
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libtheorafile.dll
Normal file
BIN
Demos.DesktopGL/FnaNative/libtheorafile.dll
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libtheorafile.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libtheorafile.dylib
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libtheorafile.so
Normal file
BIN
Demos.DesktopGL/FnaNative/libtheorafile.so
Normal file
Binary file not shown.
BIN
Demos.DesktopGL/FnaNative/libvulkan.1.dylib
Normal file
BIN
Demos.DesktopGL/FnaNative/libvulkan.1.dylib
Normal file
Binary file not shown.
|
@ -1,14 +1,20 @@
|
||||||
using Microsoft.Xna.Framework;
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
|
|
||||||
namespace Demos.DesktopGL {
|
namespace Demos.DesktopGL {
|
||||||
public static class Program {
|
public static class Program {
|
||||||
|
|
||||||
public static void Main() {
|
public static void Main() {
|
||||||
|
#if FNA
|
||||||
|
MlemPlatform.Current = new MlemPlatform.DesktopFna(a => TextInputEXT.TextInput += a);
|
||||||
|
#else
|
||||||
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
||||||
|
#endif
|
||||||
using var game = new GameImpl();
|
using var game = new GameImpl();
|
||||||
game.Run();
|
game.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Demos {
|
||||||
// using it having wrong coordinates and/or sizes
|
// using it having wrong coordinates and/or sizes
|
||||||
// the regions that are part of the atlas are then referenced by region coordinates rather than texture coordinates
|
// the regions that are part of the atlas are then referenced by region coordinates rather than texture coordinates
|
||||||
// (as seen below)
|
// (as seen below)
|
||||||
var atlas = new UniformTextureAtlas(LoadContent<Texture2D>("Textures/Anim"), 4, 4);
|
var atlas = new UniformTextureAtlas(Demo.LoadContent<Texture2D>("Textures/Anim"), 4, 4);
|
||||||
|
|
||||||
// create the four animations by supplying the time per frame, and the four regions used
|
// create the four animations by supplying the time per frame, and the four regions used
|
||||||
// note that you don't need to use a texture atlas for this, you can also simply supply the texture and the regions manually here
|
// note that you don't need to use a texture atlas for this, you can also simply supply the texture and the regions manually here
|
||||||
|
@ -90,7 +90,7 @@ namespace Demos {
|
||||||
public override void DoDraw(GameTime gameTime) {
|
public override void DoDraw(GameTime gameTime) {
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(10));
|
||||||
// draw the group's current region
|
// draw the group's current region
|
||||||
// if not using a group, just draw the animation's CurrentRegion here
|
// if not using a group, just draw the animation's CurrentRegion here
|
||||||
this.SpriteBatch.Draw(this.group.CurrentRegion, new Vector2(10, 10), Color.White);
|
this.SpriteBatch.Draw(this.group.CurrentRegion, new Vector2(10, 10), Color.White);
|
||||||
|
@ -104,4 +104,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Demos {
|
||||||
public override void LoadContent() {
|
public override void LoadContent() {
|
||||||
base.LoadContent();
|
base.LoadContent();
|
||||||
// The layout of the texture is important for auto tiling to work correctly, and is explained in the XML docs for the methods used
|
// The layout of the texture is important for auto tiling to work correctly, and is explained in the XML docs for the methods used
|
||||||
this.texture = LoadContent<Texture2D>("Textures/AutoTiling");
|
this.texture = Demo.LoadContent<Texture2D>("Textures/AutoTiling");
|
||||||
|
|
||||||
// in this example, a simple string array is used for layout purposes. As the AutoTiling method allows any kind of
|
// in this example, a simple string array is used for layout purposes. As the AutoTiling method allows any kind of
|
||||||
// comparison, the actual implementation can vary (for instance, based on a more in-depth tile map)
|
// comparison, the actual implementation can vary (for instance, based on a more in-depth tile map)
|
||||||
|
@ -37,7 +37,7 @@ namespace Demos {
|
||||||
this.GraphicsDevice.Clear(Color.Black);
|
this.GraphicsDevice.Clear(Color.Black);
|
||||||
|
|
||||||
// drawing the auto tiles
|
// drawing the auto tiles
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(10));
|
||||||
for (var x = 0; x < 6; x++) {
|
for (var x = 0; x < 6; x++) {
|
||||||
for (var y = 0; y < 5; y++) {
|
for (var y = 0; y < 5; y++) {
|
||||||
// don't draw non-grass tiles ( )
|
// don't draw non-grass tiles ( )
|
||||||
|
@ -59,12 +59,12 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the texture region supplied to the AutoTiling method should only encompass the first filler tile's location and size
|
// the texture region supplied to the AutoTiling method should only encompass the first filler tile's location and size
|
||||||
AutoTiling.DrawAutoTile(this.SpriteBatch, new Vector2(x + 1, y + 1) * TileSize, new TextureRegion(this.texture, 0, 0, TileSize, TileSize), ConnectsTo, Color.White);
|
AutoTiling.DrawAutoTile(this.SpriteBatch, new Vector2(x + 1, y + 1) * AutoTilingDemo.TileSize, new TextureRegion(this.texture, 0, 0, AutoTilingDemo.TileSize, AutoTilingDemo.TileSize), ConnectsTo, Color.White);
|
||||||
|
|
||||||
// when drawing extended auto-tiles, the same rules apply, but the source texture layout is different
|
// when drawing extended auto-tiles, the same rules apply, but the source texture layout is different
|
||||||
var background = new TextureRegion(this.texture, 0, TileSize * 2, TileSize, TileSize);
|
var background = new TextureRegion(this.texture, 0, AutoTilingDemo.TileSize * 2, AutoTilingDemo.TileSize, AutoTilingDemo.TileSize);
|
||||||
var overlay = new TextureRegion(this.texture, background.Area.OffsetCopy(new Point(TileSize, 0)));
|
var overlay = new TextureRegion(this.texture, background.Area.OffsetCopy(new Point(AutoTilingDemo.TileSize, 0)));
|
||||||
AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * TileSize, background, overlay, ConnectsTo, Color.White, Color.White);
|
AutoTiling.DrawExtendedAutoTile(this.SpriteBatch, new Vector2(x + 8, y + 1) * AutoTilingDemo.TileSize, background, overlay, ConnectsTo, Color.White, Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.SpriteBatch.End();
|
this.SpriteBatch.End();
|
||||||
|
@ -73,4 +73,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
|
|
||||||
#---------------------------------- Content ---------------------------------#
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
||||||
|
#begin Fonts/MonospacedFont.spritefont
|
||||||
|
/importer:FontDescriptionImporter
|
||||||
|
/processor:FontDescriptionProcessor
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:TextureFormat=Compressed
|
||||||
|
/build:Fonts/MonospacedFont.spritefont
|
||||||
|
|
||||||
#begin Fonts/TestFont.spritefont
|
#begin Fonts/TestFont.spritefont
|
||||||
/importer:FontDescriptionImporter
|
/importer:FontDescriptionImporter
|
||||||
/processor:FontDescriptionProcessor
|
/processor:FontDescriptionProcessor
|
||||||
|
@ -34,12 +41,8 @@
|
||||||
/processorParam:TextureFormat=Compressed
|
/processorParam:TextureFormat=Compressed
|
||||||
/build:Fonts/TestFontItalic.spritefont
|
/build:Fonts/TestFontItalic.spritefont
|
||||||
|
|
||||||
#begin Fonts/MonospacedFont.spritefont
|
#begin Markdown.md
|
||||||
/importer:FontDescriptionImporter
|
/copy:Markdown.md
|
||||||
/processor:FontDescriptionProcessor
|
|
||||||
/processorParam:PremultiplyAlpha=True
|
|
||||||
/processorParam:TextureFormat=Compressed
|
|
||||||
/build:Fonts/MonospacedFont.spritefont
|
|
||||||
|
|
||||||
#begin Textures/Anim.png
|
#begin Textures/Anim.png
|
||||||
/importer:TextureImporter
|
/importer:TextureImporter
|
||||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
||||||
with.
|
with.
|
||||||
-->
|
-->
|
||||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
<Asset Type="Graphics:FontDescription">
|
<Asset Type="Graphics:FontDescription">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Modify this string to change the font that will be imported.
|
Modify this string to change the font that will be imported.
|
||||||
-->
|
-->
|
||||||
<FontName>JetBrainsMono-Regular.ttf</FontName>
|
<FontName>JetBrainsMono-Regular.ttf</FontName>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Size is a float value, measured in points. Modify this value to change
|
Size is a float value, measured in points. Modify this value to change
|
||||||
the size of the font.
|
the size of the font.
|
||||||
-->
|
-->
|
||||||
<Size>32</Size>
|
<Size>32</Size>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Spacing is a float value, measured in pixels. Modify this value to change
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
the amount of spacing in between characters.
|
the amount of spacing in between characters.
|
||||||
-->
|
-->
|
||||||
<Spacing>0</Spacing>
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
will be used when placing characters.
|
will be used when placing characters.
|
||||||
-->
|
-->
|
||||||
<UseKerning>true</UseKerning>
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
and "Bold, Italic", and are case sensitive.
|
and "Bold, Italic", and are case sensitive.
|
||||||
-->
|
-->
|
||||||
<Style>Regular</Style>
|
<Style>Regular</Style>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If you uncomment this line, the default character will be substituted if you draw
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
or measure text that contains characters which were not included in the font.
|
or measure text that contains characters which were not included in the font.
|
||||||
-->
|
-->
|
||||||
<DefaultCharacter>*</DefaultCharacter>
|
<DefaultCharacter>*</DefaultCharacter>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CharacterRegions control what letters are available in the font. Every
|
CharacterRegions control what letters are available in the font. Every
|
||||||
character from Start to End will be built and made available for drawing. The
|
character from Start to End will be built and made available for drawing. The
|
||||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
character set. The characters are ordered according to the Unicode standard.
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
See the documentation for more information.
|
See the documentation for more information.
|
||||||
-->
|
-->
|
||||||
<CharacterRegions>
|
<CharacterRegions>
|
||||||
<CharacterRegion>
|
<CharacterRegion>
|
||||||
<Start> </Start>
|
<Start> </Start>
|
||||||
<End>ɏ</End>
|
<End>ɏ</End>
|
||||||
</CharacterRegion>
|
</CharacterRegion>
|
||||||
</CharacterRegions>
|
</CharacterRegions>
|
||||||
</Asset>
|
</Asset>
|
||||||
</XnaContent>
|
</XnaContent>
|
||||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
||||||
with.
|
with.
|
||||||
-->
|
-->
|
||||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
<Asset Type="Graphics:FontDescription">
|
<Asset Type="Graphics:FontDescription">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Modify this string to change the font that will be imported.
|
Modify this string to change the font that will be imported.
|
||||||
-->
|
-->
|
||||||
<FontName>CAYETANO.ttf</FontName>
|
<FontName>CAYETANO.ttf</FontName>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Size is a float value, measured in points. Modify this value to change
|
Size is a float value, measured in points. Modify this value to change
|
||||||
the size of the font.
|
the size of the font.
|
||||||
-->
|
-->
|
||||||
<Size>32</Size>
|
<Size>32</Size>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Spacing is a float value, measured in pixels. Modify this value to change
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
the amount of spacing in between characters.
|
the amount of spacing in between characters.
|
||||||
-->
|
-->
|
||||||
<Spacing>0</Spacing>
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
will be used when placing characters.
|
will be used when placing characters.
|
||||||
-->
|
-->
|
||||||
<UseKerning>true</UseKerning>
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
and "Bold, Italic", and are case sensitive.
|
and "Bold, Italic", and are case sensitive.
|
||||||
-->
|
-->
|
||||||
<Style>Regular</Style>
|
<Style>Regular</Style>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If you uncomment this line, the default character will be substituted if you draw
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
or measure text that contains characters which were not included in the font.
|
or measure text that contains characters which were not included in the font.
|
||||||
-->
|
-->
|
||||||
<DefaultCharacter>*</DefaultCharacter>
|
<DefaultCharacter>*</DefaultCharacter>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CharacterRegions control what letters are available in the font. Every
|
CharacterRegions control what letters are available in the font. Every
|
||||||
character from Start to End will be built and made available for drawing. The
|
character from Start to End will be built and made available for drawing. The
|
||||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
character set. The characters are ordered according to the Unicode standard.
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
See the documentation for more information.
|
See the documentation for more information.
|
||||||
-->
|
-->
|
||||||
<CharacterRegions>
|
<CharacterRegions>
|
||||||
<CharacterRegion>
|
<CharacterRegion>
|
||||||
<Start> </Start>
|
<Start> </Start>
|
||||||
<End>ɏ</End>
|
<End>ɏ</End>
|
||||||
</CharacterRegion>
|
</CharacterRegion>
|
||||||
</CharacterRegions>
|
</CharacterRegions>
|
||||||
</Asset>
|
</Asset>
|
||||||
</XnaContent>
|
</XnaContent>
|
||||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
||||||
with.
|
with.
|
||||||
-->
|
-->
|
||||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
<Asset Type="Graphics:FontDescription">
|
<Asset Type="Graphics:FontDescription">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Modify this string to change the font that will be imported.
|
Modify this string to change the font that will be imported.
|
||||||
-->
|
-->
|
||||||
<FontName>CAYTANOB</FontName>
|
<FontName>CAYTANOB</FontName>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Size is a float value, measured in points. Modify this value to change
|
Size is a float value, measured in points. Modify this value to change
|
||||||
the size of the font.
|
the size of the font.
|
||||||
-->
|
-->
|
||||||
<Size>32</Size>
|
<Size>32</Size>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Spacing is a float value, measured in pixels. Modify this value to change
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
the amount of spacing in between characters.
|
the amount of spacing in between characters.
|
||||||
-->
|
-->
|
||||||
<Spacing>0</Spacing>
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
will be used when placing characters.
|
will be used when placing characters.
|
||||||
-->
|
-->
|
||||||
<UseKerning>true</UseKerning>
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
and "Bold, Italic", and are case sensitive.
|
and "Bold, Italic", and are case sensitive.
|
||||||
-->
|
-->
|
||||||
<Style>Regular</Style>
|
<Style>Regular</Style>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If you uncomment this line, the default character will be substituted if you draw
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
or measure text that contains characters which were not included in the font.
|
or measure text that contains characters which were not included in the font.
|
||||||
-->
|
-->
|
||||||
<DefaultCharacter>*</DefaultCharacter>
|
<DefaultCharacter>*</DefaultCharacter>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CharacterRegions control what letters are available in the font. Every
|
CharacterRegions control what letters are available in the font. Every
|
||||||
character from Start to End will be built and made available for drawing. The
|
character from Start to End will be built and made available for drawing. The
|
||||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
character set. The characters are ordered according to the Unicode standard.
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
See the documentation for more information.
|
See the documentation for more information.
|
||||||
-->
|
-->
|
||||||
<CharacterRegions>
|
<CharacterRegions>
|
||||||
<CharacterRegion>
|
<CharacterRegion>
|
||||||
<Start> </Start>
|
<Start> </Start>
|
||||||
<End>ɏ</End>
|
<End>ɏ</End>
|
||||||
</CharacterRegion>
|
</CharacterRegion>
|
||||||
</CharacterRegions>
|
</CharacterRegions>
|
||||||
</Asset>
|
</Asset>
|
||||||
</XnaContent>
|
</XnaContent>
|
||||||
|
|
|
@ -6,55 +6,55 @@ of the font in your game, and to change the characters which are available to dr
|
||||||
with.
|
with.
|
||||||
-->
|
-->
|
||||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
<Asset Type="Graphics:FontDescription">
|
<Asset Type="Graphics:FontDescription">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Modify this string to change the font that will be imported.
|
Modify this string to change the font that will be imported.
|
||||||
-->
|
-->
|
||||||
<FontName>CAYETANI</FontName>
|
<FontName>CAYETANI</FontName>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Size is a float value, measured in points. Modify this value to change
|
Size is a float value, measured in points. Modify this value to change
|
||||||
the size of the font.
|
the size of the font.
|
||||||
-->
|
-->
|
||||||
<Size>32</Size>
|
<Size>32</Size>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Spacing is a float value, measured in pixels. Modify this value to change
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
the amount of spacing in between characters.
|
the amount of spacing in between characters.
|
||||||
-->
|
-->
|
||||||
<Spacing>0</Spacing>
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
will be used when placing characters.
|
will be used when placing characters.
|
||||||
-->
|
-->
|
||||||
<UseKerning>true</UseKerning>
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
and "Bold, Italic", and are case sensitive.
|
and "Bold, Italic", and are case sensitive.
|
||||||
-->
|
-->
|
||||||
<Style>Regular</Style>
|
<Style>Regular</Style>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If you uncomment this line, the default character will be substituted if you draw
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
or measure text that contains characters which were not included in the font.
|
or measure text that contains characters which were not included in the font.
|
||||||
-->
|
-->
|
||||||
<DefaultCharacter>*</DefaultCharacter>
|
<DefaultCharacter>*</DefaultCharacter>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CharacterRegions control what letters are available in the font. Every
|
CharacterRegions control what letters are available in the font. Every
|
||||||
character from Start to End will be built and made available for drawing. The
|
character from Start to End will be built and made available for drawing. The
|
||||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
character set. The characters are ordered according to the Unicode standard.
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
See the documentation for more information.
|
See the documentation for more information.
|
||||||
-->
|
-->
|
||||||
<CharacterRegions>
|
<CharacterRegions>
|
||||||
<CharacterRegion>
|
<CharacterRegion>
|
||||||
<Start> </Start>
|
<Start> </Start>
|
||||||
<End>ɏ</End>
|
<End>ɏ</End>
|
||||||
</CharacterRegion>
|
</CharacterRegion>
|
||||||
</CharacterRegions>
|
</CharacterRegions>
|
||||||
</Asset>
|
</Asset>
|
||||||
</XnaContent>
|
</XnaContent>
|
||||||
|
|
23
Demos/Content/Markdown.md
Normal file
23
Demos/Content/Markdown.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# H1
|
||||||
|
## H2
|
||||||
|
### H3
|
||||||
|
#### H4
|
||||||
|
##### H5
|
||||||
|
###### H6
|
||||||
|
|
||||||
|
Italics with *asterisks* or _underscores_.
|
||||||
|
Bold with **asterisks** or __underscores__.
|
||||||
|
Strikethrough with ~~two tildes~~.
|
||||||
|
|
||||||
|
[I'm an inline-style link](https://www.google.com)
|
||||||
|
<http://www.example.com>
|
||||||
|
|
||||||
|
![](https://raw.githubusercontent.com/Ellpeck/MLEM/main/Media/Logo.png)
|
||||||
|
|
||||||
|
Some `inline code` right here
|
||||||
|
|
||||||
|
```js
|
||||||
|
function codeBlock() {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
|
@ -32,4 +32,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
Demos/Demos.FNA.csproj
Normal file
21
Demos/Demos.FNA.csproj
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>Demos</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.263">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Demos {
|
||||||
|
|
||||||
private static readonly FieldInfo[] EasingFields = typeof(Easings)
|
private static readonly FieldInfo[] EasingFields = typeof(Easings)
|
||||||
.GetFields(BindingFlags.Public | BindingFlags.Static).ToArray();
|
.GetFields(BindingFlags.Public | BindingFlags.Static).ToArray();
|
||||||
private static readonly Easings.Easing[] Easings = EasingFields
|
private static readonly Easings.Easing[] Easings = EasingsDemo.EasingFields
|
||||||
.Select(f => (Easings.Easing) f.GetValue(null)).ToArray();
|
.Select(f => (Easings.Easing) f.GetValue(null)).ToArray();
|
||||||
private Group group;
|
private Group group;
|
||||||
private int current;
|
private int current;
|
||||||
|
@ -27,11 +27,11 @@ namespace Demos {
|
||||||
this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false};
|
this.group = new Group(Anchor.TopCenter, Vector2.One) {CanBeMoused = false};
|
||||||
this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") {
|
this.group.AddChild(new Button(Anchor.AutoCenter, new Vector2(30, 10), "Next") {
|
||||||
OnPressed = e => {
|
OnPressed = e => {
|
||||||
this.current = (this.current + 1) % Easings.Length;
|
this.current = (this.current + 1) % EasingsDemo.Easings.Length;
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingFields[this.current].Name, true));
|
this.group.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => EasingsDemo.EasingFields[this.current].Name, true));
|
||||||
this.UiRoot.AddChild(this.group);
|
this.UiRoot.AddChild(this.group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,11 +43,11 @@ namespace Demos {
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
base.DoDraw(time);
|
base.DoDraw(time);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp);
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
|
||||||
var view = this.GraphicsDevice.Viewport;
|
var view = this.GraphicsDevice.Viewport;
|
||||||
|
|
||||||
// graph the easing function
|
// graph the easing function
|
||||||
var graphEase = Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3);
|
var graphEase = EasingsDemo.Easings[this.current].ScaleInput(0, view.Width).ScaleOutput(-view.Height / 3, view.Height / 3);
|
||||||
for (var x = 0; x < view.Width; x++) {
|
for (var x = 0; x < view.Width; x++) {
|
||||||
var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4);
|
var area = new RectangleF(x - 2, view.Height / 2 - graphEase(x) - 2, 4, 4);
|
||||||
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Green);
|
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), area, Color.Green);
|
||||||
|
@ -55,7 +55,7 @@ namespace Demos {
|
||||||
|
|
||||||
// draw a little dot to show what it would look like
|
// draw a little dot to show what it would look like
|
||||||
this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1;
|
this.progress = (this.progress + (float) time.ElapsedGameTime.TotalSeconds / 2) % 1;
|
||||||
var dotEase = Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4);
|
var dotEase = EasingsDemo.Easings[this.current].AndReverse().ScaleOutput(0, view.Height / 4);
|
||||||
var pos = new RectangleF(view.Width / 2 - 4, view.Height - 20 - dotEase(this.progress), 8, 8);
|
var pos = new RectangleF(view.Width / 2 - 4, view.Height - 20 - dotEase(this.progress), 8, 8);
|
||||||
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red);
|
this.SpriteBatch.Draw(this.SpriteBatch.GetBlankTexture(), pos, Color.Red);
|
||||||
|
|
||||||
|
@ -63,4 +63,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ using MLEM.Textures;
|
||||||
using MLEM.Ui;
|
using MLEM.Ui;
|
||||||
using MLEM.Ui.Elements;
|
using MLEM.Ui.Elements;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
#if !FNA
|
||||||
using MonoGame.Framework.Utilities;
|
using MonoGame.Framework.Utilities;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Demos {
|
namespace Demos {
|
||||||
public class GameImpl : MlemGame {
|
public class GameImpl : MlemGame {
|
||||||
|
@ -23,11 +25,12 @@ namespace Demos {
|
||||||
private TimeSpan secondCounter;
|
private TimeSpan secondCounter;
|
||||||
|
|
||||||
static GameImpl() {
|
static GameImpl() {
|
||||||
Demos.Add("Ui", ("An in-depth demonstration of the MLEM.Ui package and its abilities", game => new UiDemo(game)));
|
GameImpl.Demos.Add("Ui", ("An in-depth demonstration of the MLEM.Ui package and its abilities", game => new UiDemo(game)));
|
||||||
Demos.Add("Easings", ("An example of MLEM's Easings class, an adaptation of easings.net", game => new EasingsDemo(game)));
|
GameImpl.Demos.Add("Text Formatting", ("A demonstration of MLEM's text formatting system", game => new TextFormattingDemo(game)));
|
||||||
Demos.Add("Pathfinding", ("An example of MLEM's A* pathfinding implementation in 2D", game => new PathfindingDemo(game)));
|
GameImpl.Demos.Add("Easings", ("An example of MLEM's Easings class, an adaptation of easings.net", game => new EasingsDemo(game)));
|
||||||
Demos.Add("Animation and Texture Atlas", ("An example of UniformTextureAtlases, SpriteAnimations and SpriteAnimationGroups", game => new AnimationDemo(game)));
|
GameImpl.Demos.Add("Pathfinding", ("An example of MLEM's A* pathfinding implementation in 2D", game => new PathfindingDemo(game)));
|
||||||
Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game)));
|
GameImpl.Demos.Add("Animation and Texture Atlas", ("An example of UniformTextureAtlases, SpriteAnimations and SpriteAnimationGroups", game => new AnimationDemo(game)));
|
||||||
|
GameImpl.Demos.Add("Auto Tiling", ("A demonstration of the AutoTiling class that MLEM provides", game => new AutoTilingDemo(game)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameImpl() {
|
public GameImpl() {
|
||||||
|
@ -45,13 +48,6 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadContent() {
|
protected override void LoadContent() {
|
||||||
// TODO remove with MonoGame 3.8.1 https://github.com/MonoGame/MonoGame/issues/7298
|
|
||||||
if (PlatformInfo.MonoGamePlatform == MonoGamePlatform.DesktopGL) {
|
|
||||||
this.GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
|
|
||||||
this.GraphicsDeviceManager.PreferredBackBufferHeight = 720;
|
|
||||||
this.GraphicsDeviceManager.ApplyChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
base.LoadContent();
|
base.LoadContent();
|
||||||
this.UiSystem.AutoScaleReferenceSize = new Point(1280, 720);
|
this.UiSystem.AutoScaleReferenceSize = new Point(1280, 720);
|
||||||
this.UiSystem.AutoScaleWithScreen = true;
|
this.UiSystem.AutoScaleWithScreen = true;
|
||||||
|
@ -74,7 +70,7 @@ namespace Demos {
|
||||||
|
|
||||||
selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' <l https://github.com/Ellpeck/MLEM/tree/main/Demos>source code</l> for more in-depth explanations of their functionality or the <l https://mlem.ellpeck.de/>website</l> for tutorials and API documentation."));
|
selection.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Select the demo you want to see below using your mouse, touch input, your keyboard or a controller. Check the demos' <l https://github.com/Ellpeck/MLEM/tree/main/Demos>source code</l> for more in-depth explanations of their functionality or the <l https://mlem.ellpeck.de/>website</l> for tutorials and API documentation."));
|
||||||
selection.AddChild(new VerticalSpace(5));
|
selection.AddChild(new VerticalSpace(5));
|
||||||
foreach (var demo in Demos) {
|
foreach (var demo in GameImpl.Demos) {
|
||||||
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
|
selection.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), demo.Key, demo.Value.Item1) {
|
||||||
OnPressed = e => {
|
OnPressed = e => {
|
||||||
selection.IsHidden = true;
|
selection.IsHidden = true;
|
||||||
|
@ -92,9 +88,9 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override UiStyle InitializeDefaultUiStyle(SpriteBatch batch) {
|
protected override UiStyle InitializeDefaultUiStyle(SpriteBatch batch) {
|
||||||
var tex = LoadContent<Texture2D>("Textures/Test");
|
var tex = MlemGame.LoadContent<Texture2D>("Textures/Test");
|
||||||
return new UntexturedStyle(this.SpriteBatch) {
|
return new UntexturedStyle(this.SpriteBatch) {
|
||||||
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")),
|
Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/TestFont")),
|
||||||
TextScale = 0.1F,
|
TextScale = 0.1F,
|
||||||
PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8),
|
PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8),
|
||||||
ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
|
ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
|
||||||
|
@ -128,4 +124,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,14 @@ namespace Demos {
|
||||||
|
|
||||||
// Create a cost function, which determines how expensive (or difficult) it should be to move from a given position
|
// Create a cost function, which determines how expensive (or difficult) it should be to move from a given position
|
||||||
// to the next, adjacent position. In our case, the only restriction should be walls and out-of-bounds positions, which
|
// to the next, adjacent position. In our case, the only restriction should be walls and out-of-bounds positions, which
|
||||||
// both have a cost of AStar2.InfiniteCost, meaning they are completely unwalkable.
|
// both have a cost of AStar2.InfiniteCost, meaning they are completely unwalkable.
|
||||||
// If your game contains harder-to-move-on areas like, say, a muddy pit, you can return a higher cost value for those
|
// If your game contains harder-to-move-on areas like, say, a muddy pit, you can return a higher cost value for those
|
||||||
// locations. If you want to scale your cost function differently, you can specify a different default cost in your
|
// locations. If you want to scale your cost function differently, you can specify a different default cost in your
|
||||||
// pathfinder's constructor
|
// pathfinder's constructor
|
||||||
float Cost(Point pos, Point nextPos) {
|
float Cost(Point pos, Point nextPos) {
|
||||||
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
|
if (nextPos.X < 0 || nextPos.Y < 0 || nextPos.X >= 50 || nextPos.Y >= 50)
|
||||||
return AStar2.InfiniteCost;
|
return float.PositiveInfinity;
|
||||||
return this.world[nextPos.X, nextPos.Y] ? 1 : AStar2.InfiniteCost;
|
return this.world[nextPos.X, nextPos.Y] ? 1 : float.PositiveInfinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually initialize the pathfinder with the cost function, as well as specify if moving diagonally between tiles should be
|
// Actually initialize the pathfinder with the cost function, as well as specify if moving diagonally between tiles should be
|
||||||
|
@ -73,7 +73,7 @@ namespace Demos {
|
||||||
public override void DoDraw(GameTime gameTime) {
|
public override void DoDraw(GameTime gameTime) {
|
||||||
this.GraphicsDevice.Clear(Color.White);
|
this.GraphicsDevice.Clear(Color.White);
|
||||||
|
|
||||||
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(14));
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, null, Matrix.CreateScale(14));
|
||||||
var tex = this.SpriteBatch.GetBlankTexture();
|
var tex = this.SpriteBatch.GetBlankTexture();
|
||||||
// draw the world with simple shapes
|
// draw the world with simple shapes
|
||||||
for (var x = 0; x < 50; x++) {
|
for (var x = 0; x < 50; x++) {
|
||||||
|
@ -87,9 +87,9 @@ namespace Demos {
|
||||||
// in a real game, you'd obviously make your characters walk along the path instead of drawing it
|
// in a real game, you'd obviously make your characters walk along the path instead of drawing it
|
||||||
if (this.path != null) {
|
if (this.path != null) {
|
||||||
for (var i = 1; i < this.path.Count; i++) {
|
for (var i = 1; i < this.path.Count; i++) {
|
||||||
var (firstX, firstY) = this.path[i - 1];
|
var first = this.path[i - 1];
|
||||||
var (secondX, secondY) = this.path[i];
|
var second = this.path[i];
|
||||||
this.SpriteBatch.Draw(tex, RectangleF.FromCorners(new Vector2(firstX + 0.25F, firstY + 0.25F), new Vector2(secondX + 0.75F, secondY + 0.75F)), Color.Blue);
|
this.SpriteBatch.Draw(tex, RectangleF.FromCorners(new Vector2(first.X + 0.25F, first.Y + 0.25F), new Vector2(second.X + 0.75F, second.Y + 0.75F)), Color.Blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.SpriteBatch.End();
|
this.SpriteBatch.End();
|
||||||
|
@ -102,4 +102,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
81
Demos/TextFormattingDemo.cs
Normal file
81
Demos/TextFormattingDemo.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Font;
|
||||||
|
using MLEM.Formatting;
|
||||||
|
using MLEM.Formatting.Codes;
|
||||||
|
using MLEM.Startup;
|
||||||
|
using MLEM.Textures;
|
||||||
|
|
||||||
|
namespace Demos {
|
||||||
|
public class TextFormattingDemo : Demo {
|
||||||
|
|
||||||
|
private const string Text =
|
||||||
|
"MLEM's text formatting system allows for various <b>formatting codes</b> to be applied in the middle of a string. Here's a demonstration of some of them.\n\n" +
|
||||||
|
"You can write in <b>bold</i>, <i>italics</i>, <u>with an underline</u>, <st>strikethrough</st>, with a <s #000000 4>drop shadow</s> whose <s #ff0000 4>color</s> and <s #000000 10>offset</s> you can modify in each application of the code, or with various types of <b>combined <c Pink>formatting</c> codes</b>.\n\n" +
|
||||||
|
"You can apply <c CornflowerBlue>custom</c> <c Yellow>colors</c> to text, including all default <c Orange>MonoGame colors</c> and <c #aabb00>inline custom colors</c>.\n\n" +
|
||||||
|
"You can also use animations like <a wobbly>a wobbly one</a>, as well as create custom ones using the <a wobbly>Code class</a>.\n\n" +
|
||||||
|
"You can also display <i grass> icons in your text!\n\n" +
|
||||||
|
"Additionally, the text formatter has various methods for interacting with the text, like custom behaviors when hovering over certain parts, and more.";
|
||||||
|
private const float Scale = 0.5F;
|
||||||
|
private const float Width = 0.9F;
|
||||||
|
|
||||||
|
private TextFormatter formatter;
|
||||||
|
private TokenizedString tokenizedText;
|
||||||
|
private GenericFont font;
|
||||||
|
|
||||||
|
public TextFormattingDemo(MlemGame game) : base(game) {}
|
||||||
|
|
||||||
|
public override void LoadContent() {
|
||||||
|
this.Game.Window.ClientSizeChanged += this.OnResize;
|
||||||
|
|
||||||
|
// creating a new text formatter as well as a generic font to draw with
|
||||||
|
this.formatter = new TextFormatter();
|
||||||
|
// GenericFont and its subtypes are wrappers around various font classes, including SpriteFont, MonoGame.Extended's BitmapFont and FontStashSharp
|
||||||
|
// supplying a bold and italic version of the font here allows for the bold and italic formatting codes to be used
|
||||||
|
this.font = new GenericSpriteFont(
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFont"),
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFontBold"),
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFontItalic"));
|
||||||
|
|
||||||
|
// adding the image code used in the example to it
|
||||||
|
var testTexture = Demo.LoadContent<Texture2D>("Textures/Test");
|
||||||
|
this.formatter.AddImage("grass", new TextureRegion(testTexture, 0, 0, 8, 8));
|
||||||
|
|
||||||
|
// tokenizing our text and splitting it to fit the screen
|
||||||
|
// we specify our text alignment here too, so that all data is cached correctly for display
|
||||||
|
this.tokenizedText = this.formatter.Tokenize(this.font, TextFormattingDemo.Text, TextAlignment.Center);
|
||||||
|
this.tokenizedText.Split(this.font, this.GraphicsDevice.Viewport.Width * TextFormattingDemo.Width, TextFormattingDemo.Scale, TextAlignment.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DoDraw(GameTime time) {
|
||||||
|
this.GraphicsDevice.Clear(Color.DarkSlateGray);
|
||||||
|
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
|
||||||
|
|
||||||
|
// we draw the tokenized text in the center of the screen
|
||||||
|
// since the text is already center-aligned, we only need to align it on the y axis here
|
||||||
|
var size = this.tokenizedText.Measure(this.font) * TextFormattingDemo.Scale;
|
||||||
|
var pos = new Vector2(this.GraphicsDevice.Viewport.Width / 2, (this.GraphicsDevice.Viewport.Height - size.Y) / 2);
|
||||||
|
this.tokenizedText.Draw(time, this.SpriteBatch, pos, this.font, Color.White, TextFormattingDemo.Scale, 0);
|
||||||
|
|
||||||
|
this.SpriteBatch.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(GameTime time) {
|
||||||
|
// update our tokenized string to animate the animation codes
|
||||||
|
this.tokenizedText.Update(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Clear() {
|
||||||
|
base.Clear();
|
||||||
|
this.Game.Window.ClientSizeChanged -= this.OnResize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnResize(object sender, EventArgs e) {
|
||||||
|
// re-split our text if the window resizes, since it depends on the window size
|
||||||
|
// this doesn't require re-tokenization of the text, since TokenizedString also stores the un-split version
|
||||||
|
this.tokenizedText.Split(this.font, this.GraphicsDevice.Viewport.Width * TextFormattingDemo.Width, TextFormattingDemo.Scale, TextAlignment.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Coroutine;
|
using Coroutine;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
@ -7,13 +8,13 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
using MLEM.Font;
|
using MLEM.Font;
|
||||||
using MLEM.Formatting;
|
using MLEM.Formatting;
|
||||||
using MLEM.Formatting.Codes;
|
|
||||||
using MLEM.Input;
|
using MLEM.Input;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using MLEM.Startup;
|
using MLEM.Startup;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
using MLEM.Ui;
|
using MLEM.Ui;
|
||||||
using MLEM.Ui.Elements;
|
using MLEM.Ui.Elements;
|
||||||
|
using MLEM.Ui.Parsers;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
|
|
||||||
namespace Demos {
|
namespace Demos {
|
||||||
|
@ -26,7 +27,7 @@ namespace Demos {
|
||||||
public UiDemo(MlemGame game) : base(game) {}
|
public UiDemo(MlemGame game) : base(game) {}
|
||||||
|
|
||||||
public override void LoadContent() {
|
public override void LoadContent() {
|
||||||
this.testTexture = LoadContent<Texture2D>("Textures/Test");
|
this.testTexture = Demo.LoadContent<Texture2D>("Textures/Test");
|
||||||
this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8);
|
this.testPatch = new NinePatch(new TextureRegion(this.testTexture, 0, 8, 24, 24), 8);
|
||||||
base.LoadContent();
|
base.LoadContent();
|
||||||
|
|
||||||
|
@ -36,7 +37,10 @@ namespace Demos {
|
||||||
// when using a SpriteFont, use GenericSpriteFont. When using a MonoGame.Extended BitmapFont, use GenericBitmapFont.
|
// when using a SpriteFont, use GenericSpriteFont. When using a MonoGame.Extended BitmapFont, use GenericBitmapFont.
|
||||||
// Wrapping fonts like this allows for both types to be usable within MLEM.Ui easily
|
// Wrapping fonts like this allows for both types to be usable within MLEM.Ui easily
|
||||||
// Supplying a bold and an italic version is optional
|
// Supplying a bold and an italic version is optional
|
||||||
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont"), LoadContent<SpriteFont>("Fonts/TestFontBold"), LoadContent<SpriteFont>("Fonts/TestFontItalic")),
|
Font = new GenericSpriteFont(
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFont"),
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFontBold"),
|
||||||
|
Demo.LoadContent<SpriteFont>("Fonts/TestFontItalic")),
|
||||||
TextScale = 0.1F,
|
TextScale = 0.1F,
|
||||||
PanelTexture = this.testPatch,
|
PanelTexture = this.testPatch,
|
||||||
ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
|
ButtonTexture = new NinePatch(new TextureRegion(this.testTexture, 24, 8, 16, 16), 4),
|
||||||
|
@ -47,7 +51,7 @@ namespace Demos {
|
||||||
CheckboxCheckmark = new TextureRegion(this.testTexture, 24, 0, 8, 8),
|
CheckboxCheckmark = new TextureRegion(this.testTexture, 24, 0, 8, 8),
|
||||||
RadioTexture = new NinePatch(new TextureRegion(this.testTexture, 16, 0, 8, 8), 3),
|
RadioTexture = new NinePatch(new TextureRegion(this.testTexture, 16, 0, 8, 8), 3),
|
||||||
RadioCheckmark = new TextureRegion(this.testTexture, 32, 0, 8, 8),
|
RadioCheckmark = new TextureRegion(this.testTexture, 32, 0, 8, 8),
|
||||||
AdditionalFonts = {{"Monospaced", new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/MonospacedFont"))}},
|
AdditionalFonts = {{"Monospaced", new GenericSpriteFont(Demo.LoadContent<SpriteFont>("Fonts/MonospacedFont"))}},
|
||||||
LinkColor = Color.CornflowerBlue
|
LinkColor = Color.CornflowerBlue
|
||||||
};
|
};
|
||||||
var untexturedStyle = new UntexturedStyle(this.SpriteBatch) {
|
var untexturedStyle = new UntexturedStyle(this.SpriteBatch) {
|
||||||
|
@ -69,7 +73,7 @@ namespace Demos {
|
||||||
// add the root to the demos' ui
|
// add the root to the demos' ui
|
||||||
this.UiRoot.AddChild(this.root);
|
this.UiRoot.AddChild(this.root);
|
||||||
|
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame."));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame and FNA."));
|
||||||
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
|
var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
|
||||||
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
|
||||||
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
|
||||||
|
@ -88,12 +92,7 @@ namespace Demos {
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
|
|
||||||
// a paragraph with formatting codes. To see them all or to add more, check the TextFormatting class
|
// a paragraph with formatting codes. To see them all or to add more, check the TextFormatting class
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Paragraphs can also contain <c Blue>formatting codes</c>, including colors and <i>text styles</i>. The names of all <c Orange>MonoGame Colors</c> can be used, as well as the codes <i>Italic</i>, <b>Bold</b>, <s>Drop Shadow'd</s> and <s><c Pink>mixed formatting</s></c>. You can also add additional fonts for things like\n<f Monospaced>void Code() {\n // Code\n}</f>\n<i>Even <c #ff611f82>inline custom colors</c> work!</i>"));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Paragraphs can also contain <c Blue>formatting codes</c>, including colors and <i>text styles</i>. For more info, check out the <b>text formatting demo</b>!"));
|
||||||
|
|
||||||
// adding some custom image formatting codes
|
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Additionally, you can create custom formatting codes that contain <i Grass> images and more!"));
|
|
||||||
this.UiSystem.TextFormatter.AddImage("Grass", image.Texture);
|
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Defining text animations as formatting codes is also possible, including <a wobbly>wobbly text</a> at <a wobbly 8 0.25>different intensities</a>. Of course, more animations can be added though."));
|
|
||||||
|
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoCenter, 1, "Multiline text input:", true));
|
this.root.AddChild(new Paragraph(Anchor.AutoCenter, 1, "Multiline text input:", true));
|
||||||
|
@ -156,7 +155,7 @@ namespace Demos {
|
||||||
|
|
||||||
// Check the WobbleButton method for an explanation of how this button works
|
// Check the WobbleButton method for an explanation of how this button works
|
||||||
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Wobble Me", "This button wobbles around visually when clicked, but this doesn't affect its actual size and positioning") {
|
||||||
OnPressed = element => CoroutineHandler.Start(WobbleButton(element)),
|
OnPressed = element => CoroutineHandler.Start(UiDemo.WobbleButton(element)),
|
||||||
PositionOffset = new Vector2(0, 1)
|
PositionOffset = new Vector2(0, 1)
|
||||||
});
|
});
|
||||||
// Another button that shows animations!
|
// Another button that shows animations!
|
||||||
|
@ -189,13 +188,13 @@ namespace Demos {
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Progress bars!"));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Progress bars!"));
|
||||||
var bar1 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Right, 10) {PositionOffset = new Vector2(0, 1)});
|
var bar1 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Right, 10) {PositionOffset = new Vector2(0, 1)});
|
||||||
CoroutineHandler.Start(WobbleProgressBar(bar1));
|
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar1));
|
||||||
var bar2 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)});
|
var bar2 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(1, 8), Direction2.Left, 10) {PositionOffset = new Vector2(0, 1)});
|
||||||
CoroutineHandler.Start(WobbleProgressBar(bar2));
|
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar2));
|
||||||
var bar3 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)});
|
var bar3 = this.root.AddChild(new ProgressBar(Anchor.AutoLeft, new Vector2(8, 30), Direction2.Down, 10) {PositionOffset = new Vector2(0, 1)});
|
||||||
CoroutineHandler.Start(WobbleProgressBar(bar3));
|
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar3));
|
||||||
var bar4 = this.root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 0)});
|
var bar4 = this.root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 0)});
|
||||||
CoroutineHandler.Start(WobbleProgressBar(bar4));
|
CoroutineHandler.Start(UiDemo.WobbleProgressBar(bar4));
|
||||||
|
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
var dropdown = this.root.AddChild(new Dropdown(Anchor.AutoLeft, new Vector2(1, 10), "Dropdown Menu"));
|
var dropdown = this.root.AddChild(new Dropdown(Anchor.AutoLeft, new Vector2(1, 10), "Dropdown Menu"));
|
||||||
|
@ -223,6 +222,13 @@ namespace Demos {
|
||||||
alignPar.Alignment = alignment;
|
alignPar.Alignment = alignment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "MLEM.Ui also contains a simple Markdown parser, which can be useful for displaying things like changelogs in your game."));
|
||||||
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
|
var parser = new UiMarkdownParser {GraphicsDevice = this.GraphicsDevice};
|
||||||
|
using (var reader = new StreamReader(TitleContainer.OpenStream("Content/Markdown.md")))
|
||||||
|
parser.ParseInto(reader.ReadToEnd(), this.root);
|
||||||
|
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "The code for this demo contains some examples for how to query element data. This is the output of that:"));
|
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "The code for this demo contains some examples for how to query element data. This is the output of that:"));
|
||||||
|
|
||||||
|
@ -290,4 +296,4 @@ namespace Demos {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# MLEM.Ui
|
# MLEM.Ui
|
||||||
|
|
||||||
**MLEM.Ui** is a Ui framework for MonoGame that features elements with automatic positioning and sizing. It contains various ready-made element types like buttons, paragraphs, text fields and more, along with the ability to easily create custom controls. It supports **mouse**, **keyboard**, **gamepad** and **touch** input with little to no additional setup work required.
|
**MLEM.Ui** is a Ui framework for MonoGame and FNA that features elements with automatic positioning and sizing. It contains various ready-made element types like buttons, paragraphs, text fields and more, along with the ability to easily create custom controls. It supports **mouse**, **keyboard**, **gamepad** and **touch** input with little to no additional setup work required.
|
||||||
|
|
||||||
To see some of what MLEM.Ui can do, you can check out [the demo](https://github.com/Ellpeck/MLEM/blob/main/Demos/UiDemo.cs) as well.
|
To see some of what MLEM.Ui can do, you can check out [the demo](https://github.com/Ellpeck/MLEM/blob/main/Demos/UiDemo.cs) as well.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ public UiSystem UiSystem;
|
||||||
|
|
||||||
protected override void LoadContent() {
|
protected override void LoadContent() {
|
||||||
// Load your other content here
|
// Load your other content here
|
||||||
|
|
||||||
// Initialize the Ui system
|
// Initialize the Ui system
|
||||||
this.UiSystem = new UiSystem(this.Window, this.GraphicsDevice, new UntexturedStyle(this.SpriteBatch));
|
this.UiSystem = new UiSystem(this.Window, this.GraphicsDevice, new UntexturedStyle(this.SpriteBatch));
|
||||||
}
|
}
|
||||||
|
@ -24,26 +24,30 @@ protected override void Update(GameTime gameTime) {
|
||||||
protected override void Draw(GameTime gameTime) {
|
protected override void Draw(GameTime gameTime) {
|
||||||
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
this.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
// Do your regular game drawing here
|
// Do your regular game drawing here
|
||||||
|
|
||||||
// Call Draw at the end to draw the Ui on top of your game
|
// Call Draw at the end to draw the Ui on top of your game
|
||||||
this.UiSystem.Draw(gameTime, this.SpriteBatch);
|
this.UiSystem.Draw(gameTime, this.SpriteBatch);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Text Input
|
### Text Input
|
||||||
On desktop devices, MonoGame provides the `Window.TextInput` event that gets called automatically with the correct characters for the keys that you're pressing, even for non-American keyboards. However, this function doesn't exist on other devices. Similarly, MonoGame provides the `KeyboardInput` class for showing an on-screen keyboard on mobile devices and consoles, but not on desktop.
|
On desktop devices, MonoGame provides the `Window.TextInput` event that gets called automatically with the correct characters for the keys that you're pressing, even for non-American keyboards. However, this function doesn't exist on other devices. Similarly, MonoGame provides the `KeyboardInput` class for showing an on-screen keyboard on mobile devices and consoles, but not on desktop.
|
||||||
|
|
||||||
To make MLEM compatible with all devices without publishing a separate version for each MonoGame platform, you have to set up the `MlemPlatform` class based on the system you're using MLEM.Ui with. This has to be done *before* initializing your `UiSystem`.
|
To make MLEM compatible with all devices without publishing a separate version for each MonoGame platform, you have to set up the `MlemPlatform` class based on the system you're using MLEM.Ui with. This has to be done *before* initializing your `UiSystem`.
|
||||||
|
|
||||||
DesktopGL:
|
DesktopGL and WindowsDX using MonoGame:
|
||||||
```cs
|
```cs
|
||||||
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
||||||
```
|
```
|
||||||
|
Desktop using FNA:
|
||||||
|
```cs
|
||||||
|
MlemPlatform.Current = new MlemPlatform.DesktopFna(a => TextInputEXT.TextInput += a);
|
||||||
|
```
|
||||||
Mobile devices and consoles:
|
Mobile devices and consoles:
|
||||||
```cs
|
```cs
|
||||||
MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l))));
|
MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l))));
|
||||||
```
|
```
|
||||||
If you're not using text input, you can just set the platform to a stub one like so:
|
If you're not using text input, you can leave the platform uninitialized or just set it to a stub one like so:
|
||||||
```cs
|
```cs
|
||||||
MlemPlatform.Current = new MlemPlatform.None();
|
MlemPlatform.Current = new MlemPlatform.None();
|
||||||
```
|
```
|
||||||
|
@ -89,4 +93,4 @@ this.UiSystem.Add("InfoBox", box);
|
||||||
Note that, when setting the width and height of any element, there are some things to note:
|
Note that, when setting the width and height of any element, there are some things to note:
|
||||||
- Each element has a `SetWidthBasedOnChildren` and a `SetHeightBasedOnChildren` property, which allow them to change their size automatically based on their content
|
- Each element has a `SetWidthBasedOnChildren` and a `SetHeightBasedOnChildren` property, which allow them to change their size automatically based on their content
|
||||||
- When specifying a width or height *lower than or equal to 1*, it is seen as a percentage based on the parent's size instead. For example, a paragraph with a width of `0.5F` inside of a panel width a width of `200` will be `100` units wide.
|
- When specifying a width or height *lower than or equal to 1*, it is seen as a percentage based on the parent's size instead. For example, a paragraph with a width of `0.5F` inside of a panel width a width of `200` will be `100` units wide.
|
||||||
- When specifying a width *lower than 0*, it is seen as a percentage based on the element's height, and vice versa. For example, a panel with a width of `200` and a height of `-2` will be `400` units tall.
|
- When specifying a width *lower than 0*, it is seen as a percentage based on the element's height, and vice versa. For example, a panel with a width of `200` and a height of `-2` will be `400` units tall.
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Banner.png)
|
![The MLEM logo](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Banner.png)
|
||||||
|
|
||||||
**MLEM Library for Extending MonoGame** is an addition to the game framework [MonoGame](https://www.monogame.net/) that provides extension methods, quality of life improvements and additional features like a ui system and easy input handling.
|
**MLEM Library for Extending MonoGame and FNA** is a set of multipurpose libraries for the game frameworks [MonoGame](https://www.monogame.net/) and [FNA](https://fna-xna.github.io/) that provides abstractions, quality of life improvements and additional features like an extensive ui system and easy input handling.
|
||||||
|
|
||||||
# What next?
|
# What next?
|
||||||
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
- Get it on [NuGet](https://www.nuget.org/packages?q=mlem)
|
||||||
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de)
|
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de/?q=mlem)
|
||||||
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
||||||
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
||||||
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/release/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/release/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/release/Demos.Android)
|
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/release/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/release/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/release/Demos.Android)
|
||||||
- See [the changelog](https://mlem.ellpeck.de/CHANGELOG.html) for information on updates
|
- See [the changelog](https://mlem.ellpeck.de/CHANGELOG.html) for information on updates
|
||||||
|
|
||||||
# Packages
|
# Packages
|
||||||
- **MLEM** is the base package, which provides extension methods and additional features for MonoGame
|
- **MLEM** is the base package, which provides various small addons and abstractions for MonoGame and FNA, including a text formatting system and simple input handling
|
||||||
- **MLEM.Ui** features a mouse, keyboard, gamepad and touch ready Ui system that features automatic anchoring, sizing and several ready-to-use element types
|
- **MLEM.Ui** provides a mouse, keyboard, gamepad and touch ready Ui system that features automatic anchoring, sizing and several ready-to-use element types
|
||||||
- **MLEM.Extended** ties in with MonoGame.Extended and other MonoGame libraries
|
- **MLEM.Extended** ties in with MonoGame.Extended and other MonoGame and FNA libraries
|
||||||
- **MLEM.Data** provides simple loading and processing of textures and data
|
- **MLEM.Data** provides simple loading and processing of textures and other data, including the ability to load non-XNB content files easily
|
||||||
- **MLEM.Startup** combines MLEM with some other useful libraries into a quick Game startup class
|
- **MLEM.Startup** combines MLEM with some other useful libraries into a quick Game startup class
|
||||||
- **MLEM.Templates** contains cross-platform project templates
|
- **MLEM.Templates** contains cross-platform project templates
|
||||||
|
|
||||||
# Made with MLEM
|
# Made with MLEM
|
||||||
- [A Breath of Spring Air](https://ellpeck.itch.io/a-breath-of-spring-air), a short platformer ([Source](https://git.ellpeck.de/Ellpeck/GreatSpringGameJam))
|
- [A Breath of Spring Air](https://ellpeck.itch.io/a-breath-of-spring-air), a short platformer ([Source](https://git.ellpeck.de/Ellpeck/GreatSpringGameJam))
|
||||||
- [Don't Wake Up](https://ellpeck.itch.io/dont-wake-up), a short puzzle game ([Source](https://github.com/Ellpeck/DontLetGo))
|
- [Don't Wake Up](https://ellpeck.itch.io/dont-wake-up), a short puzzle game ([Source](https://github.com/Ellpeck/DontLetGo))
|
||||||
- [Pong clone](https://github.com/luanfagu/pong), a very simple pong clone ([Source](https://github.com/luanfagu/pong))
|
- [Pong Clone](https://github.com/luanfagu/pong), a very simple pong clone ([Source](https://github.com/luanfagu/pong))
|
||||||
- [Tiny Life](https://tinylifegame.com), an isometric life simulation game ([Modding API](https://github.com/Ellpeck/TinyLifeExampleMod))
|
- [Tiny Life](https://tinylifegame.com), an isometric life simulation game ([Modding API](https://github.com/Ellpeck/TinyLifeExampleMod))
|
||||||
|
|
||||||
If you created a game with the help of MLEM, you can get it added to this list by submitting it on the [issue tracker](https://github.com/Ellpeck/MLEM/issues). If its source is public, other people will be able to use your project as an example, too!
|
If you created a game with the help of MLEM, you can get it added to this list by submitting it on the [issue tracker](https://github.com/Ellpeck/MLEM/issues). If its source is public, other people will be able to use your project as an example, too!
|
||||||
|
@ -38,9 +38,9 @@ MLEM's [text formatting system](https://mlem.ellpeck.de/articles/text_formatting
|
||||||
![An image showing text with various colors and other formatting](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Formatting.png)
|
![An image showing text with various colors and other formatting](https://raw.githubusercontent.com/Ellpeck/MLEM/release/Media/Formatting.png)
|
||||||
|
|
||||||
# Friends of MLEM
|
# Friends of MLEM
|
||||||
There are several other libraries and tools that work well in combination with MonoGame and MLEM. Here are some of them:
|
There are several other libraries and tools that work well in combination with MonoGame, FNA and MLEM. Here are some of them:
|
||||||
- [Contentless](https://github.com/Ellpeck/Contentless), a tool that removes the need to add assets to the MonoGame Content Pipeline manually
|
- [Contentless](https://github.com/Ellpeck/Contentless), a tool that removes the need to add assets to the MonoGame Content Pipeline manually
|
||||||
- [GameBundle](https://github.com/Ellpeck/GameBundle), a tool that packages MonoGame and other .NET Core applications into several distributable formats
|
- [GameBundle](https://github.com/Ellpeck/GameBundle), a tool that packages MonoGame and other .NET applications into several distributable formats
|
||||||
- [MonoGame.Extended](https://github.com/craftworkgames/MonoGame.Extended), a package that also provides several additional features for MonoGame
|
- [MonoGame.Extended](https://github.com/craftworkgames/MonoGame.Extended), a package that also provides several additional features for MonoGame
|
||||||
- [Coroutine](https://github.com/Ellpeck/Coroutine), a package that implements Unity-style coroutines for any project
|
- [Coroutine](https://github.com/Ellpeck/Coroutine), a package that implements Unity-style coroutines for any project
|
||||||
- [Illumilib](https://github.com/Ellpeck/Illumilib), a simple keyboard and mouse lighting library with support for Razer, Logitech and Corsair devices
|
- [Illumilib](https://github.com/Ellpeck/Illumilib), a simple keyboard and mouse lighting library with support for Razer, Logitech and Corsair devices
|
||||||
|
|
1
FNA
Submodule
1
FNA
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 102990f514f1e5bfac07d33f7c33e2e712946da4
|
1
FontStashSharp
Submodule
1
FontStashSharp
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit f0774130cad6cec0b790a58bc7c811a186443fb3
|
5
Jenkinsfile
vendored
5
Jenkinsfile
vendored
|
@ -1,6 +1,11 @@
|
||||||
pipeline {
|
pipeline {
|
||||||
agent any
|
agent any
|
||||||
stages {
|
stages {
|
||||||
|
stage('Submodules') {
|
||||||
|
steps {
|
||||||
|
sh 'git submodule update --init --recursive --force'
|
||||||
|
}
|
||||||
|
}
|
||||||
stage('Cake Build') {
|
stage('Cake Build') {
|
||||||
steps {
|
steps {
|
||||||
sh 'dotnet tool restore'
|
sh 'dotnet tool restore'
|
||||||
|
|
|
@ -23,4 +23,4 @@ namespace MLEM.Data.Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,19 +7,22 @@ using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
namespace MLEM.Data.Content {
|
namespace MLEM.Data.Content {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a version of <see cref="ContentManager"/> that doesn't load content binary <c>xnb</c> files, but rather as their regular formats.
|
/// Represents a version of <see cref="ContentManager"/> that doesn't load content binary <c>xnb</c> files, but rather as their regular formats.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RawContentManager : ContentManager, IGameComponent {
|
public class RawContentManager : ContentManager, IGameComponent {
|
||||||
|
|
||||||
private static List<RawContentReader> readers;
|
private static List<RawContentReader> readers;
|
||||||
|
|
||||||
private readonly List<IDisposable> disposableAssets = new List<IDisposable>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The graphics device that this content manager uses
|
/// The graphics device that this content manager uses
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly GraphicsDevice GraphicsDevice;
|
public readonly GraphicsDevice GraphicsDevice;
|
||||||
|
|
||||||
|
private readonly List<IDisposable> disposableAssets = new List<IDisposable>();
|
||||||
|
#if FNA
|
||||||
|
private Dictionary<string, object> LoadedAssets { get; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new content manager with an optionally specified root directory.
|
/// Creates a new content manager with an optionally specified root directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -50,15 +53,19 @@ namespace MLEM.Data.Content {
|
||||||
/// <param name="originalAssetName">The original name of the asset.</param>
|
/// <param name="originalAssetName">The original name of the asset.</param>
|
||||||
/// <param name="currentAsset">The current asset instance.</param>
|
/// <param name="currentAsset">The current asset instance.</param>
|
||||||
/// <typeparam name="T">The asset's type.</typeparam>
|
/// <typeparam name="T">The asset's type.</typeparam>
|
||||||
protected override void ReloadAsset<T>(string originalAssetName, T currentAsset) {
|
protected
|
||||||
|
#if !FNA
|
||||||
|
override
|
||||||
|
#endif
|
||||||
|
void ReloadAsset<T>(string originalAssetName, T currentAsset) {
|
||||||
this.Read(originalAssetName, currentAsset);
|
this.Read(originalAssetName, currentAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T Read<T>(string assetName, T existing) {
|
private T Read<T>(string assetName, T existing) {
|
||||||
var triedFiles = new List<string>();
|
var triedFiles = new List<string>();
|
||||||
if (readers == null)
|
if (RawContentManager.readers == null)
|
||||||
readers = CollectContentReaders();
|
RawContentManager.readers = RawContentManager.CollectContentReaders();
|
||||||
foreach (var reader in readers) {
|
foreach (var reader in RawContentManager.readers) {
|
||||||
if (!reader.CanRead(typeof(T)))
|
if (!reader.CanRead(typeof(T)))
|
||||||
continue;
|
continue;
|
||||||
foreach (var ext in reader.GetFileExtensions()) {
|
foreach (var ext in reader.GetFileExtensions()) {
|
||||||
|
@ -125,4 +132,4 @@ namespace MLEM.Data.Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,4 +58,4 @@ namespace MLEM.Data.Content {
|
||||||
protected abstract T Read(RawContentManager manager, string assetPath, Stream stream, T existing);
|
protected abstract T Read(RawContentManager manager, string assetPath, Stream stream, T existing);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,4 @@ namespace MLEM.Data.Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace MLEM.Data.Content {
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string[] GetFileExtensions() {
|
public override string[] GetFileExtensions() {
|
||||||
return new[] {"ogg", "wav", "mp3"};
|
return new[] {"wav"};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Extensions;
|
||||||
|
|
||||||
namespace MLEM.Data.Content {
|
namespace MLEM.Data.Content {
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -7,11 +9,26 @@ namespace MLEM.Data.Content {
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) {
|
protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) {
|
||||||
|
#if !FNA
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
existing.Reload(stream);
|
existing.Reload(stream);
|
||||||
return existing;
|
return existing;
|
||||||
} else {
|
} else
|
||||||
return Texture2D.FromStream(manager.GraphicsDevice, stream);
|
#endif
|
||||||
|
{
|
||||||
|
// premultiply the texture's color to be in line with the pipeline's texture reader
|
||||||
|
using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream)) {
|
||||||
|
var ret = new Texture2D(manager.GraphicsDevice, texture.Width, texture.Height);
|
||||||
|
using (var textureData = texture.GetTextureData()) {
|
||||||
|
using (var retData = ret.GetTextureData()) {
|
||||||
|
for (var x = 0; x < ret.Width; x++) {
|
||||||
|
for (var y = 0; y < ret.Height; y++)
|
||||||
|
retData[x, y] = Color.FromNonPremultiplied(textureData[x, y].ToVector4());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,4 +38,4 @@ namespace MLEM.Data.Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,4 @@ namespace MLEM.Data.Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="content">The content manager to add the json serializer to</param>
|
/// <param name="content">The content manager to add the json serializer to</param>
|
||||||
/// <param name="serializer">The json serializer to add</param>
|
/// <param name="serializer">The json serializer to add</param>
|
||||||
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
|
public static void SetJsonSerializer(this ContentManager content, JsonSerializer serializer) {
|
||||||
Serializers[content] = serializer;
|
ContentExtensions.Serializers[content] = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -31,7 +31,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="content">The content manager whose serializer to get</param>
|
/// <param name="content">The content manager whose serializer to get</param>
|
||||||
/// <returns>The content manager's serializer</returns>
|
/// <returns>The content manager's serializer</returns>
|
||||||
public static JsonSerializer GetJsonSerializer(this ContentManager content) {
|
public static JsonSerializer GetJsonSerializer(this ContentManager content) {
|
||||||
if (!Serializers.TryGetValue(content, out var serializer)) {
|
if (!ContentExtensions.Serializers.TryGetValue(content, out var serializer)) {
|
||||||
serializer = JsonConverters.AddAll(new JsonSerializer());
|
serializer = JsonConverters.AddAll(new JsonSerializer());
|
||||||
content.SetJsonSerializer(serializer);
|
content.SetJsonSerializer(serializer);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="content">The content manager to add the converter to</param>
|
/// <param name="content">The content manager to add the converter to</param>
|
||||||
/// <param name="converter">The converter to add</param>
|
/// <param name="converter">The converter to add</param>
|
||||||
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
|
public static void AddJsonConverter(this ContentManager content, JsonConverter converter) {
|
||||||
var serializer = GetJsonSerializer(content);
|
var serializer = content.GetJsonSerializer();
|
||||||
serializer.Converters.Add(converter);
|
serializer.Converters.Add(converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace MLEM.Data {
|
||||||
public static T LoadJson<T>(this ContentManager content, string name, string[] extensions = null, JsonSerializer serializer = null) {
|
public static T LoadJson<T>(this ContentManager content, string name, string[] extensions = null, JsonSerializer serializer = null) {
|
||||||
var triedFiles = new List<string>();
|
var triedFiles = new List<string>();
|
||||||
var serializerToUse = serializer ?? content.GetJsonSerializer();
|
var serializerToUse = serializer ?? content.GetJsonSerializer();
|
||||||
foreach (var extension in extensions ?? JsonExtensions) {
|
foreach (var extension in extensions ?? ContentExtensions.JsonExtensions) {
|
||||||
var file = Path.Combine(content.RootDirectory, name + extension);
|
var file = Path.Combine(content.RootDirectory, name + extension);
|
||||||
triedFiles.Add(file);
|
triedFiles.Add(file);
|
||||||
try {
|
try {
|
||||||
|
@ -74,4 +74,4 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||||
/// <returns>A shallow copy of the object</returns>
|
/// <returns>A shallow copy of the object</returns>
|
||||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||||
public static T Copy<T>(this T obj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
public static T Copy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||||
var copy = (T) Construct(typeof(T), flags);
|
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
|
||||||
obj.CopyInto(copy, flags, fieldInclusion);
|
obj.CopyInto(copy, flags, fieldInclusion);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||||
/// <returns>A deep copy of the object</returns>
|
/// <returns>A deep copy of the object</returns>
|
||||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||||
public static T DeepCopy<T>(this T obj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
public static T DeepCopy<T>(this T obj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||||
var copy = (T) Construct(typeof(T), flags);
|
var copy = (T) CopyExtensions.Construct(typeof(T), flags);
|
||||||
obj.DeepCopyInto(copy, flags, fieldInclusion);
|
obj.DeepCopyInto(copy, flags, fieldInclusion);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
|
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
|
||||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||||
public static void CopyInto<T>(this T obj, T otherObj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
public static void CopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||||
foreach (var field in typeof(T).GetFields(flags)) {
|
foreach (var field in typeof(T).GetFields(flags)) {
|
||||||
if (fieldInclusion == null || fieldInclusion(field))
|
if (fieldInclusion == null || fieldInclusion(field))
|
||||||
field.SetValue(otherObj, field.GetValue(obj));
|
field.SetValue(otherObj, field.GetValue(obj));
|
||||||
|
@ -71,7 +71,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
|
/// <param name="fieldInclusion">A predicate that determines whether or not the given field should be copied. If null, all fields will be copied.</param>
|
||||||
/// <typeparam name="T">The type of the object to copy</typeparam>
|
/// <typeparam name="T">The type of the object to copy</typeparam>
|
||||||
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
[Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||||
public static void DeepCopyInto<T>(this T obj, T otherObj, BindingFlags flags = DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
public static void DeepCopyInto<T>(this T obj, T otherObj, BindingFlags flags = CopyExtensions.DefaultFlags, Predicate<FieldInfo> fieldInclusion = null) {
|
||||||
foreach (var field in obj.GetType().GetFields(flags)) {
|
foreach (var field in obj.GetType().GetFields(flags)) {
|
||||||
if (fieldInclusion != null && !fieldInclusion(field))
|
if (fieldInclusion != null && !fieldInclusion(field))
|
||||||
continue;
|
continue;
|
||||||
|
@ -83,7 +83,7 @@ namespace MLEM.Data {
|
||||||
var otherVal = field.GetValue(otherObj);
|
var otherVal = field.GetValue(otherObj);
|
||||||
// if the object we want to copy into doesn't have a value yet, we create one
|
// if the object we want to copy into doesn't have a value yet, we create one
|
||||||
if (otherVal == null) {
|
if (otherVal == null) {
|
||||||
otherVal = Construct(field.FieldType, flags);
|
otherVal = CopyExtensions.Construct(field.FieldType, flags);
|
||||||
field.SetValue(otherObj, otherVal);
|
field.SetValue(otherObj, otherVal);
|
||||||
}
|
}
|
||||||
val.DeepCopyInto(otherVal, flags);
|
val.DeepCopyInto(otherVal, flags);
|
||||||
|
@ -92,7 +92,7 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object Construct(Type t, BindingFlags flags) {
|
private static object Construct(Type t, BindingFlags flags) {
|
||||||
if (!ConstructorCache.TryGetValue(t, out var constructor)) {
|
if (!CopyExtensions.ConstructorCache.TryGetValue(t, out var constructor)) {
|
||||||
var constructors = t.GetConstructors(flags);
|
var constructors = t.GetConstructors(flags);
|
||||||
// find a contructor with the correct attribute
|
// find a contructor with the correct attribute
|
||||||
constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
|
constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
|
||||||
|
@ -104,7 +104,7 @@ namespace MLEM.Data {
|
||||||
constructor = constructors.FirstOrDefault();
|
constructor = constructors.FirstOrDefault();
|
||||||
if (constructor == null)
|
if (constructor == null)
|
||||||
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
|
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
|
||||||
ConstructorCache.Add(t, constructor);
|
CopyExtensions.ConstructorCache.Add(t, constructor);
|
||||||
}
|
}
|
||||||
return constructor.Invoke(new object[constructor.GetParameters().Length]);
|
return constructor.Invoke(new object[constructor.GetParameters().Length]);
|
||||||
}
|
}
|
||||||
|
@ -116,4 +116,4 @@ namespace MLEM.Data {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Constructor), Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
[AttributeUsage(AttributeTargets.Constructor), Obsolete("CopyExtensions has major flaws and insufficient speed compared to other libraries specifically designed for copying objects.")]
|
||||||
public class CopyConstructorAttribute : Attribute {}
|
public class CopyConstructorAttribute : Attribute {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -5,12 +6,13 @@ using System.Text.RegularExpressions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Content;
|
using Microsoft.Xna.Framework.Content;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using MLEM.Extensions;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// This class represents an atlas of <see cref="TextureRegion"/> objects which are loaded from a special texture atlas file.
|
/// This class represents an atlas of <see cref="TextureRegion"/> objects which are loaded from a special texture atlas file.
|
||||||
/// To load a data texture atlas, you can use <see cref="DataTextureAtlasExtensions.LoadTextureAtlas"/>.
|
/// To load a data texture atlas, you can use <see cref="DataTextureAtlasExtensions.LoadTextureAtlas"/>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
|
@ -50,9 +52,13 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns an enumerable of all of the <see cref="TextureRegion"/>s in this atlas.
|
/// Returns an enumerable of all of the <see cref="TextureRegion"/> values in this atlas.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<TextureRegion> Regions => this.regions.Values;
|
public IEnumerable<TextureRegion> Regions => this.regions.Values;
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerable of all of the <see cref="TextureRegion"/> names in this atlas.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<string> RegionNames => this.regions.Keys;
|
||||||
|
|
||||||
private readonly Dictionary<string, TextureRegion> regions = new Dictionary<string, TextureRegion>();
|
private readonly Dictionary<string, TextureRegion> regions = new Dictionary<string, TextureRegion>();
|
||||||
|
|
||||||
|
@ -79,9 +85,8 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
var atlas = new DataTextureAtlas(texture);
|
var atlas = new DataTextureAtlas(texture);
|
||||||
|
|
||||||
// parse each texture region: "<name> loc <u> <v> <w> <h> [piv <px> <py>] [off <ox> <oy>]"
|
// parse each texture region: "<names> loc <u> <v> <w> <h> [piv <px> <py>] [off <ox> <oy>]"
|
||||||
foreach (Match match in Regex.Matches(text, @"(.+)\W+loc\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W*(?:piv\W+([0-9.]+)\W+([0-9.]+))?\W*(?:off\W+([0-9.]+)\W+([0-9.]+))?")) {
|
foreach (Match match in Regex.Matches(text, @"(.+)\W+loc\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W+([0-9]+)\W*(?:piv\W+([0-9.]+)\W+([0-9.]+))?\W*(?:off\W+([0-9.]+)\W+([0-9.]+))?")) {
|
||||||
var name = match.Groups[1].Value.Trim();
|
|
||||||
// offset
|
// offset
|
||||||
var off = !match.Groups[8].Success ? Vector2.Zero : new Vector2(
|
var off = !match.Groups[8].Success ? Vector2.Zero : new Vector2(
|
||||||
float.Parse(match.Groups[8].Value, CultureInfo.InvariantCulture),
|
float.Parse(match.Groups[8].Value, CultureInfo.InvariantCulture),
|
||||||
|
@ -91,18 +96,23 @@ namespace MLEM.Data {
|
||||||
var loc = new Rectangle(
|
var loc = new Rectangle(
|
||||||
int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value),
|
int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value),
|
||||||
int.Parse(match.Groups[4].Value), int.Parse(match.Groups[5].Value));
|
int.Parse(match.Groups[4].Value), int.Parse(match.Groups[5].Value));
|
||||||
loc.Offset(off);
|
loc.Offset(off.ToPoint());
|
||||||
|
|
||||||
// pivot
|
// pivot
|
||||||
var piv = !match.Groups[6].Success ? Vector2.Zero : off + new Vector2(
|
var piv = !match.Groups[6].Success ? Vector2.Zero : off + new Vector2(
|
||||||
float.Parse(match.Groups[6].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.X),
|
float.Parse(match.Groups[6].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.X),
|
||||||
float.Parse(match.Groups[7].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.Y));
|
float.Parse(match.Groups[7].Value, CultureInfo.InvariantCulture) - (pivotRelative ? 0 : loc.Y));
|
||||||
|
|
||||||
var region = new TextureRegion(texture, loc) {
|
foreach (var name in Regex.Split(match.Groups[1].Value, @"\W")) {
|
||||||
PivotPixels = piv,
|
var trimmed = name.Trim();
|
||||||
Name = name
|
if (trimmed.Length <= 0)
|
||||||
};
|
continue;
|
||||||
atlas.regions.Add(name, region);
|
var region = new TextureRegion(texture, loc) {
|
||||||
|
PivotPixels = piv,
|
||||||
|
Name = trimmed
|
||||||
|
};
|
||||||
|
atlas.regions.Add(trimmed, region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return atlas;
|
return atlas;
|
||||||
|
@ -129,4 +139,4 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace MLEM.Data {
|
||||||
if (this.allFlagsCache == null)
|
if (this.allFlagsCache == null)
|
||||||
this.allFlagsCache = new Dictionary<DynamicEnum, bool>();
|
this.allFlagsCache = new Dictionary<DynamicEnum, bool>();
|
||||||
if (!this.allFlagsCache.TryGetValue(flags, out var ret)) {
|
if (!this.allFlagsCache.TryGetValue(flags, out var ret)) {
|
||||||
ret = (GetValue(this) & GetValue(flags)) == GetValue(flags);
|
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) == DynamicEnum.GetValue(flags);
|
||||||
this.allFlagsCache.Add(flags, ret);
|
this.allFlagsCache.Add(flags, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -76,7 +76,7 @@ namespace MLEM.Data {
|
||||||
if (this.anyFlagsCache == null)
|
if (this.anyFlagsCache == null)
|
||||||
this.anyFlagsCache = new Dictionary<DynamicEnum, bool>();
|
this.anyFlagsCache = new Dictionary<DynamicEnum, bool>();
|
||||||
if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) {
|
if (!this.anyFlagsCache.TryGetValue(flags, out var ret)) {
|
||||||
ret = (GetValue(this) & GetValue(flags)) != 0;
|
ret = (DynamicEnum.GetValue(this) & DynamicEnum.GetValue(flags)) != 0;
|
||||||
this.anyFlagsCache.Add(flags, ret);
|
this.anyFlagsCache.Add(flags, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -87,13 +87,13 @@ namespace MLEM.Data {
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
if (this.name == null) {
|
if (this.name == null) {
|
||||||
var included = new List<DynamicEnum>();
|
var included = new List<DynamicEnum>();
|
||||||
if (GetValue(this) != 0) {
|
if (DynamicEnum.GetValue(this) != 0) {
|
||||||
foreach (var v in GetValues(this.GetType())) {
|
foreach (var v in DynamicEnum.GetValues(this.GetType())) {
|
||||||
if (this.HasFlag(v) && GetValue(v) != 0)
|
if (this.HasFlag(v) && DynamicEnum.GetValue(v) != 0)
|
||||||
included.Add(v);
|
included.Add(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.name = included.Count > 0 ? string.Join(" | ", included) : GetValue(this).ToString();
|
this.name = included.Count > 0 ? string.Join(" | ", included) : DynamicEnum.GetValue(this).ToString();
|
||||||
}
|
}
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ namespace MLEM.Data {
|
||||||
/// <returns>The newly created enum value</returns>
|
/// <returns>The newly created enum value</returns>
|
||||||
/// <exception cref="ArgumentException">Thrown if the name or value passed are already present</exception>
|
/// <exception cref="ArgumentException">Thrown if the name or value passed are already present</exception>
|
||||||
public static T Add<T>(string name, BigInteger value) where T : DynamicEnum {
|
public static T Add<T>(string name, BigInteger value) where T : DynamicEnum {
|
||||||
var storage = GetStorage(typeof(T));
|
var storage = DynamicEnum.GetStorage(typeof(T));
|
||||||
|
|
||||||
// cached parsed values and names might be incomplete with new values
|
// cached parsed values and names might be incomplete with new values
|
||||||
storage.ClearCaches();
|
storage.ClearCaches();
|
||||||
|
@ -119,7 +119,7 @@ namespace MLEM.Data {
|
||||||
throw new ArgumentException($"Duplicate name {name}", nameof(name));
|
throw new ArgumentException($"Duplicate name {name}", nameof(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret = Construct(typeof(T), name, value);
|
var ret = DynamicEnum.Construct(typeof(T), name, value);
|
||||||
storage.Values.Add(value, ret);
|
storage.Values.Add(value, ret);
|
||||||
return (T) ret;
|
return (T) ret;
|
||||||
}
|
}
|
||||||
|
@ -134,9 +134,9 @@ namespace MLEM.Data {
|
||||||
/// <returns>The newly created enum value</returns>
|
/// <returns>The newly created enum value</returns>
|
||||||
public static T AddValue<T>(string name) where T : DynamicEnum {
|
public static T AddValue<T>(string name) where T : DynamicEnum {
|
||||||
BigInteger value = 0;
|
BigInteger value = 0;
|
||||||
while (GetStorage(typeof(T)).Values.ContainsKey(value))
|
while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||||
value++;
|
value++;
|
||||||
return Add<T>(name, value);
|
return DynamicEnum.Add<T>(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -149,9 +149,9 @@ namespace MLEM.Data {
|
||||||
/// <returns>The newly created enum value</returns>
|
/// <returns>The newly created enum value</returns>
|
||||||
public static T AddFlag<T>(string name) where T : DynamicEnum {
|
public static T AddFlag<T>(string name) where T : DynamicEnum {
|
||||||
BigInteger value = 1;
|
BigInteger value = 1;
|
||||||
while (GetStorage(typeof(T)).Values.ContainsKey(value))
|
while (DynamicEnum.GetStorage(typeof(T)).Values.ContainsKey(value))
|
||||||
value <<= 1;
|
value <<= 1;
|
||||||
return Add<T>(name, value);
|
return DynamicEnum.Add<T>(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -161,7 +161,7 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type whose values to get</typeparam>
|
/// <typeparam name="T">The type whose values to get</typeparam>
|
||||||
/// <returns>The defined values for the given type</returns>
|
/// <returns>The defined values for the given type</returns>
|
||||||
public static IEnumerable<T> GetValues<T>() where T : DynamicEnum {
|
public static IEnumerable<T> GetValues<T>() where T : DynamicEnum {
|
||||||
return GetValues(typeof(T)).Cast<T>();
|
return DynamicEnum.GetValues(typeof(T)).Cast<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -171,7 +171,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="type">The type whose values to get</param>
|
/// <param name="type">The type whose values to get</param>
|
||||||
/// <returns>The defined values for the given type</returns>
|
/// <returns>The defined values for the given type</returns>
|
||||||
public static IEnumerable<DynamicEnum> GetValues(Type type) {
|
public static IEnumerable<DynamicEnum> GetValues(Type type) {
|
||||||
return GetStorage(type).Values.Values;
|
return DynamicEnum.GetStorage(type).Values.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -182,9 +182,9 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the values</typeparam>
|
/// <typeparam name="T">The type of the values</typeparam>
|
||||||
/// <returns>The bitwise OR (|) combination</returns>
|
/// <returns>The bitwise OR (|) combination</returns>
|
||||||
public static T Or<T>(T left, T right) where T : DynamicEnum {
|
public static T Or<T>(T left, T right) where T : DynamicEnum {
|
||||||
var cache = GetStorage(typeof(T)).OrCache;
|
var cache = DynamicEnum.GetStorage(typeof(T)).OrCache;
|
||||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||||
ret = GetEnumValue<T>(GetValue(left) | GetValue(right));
|
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) | DynamicEnum.GetValue(right));
|
||||||
cache.Add((left, right), ret);
|
cache.Add((left, right), ret);
|
||||||
}
|
}
|
||||||
return (T) ret;
|
return (T) ret;
|
||||||
|
@ -198,9 +198,9 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the values</typeparam>
|
/// <typeparam name="T">The type of the values</typeparam>
|
||||||
/// <returns>The bitwise AND (&) combination</returns>
|
/// <returns>The bitwise AND (&) combination</returns>
|
||||||
public static T And<T>(T left, T right) where T : DynamicEnum {
|
public static T And<T>(T left, T right) where T : DynamicEnum {
|
||||||
var cache = GetStorage(typeof(T)).AndCache;
|
var cache = DynamicEnum.GetStorage(typeof(T)).AndCache;
|
||||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||||
ret = GetEnumValue<T>(GetValue(left) & GetValue(right));
|
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) & DynamicEnum.GetValue(right));
|
||||||
cache.Add((left, right), ret);
|
cache.Add((left, right), ret);
|
||||||
}
|
}
|
||||||
return (T) ret;
|
return (T) ret;
|
||||||
|
@ -214,9 +214,9 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the values</typeparam>
|
/// <typeparam name="T">The type of the values</typeparam>
|
||||||
/// <returns>The bitwise XOR (^) combination</returns>
|
/// <returns>The bitwise XOR (^) combination</returns>
|
||||||
public static T Xor<T>(T left, T right) where T : DynamicEnum {
|
public static T Xor<T>(T left, T right) where T : DynamicEnum {
|
||||||
var cache = GetStorage(typeof(T)).XorCache;
|
var cache = DynamicEnum.GetStorage(typeof(T)).XorCache;
|
||||||
if (!cache.TryGetValue((left, right), out var ret)) {
|
if (!cache.TryGetValue((left, right), out var ret)) {
|
||||||
ret = GetEnumValue<T>(GetValue(left) ^ GetValue(right));
|
ret = DynamicEnum.GetEnumValue<T>(DynamicEnum.GetValue(left) ^ DynamicEnum.GetValue(right));
|
||||||
cache.Add((left, right), ret);
|
cache.Add((left, right), ret);
|
||||||
}
|
}
|
||||||
return (T) ret;
|
return (T) ret;
|
||||||
|
@ -229,9 +229,9 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the values</typeparam>
|
/// <typeparam name="T">The type of the values</typeparam>
|
||||||
/// <returns>The bitwise NEG (~) value</returns>
|
/// <returns>The bitwise NEG (~) value</returns>
|
||||||
public static T Neg<T>(T value) where T : DynamicEnum {
|
public static T Neg<T>(T value) where T : DynamicEnum {
|
||||||
var cache = GetStorage(typeof(T)).NegCache;
|
var cache = DynamicEnum.GetStorage(typeof(T)).NegCache;
|
||||||
if (!cache.TryGetValue(value, out var ret)) {
|
if (!cache.TryGetValue(value, out var ret)) {
|
||||||
ret = GetEnumValue<T>(~GetValue(value));
|
ret = DynamicEnum.GetEnumValue<T>(~DynamicEnum.GetValue(value));
|
||||||
cache.Add(value, ret);
|
cache.Add(value, ret);
|
||||||
}
|
}
|
||||||
return (T) ret;
|
return (T) ret;
|
||||||
|
@ -253,7 +253,7 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type that the returned dynamic enum should have</typeparam>
|
/// <typeparam name="T">The type that the returned dynamic enum should have</typeparam>
|
||||||
/// <returns>The defined or combined dynamic enum value</returns>
|
/// <returns>The defined or combined dynamic enum value</returns>
|
||||||
public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum {
|
public static T GetEnumValue<T>(BigInteger value) where T : DynamicEnum {
|
||||||
return (T) GetEnumValue(typeof(T), value);
|
return (T) DynamicEnum.GetEnumValue(typeof(T), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -263,7 +263,7 @@ namespace MLEM.Data {
|
||||||
/// <param name="value">The value whose dynamic enum value to get</param>
|
/// <param name="value">The value whose dynamic enum value to get</param>
|
||||||
/// <returns>The defined or combined dynamic enum value</returns>
|
/// <returns>The defined or combined dynamic enum value</returns>
|
||||||
public static DynamicEnum GetEnumValue(Type type, BigInteger value) {
|
public static DynamicEnum GetEnumValue(Type type, BigInteger value) {
|
||||||
var storage = GetStorage(type);
|
var storage = DynamicEnum.GetStorage(type);
|
||||||
|
|
||||||
// get the defined value if it exists
|
// get the defined value if it exists
|
||||||
if (storage.Values.TryGetValue(value, out var defined))
|
if (storage.Values.TryGetValue(value, out var defined))
|
||||||
|
@ -271,7 +271,7 @@ namespace MLEM.Data {
|
||||||
|
|
||||||
// otherwise, cache the combined value
|
// otherwise, cache the combined value
|
||||||
if (!storage.FlagCache.TryGetValue(value, out var combined)) {
|
if (!storage.FlagCache.TryGetValue(value, out var combined)) {
|
||||||
combined = Construct(type, null, value);
|
combined = DynamicEnum.Construct(type, null, value);
|
||||||
storage.FlagCache.Add(value, combined);
|
storage.FlagCache.Add(value, combined);
|
||||||
}
|
}
|
||||||
return combined;
|
return combined;
|
||||||
|
@ -286,7 +286,7 @@ namespace MLEM.Data {
|
||||||
/// <typeparam name="T">The type of the dynamic enum value to parse</typeparam>
|
/// <typeparam name="T">The type of the dynamic enum value to parse</typeparam>
|
||||||
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
||||||
public static T Parse<T>(string strg) where T : DynamicEnum {
|
public static T Parse<T>(string strg) where T : DynamicEnum {
|
||||||
return (T) Parse(typeof(T), strg);
|
return (T) DynamicEnum.Parse(typeof(T), strg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -297,28 +297,28 @@ namespace MLEM.Data {
|
||||||
/// <param name="strg">The string to parse into a dynamic enum value</param>
|
/// <param name="strg">The string to parse into a dynamic enum value</param>
|
||||||
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
/// <returns>The parsed enum value, or null if parsing fails</returns>
|
||||||
public static DynamicEnum Parse(Type type, string strg) {
|
public static DynamicEnum Parse(Type type, string strg) {
|
||||||
var cache = GetStorage(type).ParseCache;
|
var cache = DynamicEnum.GetStorage(type).ParseCache;
|
||||||
if (!cache.TryGetValue(strg, out var cached)) {
|
if (!cache.TryGetValue(strg, out var cached)) {
|
||||||
BigInteger? accum = null;
|
BigInteger? accum = null;
|
||||||
foreach (var val in strg.Split('|')) {
|
foreach (var val in strg.Split('|')) {
|
||||||
foreach (var defined in GetValues(type)) {
|
foreach (var defined in DynamicEnum.GetValues(type)) {
|
||||||
if (defined.name == val.Trim()) {
|
if (defined.name == val.Trim()) {
|
||||||
accum = (accum ?? 0) | GetValue(defined);
|
accum = (accum ?? 0) | DynamicEnum.GetValue(defined);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (accum != null)
|
if (accum != null)
|
||||||
cached = GetEnumValue(type, accum.Value);
|
cached = DynamicEnum.GetEnumValue(type, accum.Value);
|
||||||
cache.Add(strg, cached);
|
cache.Add(strg, cached);
|
||||||
}
|
}
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Storage GetStorage(Type type) {
|
private static Storage GetStorage(Type type) {
|
||||||
if (!Storages.TryGetValue(type, out var storage)) {
|
if (!DynamicEnum.Storages.TryGetValue(type, out var storage)) {
|
||||||
storage = new Storage();
|
storage = new Storage();
|
||||||
Storages.Add(type, storage);
|
DynamicEnum.Storages.Add(type, storage);
|
||||||
}
|
}
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
@ -349,4 +349,4 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,4 +29,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,4 +27,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ namespace MLEM.Data.Json {
|
||||||
/// <param name="serializer">The serializer to add the converters to</param>
|
/// <param name="serializer">The serializer to add the converters to</param>
|
||||||
/// <returns>The given serializer, for chaining</returns>
|
/// <returns>The given serializer, for chaining</returns>
|
||||||
public static JsonSerializer AddAll(JsonSerializer serializer) {
|
public static JsonSerializer AddAll(JsonSerializer serializer) {
|
||||||
foreach (var converter in Converters)
|
foreach (var converter in JsonConverters.Converters)
|
||||||
serializer.Converters.Add(converter);
|
serializer.Converters.Add(converter);
|
||||||
return serializer;
|
return serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,4 +60,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace MLEM.Data.Json {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">The type that the dictionary is declared in</param>
|
/// <param name="type">The type that the dictionary is declared in</param>
|
||||||
/// <param name="memberName">The name of the dictionary itself</param>
|
/// <param name="memberName">The name of the dictionary itself</param>
|
||||||
public StaticJsonConverter(Type type, string memberName) : this(GetEntries(type, memberName)) {}
|
public StaticJsonConverter(Type type, string memberName) : this(StaticJsonConverter<T>.GetEntries(type, memberName)) {}
|
||||||
|
|
||||||
/// <summary>Writes the JSON representation of the object.</summary>
|
/// <summary>Writes the JSON representation of the object.</summary>
|
||||||
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
|
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
|
||||||
|
@ -65,4 +65,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,4 @@ namespace MLEM.Data.Json {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
MLEM.Data/MLEM.Data.FNA.csproj
Normal file
45
MLEM.Data/MLEM.Data.FNA.csproj
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Data</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>Simple loading and processing of textures and other data for FNA, including the ability to load non-XNB content files easily</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions data serialize</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
||||||
|
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -3,11 +3,12 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Ellpeck</Authors>
|
<Authors>Ellpeck</Authors>
|
||||||
<Description>Simple loading and processing of textures and data for MLEM Library for Extending MonoGame</Description>
|
<Description>Simple loading and processing of textures and other data for MonoGame, including the ability to load non-XNB content files easily</Description>
|
||||||
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
<PackageTags>monogame ellpeck mlem utility extensions data serialize</PackageTags>
|
<PackageTags>monogame ellpeck mlem utility extensions data serialize</PackageTags>
|
||||||
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
@ -15,12 +16,11 @@
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageIcon>Logo.png</PackageIcon>
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<NoWarn>NU1701</NoWarn>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
<ProjectReference Include="..\MLEM\MLEM.csproj" />
|
||||||
|
|
||||||
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
<!--TODO remove lidgren support eventually (methods marked as obsolete since 5.2.0)-->
|
||||||
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
<PackageReference Include="Lidgren.Network" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
@ -35,9 +35,9 @@
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -100,4 +100,4 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,4 +117,4 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
using MLEM.Textures;
|
using MLEM.Textures;
|
||||||
|
using static MLEM.Extensions.TextureExtensions;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -33,7 +34,10 @@ namespace MLEM.Data {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime;
|
public TimeSpan LastTotalTime => this.LastCalculationTime + this.LastPackTime;
|
||||||
|
|
||||||
private readonly List<Request> textures = new List<Request>();
|
private readonly List<Request> texturesToPack = new List<Request>();
|
||||||
|
private readonly List<Request> alreadyPackedTextures = new List<Request>();
|
||||||
|
private readonly Dictionary<Point, Point> firstPossiblePosForSizeCache = new Dictionary<Point, Point>();
|
||||||
|
private readonly Dictionary<Texture2D, TextureData> dataCache = new Dictionary<Texture2D, TextureData>();
|
||||||
private readonly bool autoIncreaseMaxWidth;
|
private readonly bool autoIncreaseMaxWidth;
|
||||||
private readonly bool forcePowerOfTwo;
|
private readonly bool forcePowerOfTwo;
|
||||||
private readonly bool forceSquare;
|
private readonly bool forceSquare;
|
||||||
|
@ -42,13 +46,13 @@ namespace MLEM.Data {
|
||||||
private int maxWidth;
|
private int maxWidth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new runtime texture packer with the given settings
|
/// Creates a new runtime texture packer with the given settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="maxWidth">The maximum width that the packed texture can have. Defaults to 2048.</param>
|
/// <param name="maxWidth">The maximum width that the packed texture can have. Defaults to 2048.</param>
|
||||||
/// <param name="autoIncreaseMaxWidth">Whether the maximum width should be increased if there is a texture to be packed that is wider than <see cref="maxWidth"/>. Defaults to false.</param>
|
/// <param name="autoIncreaseMaxWidth">Whether the maximum width should be increased if there is a texture to be packed that is wider than <see cref="maxWidth"/>. Defaults to false.</param>
|
||||||
/// <param name="forcePowerOfTwo">Whether the resulting <see cref="PackedTexture"/> should have a width and height that is a power of two</param>
|
/// <param name="forcePowerOfTwo">Whether the resulting <see cref="PackedTexture"/> should have a width and height that is a power of two.</param>
|
||||||
/// <param name="forceSquare">Whether the resulting <see cref="PackedTexture"/> should be square regardless of required size</param>
|
/// <param name="forceSquare">Whether the resulting <see cref="PackedTexture"/> should be square regardless of required size.</param>
|
||||||
/// <param name="disposeTextures">Whether the original textures submitted to this texture packer should be disposed after packing</param>
|
/// <param name="disposeTextures">Whether the original textures submitted to this texture packer should be disposed after packing.</param>
|
||||||
public RuntimeTexturePacker(int maxWidth = 2048, bool autoIncreaseMaxWidth = false, bool forcePowerOfTwo = false, bool forceSquare = false, bool disposeTextures = false) {
|
public RuntimeTexturePacker(int maxWidth = 2048, bool autoIncreaseMaxWidth = false, bool forcePowerOfTwo = false, bool forceSquare = false, bool disposeTextures = false) {
|
||||||
this.maxWidth = maxWidth;
|
this.maxWidth = maxWidth;
|
||||||
this.autoIncreaseMaxWidth = autoIncreaseMaxWidth;
|
this.autoIncreaseMaxWidth = autoIncreaseMaxWidth;
|
||||||
|
@ -58,37 +62,99 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new texture to this texture packer to be packed.
|
/// Adds a new <see cref="UniformTextureAtlas"/> to this texture packer to be packed.
|
||||||
|
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting dictionary of texture regions on the <see cref="PackedTexture"/>, mapped to their x and y positions on the original <see cref="UniformTextureAtlas"/>.
|
||||||
|
/// Note that the resulting data cannot be converted back into a <see cref="UniformTextureAtlas"/>, since the resulting texture regions might be scattered throughout the <see cref="PackedTexture"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="atlas">The texture atlas to pack.</param>
|
||||||
|
/// <param name="result">The result callback which will receive the resulting texture regions.</param>
|
||||||
|
/// <param name="padding">The padding that the texture should have around itself. This can be useful if texture bleeding issues occur due to texture coordinate rounding.</param>
|
||||||
|
/// <param name="padWithPixels">Whether the texture's padding should be filled with a copy of the texture's border, rather than transparent pixels. This value only has an effect if <paramref name="padding"/> is greater than 0.</param>
|
||||||
|
/// <param name="ignoreTransparent">Whether completely transparent texture regions in the <paramref name="atlas"/> should be ignored. If this is true, they will not be part of the <paramref name="result"/> collection either.</param>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to add data to a packer that has already been packed, or when trying to add a texture width a width greater than the defined max width.</exception>
|
||||||
|
public void Add(UniformTextureAtlas atlas, Action<Dictionary<Point, TextureRegion>> result, int padding = 0, bool padWithPixels = false, bool ignoreTransparent = false) {
|
||||||
|
var addedRegions = new List<TextureRegion>();
|
||||||
|
var resultRegions = new Dictionary<Point, TextureRegion>();
|
||||||
|
for (var x = 0; x < atlas.RegionAmountX; x++) {
|
||||||
|
for (var y = 0; y < atlas.RegionAmountY; y++) {
|
||||||
|
var pos = new Point(x, y);
|
||||||
|
var region = atlas[pos];
|
||||||
|
|
||||||
|
if (ignoreTransparent) {
|
||||||
|
if (this.IsTransparent(region))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Add(region, r => {
|
||||||
|
resultRegions.Add(pos, r);
|
||||||
|
if (resultRegions.Count >= addedRegions.Count)
|
||||||
|
result.Invoke(resultRegions);
|
||||||
|
}, padding, padWithPixels);
|
||||||
|
addedRegions.Add(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new <see cref="DataTextureAtlas"/> to this texture packer to be packed.
|
||||||
|
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting dictionary of texture regions on the <see cref="PackedTexture"/>, mapped to their name on the original <see cref="DataTextureAtlas"/>.
|
||||||
|
/// Note that the resulting data cannot be converted back into a <see cref="DataTextureAtlas"/>, since the resulting texture regions might be scattered throughout the <see cref="PackedTexture"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="atlas">The texture atlas to pack.</param>
|
||||||
|
/// <param name="result">The result callback which will receive the resulting texture regions.</param>
|
||||||
|
/// <param name="padding">The padding that the texture should have around itself. This can be useful if texture bleeding issues occur due to texture coordinate rounding.</param>
|
||||||
|
/// <param name="padWithPixels">Whether the texture's padding should be filled with a copy of the texture's border, rather than transparent pixels. This value only has an effect if <paramref name="padding"/> is greater than 0.</param>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to add data to a packer that has already been packed, or when trying to add a texture width a width greater than the defined max width.</exception>
|
||||||
|
public void Add(DataTextureAtlas atlas, Action<Dictionary<string, TextureRegion>> result, int padding = 0, bool padWithPixels = false) {
|
||||||
|
var atlasRegions = atlas.RegionNames.ToArray();
|
||||||
|
var resultRegions = new Dictionary<string, TextureRegion>();
|
||||||
|
foreach (var region in atlasRegions) {
|
||||||
|
this.Add(atlas[region], r => {
|
||||||
|
resultRegions.Add(region, r);
|
||||||
|
if (resultRegions.Count >= atlasRegions.Length)
|
||||||
|
result.Invoke(resultRegions);
|
||||||
|
}, padding, padWithPixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new <see cref="Texture2D"/> to this texture packer to be packed.
|
||||||
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting texture region on the <see cref="PackedTexture"/>.
|
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting texture region on the <see cref="PackedTexture"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="texture">The texture to pack</param>
|
/// <param name="texture">The texture to pack.</param>
|
||||||
/// <param name="result">The result callback which will receive the resulting texture region</param>
|
/// <param name="result">The result callback which will receive the resulting texture region.</param>
|
||||||
public void Add(Texture2D texture, Action<TextureRegion> result) {
|
/// <param name="padding">The padding that the texture should have around itself. This can be useful if texture bleeding issues occur due to texture coordinate rounding.</param>
|
||||||
this.Add(new TextureRegion(texture), result);
|
/// <param name="padWithPixels">Whether the texture's padding should be filled with a copy of the texture's border, rather than transparent pixels. This value only has an effect if <paramref name="padding"/> is greater than 0.</param>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to add data to a packer that has already been packed, or when trying to add a texture width a width greater than the defined max width.</exception>
|
||||||
|
public void Add(Texture2D texture, Action<TextureRegion> result, int padding = 0, bool padWithPixels = false) {
|
||||||
|
this.Add(new TextureRegion(texture), result, padding, padWithPixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new <see cref="TextureRegion"/> to this texture packer to be packed.
|
/// Adds a new <see cref="TextureRegion"/> to this texture packer to be packed.
|
||||||
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting texture region on the <see cref="PackedTexture"/>.
|
/// The passed <see cref="Action{T}"/> is invoked in <see cref="Pack"/> and provides the caller with the resulting texture region on the <see cref="PackedTexture"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="texture">The texture to pack</param>
|
/// <param name="texture">The texture region to pack.</param>
|
||||||
/// <param name="result">The result callback which will receive the resulting texture region</param>
|
/// <param name="result">The result callback which will receive the resulting texture region.</param>
|
||||||
/// <exception cref="InvalidOperationException">Thrown when trying to add data to a packer that has already been packed, or when trying to add a texture width a width greater than the defined max width</exception>
|
/// <param name="padding">The padding that the texture should have around itself. This can be useful if texture bleeding issues occur due to texture coordinate rounding.</param>
|
||||||
public void Add(TextureRegion texture, Action<TextureRegion> result) {
|
/// <param name="padWithPixels">Whether the texture's padding should be filled with a copy of the texture's border, rather than transparent pixels. This value only has an effect if <paramref name="padding"/> is greater than 0.</param>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown when trying to add data to a packer that has already been packed, or when trying to add a texture width a width greater than the defined max width.</exception>
|
||||||
|
public void Add(TextureRegion texture, Action<TextureRegion> result, int padding = 0, bool padWithPixels = false) {
|
||||||
if (this.PackedTexture != null)
|
if (this.PackedTexture != null)
|
||||||
throw new InvalidOperationException("Cannot add texture to a texture packer that is already packed");
|
throw new InvalidOperationException("Cannot add texture to a texture packer that is already packed");
|
||||||
if (texture.Width > this.maxWidth) {
|
var paddedWidth = texture.Width + 2 * padding;
|
||||||
|
if (paddedWidth > this.maxWidth) {
|
||||||
if (this.autoIncreaseMaxWidth) {
|
if (this.autoIncreaseMaxWidth) {
|
||||||
this.maxWidth = texture.Width;
|
this.maxWidth = paddedWidth;
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidOperationException($"Cannot add texture with width {texture.Width} to a texture packer with max width {this.maxWidth}");
|
throw new InvalidOperationException($"Cannot add texture with width {texture.Width} to a texture packer with max width {this.maxWidth}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.textures.Add(new Request(texture, result));
|
this.texturesToPack.Add(new Request(texture, result, padding, padWithPixels));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Packs all of the textures and texture regions added using <see cref="Add(Microsoft.Xna.Framework.Graphics.Texture2D,System.Action{MLEM.Textures.TextureRegion})"/> into one texture.
|
/// Packs all of the textures and texture regions added using <see cref="Add(Microsoft.Xna.Framework.Graphics.Texture2D,System.Action{MLEM.Textures.TextureRegion},int,bool)"/> into one texture.
|
||||||
/// The resulting texture will be stored in <see cref="PackedTexture"/>.
|
/// The resulting texture will be stored in <see cref="PackedTexture"/>.
|
||||||
/// All of the result callbacks that were added will also be invoked.
|
/// All of the result callbacks that were added will also be invoked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -99,20 +165,23 @@ namespace MLEM.Data {
|
||||||
throw new InvalidOperationException("Cannot pack a texture packer that is already packed");
|
throw new InvalidOperationException("Cannot pack a texture packer that is already packed");
|
||||||
|
|
||||||
// set pack areas for each request
|
// set pack areas for each request
|
||||||
|
// we pack larger textures first, so that smaller textures can fit in the gaps that larger ones leave
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
foreach (var request in this.textures.OrderByDescending(t => t.Texture.Width * t.Texture.Height)) {
|
foreach (var request in this.texturesToPack.OrderByDescending(t => t.Texture.Width * t.Texture.Height)) {
|
||||||
var area = this.FindFreeArea(new Point(request.Texture.Width, request.Texture.Height));
|
request.PackedArea = this.FindFreeArea(request);
|
||||||
request.PackedArea = area;
|
// if this is the first position that this request fit in, no other requests of the same size will find a position before it
|
||||||
|
this.firstPossiblePosForSizeCache[new Point(request.PackedArea.Width, request.PackedArea.Height)] = request.PackedArea.Location;
|
||||||
|
this.alreadyPackedTextures.Add(request);
|
||||||
}
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
this.LastCalculationTime = stopwatch.Elapsed;
|
this.LastCalculationTime = stopwatch.Elapsed;
|
||||||
|
|
||||||
// figure out texture size and generate texture
|
// figure out texture size and generate texture
|
||||||
var width = this.textures.Max(t => t.PackedArea.Right);
|
var width = this.alreadyPackedTextures.Max(t => t.PackedArea.Right);
|
||||||
var height = this.textures.Max(t => t.PackedArea.Bottom);
|
var height = this.alreadyPackedTextures.Max(t => t.PackedArea.Bottom);
|
||||||
if (this.forcePowerOfTwo) {
|
if (this.forcePowerOfTwo) {
|
||||||
width = ToPowerOfTwo(width);
|
width = RuntimeTexturePacker.ToPowerOfTwo(width);
|
||||||
height = ToPowerOfTwo(height);
|
height = RuntimeTexturePacker.ToPowerOfTwo(height);
|
||||||
}
|
}
|
||||||
if (this.forceSquare)
|
if (this.forceSquare)
|
||||||
width = height = Math.Max(width, height);
|
width = height = Math.Max(width, height);
|
||||||
|
@ -121,20 +190,21 @@ namespace MLEM.Data {
|
||||||
// copy texture data onto the packed texture
|
// copy texture data onto the packed texture
|
||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
using (var data = this.PackedTexture.GetTextureData()) {
|
using (var data = this.PackedTexture.GetTextureData()) {
|
||||||
foreach (var request in this.textures)
|
foreach (var request in this.alreadyPackedTextures)
|
||||||
CopyRegion(data, request);
|
this.CopyRegion(data, request);
|
||||||
}
|
}
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
this.LastPackTime = stopwatch.Elapsed;
|
this.LastPackTime = stopwatch.Elapsed;
|
||||||
|
|
||||||
// invoke callbacks
|
// invoke callbacks
|
||||||
foreach (var request in this.textures) {
|
foreach (var request in this.alreadyPackedTextures) {
|
||||||
request.Result.Invoke(new TextureRegion(this.PackedTexture, request.PackedArea));
|
var packedArea = request.PackedArea.Shrink(new Point(request.Padding, request.Padding));
|
||||||
|
request.Result.Invoke(new TextureRegion(this.PackedTexture, packedArea));
|
||||||
if (this.disposeTextures)
|
if (this.disposeTextures)
|
||||||
request.Texture.Texture.Dispose();
|
request.Texture.Texture.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.textures.Clear();
|
this.ClearTempCollections();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -143,9 +213,9 @@ namespace MLEM.Data {
|
||||||
public void Reset() {
|
public void Reset() {
|
||||||
this.PackedTexture?.Dispose();
|
this.PackedTexture?.Dispose();
|
||||||
this.PackedTexture = null;
|
this.PackedTexture = null;
|
||||||
this.textures.Clear();
|
|
||||||
this.LastCalculationTime = TimeSpan.Zero;
|
this.LastCalculationTime = TimeSpan.Zero;
|
||||||
this.LastPackTime = TimeSpan.Zero;
|
this.LastPackTime = TimeSpan.Zero;
|
||||||
|
this.ClearTempCollections();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||||
|
@ -153,13 +223,17 @@ namespace MLEM.Data {
|
||||||
this.Reset();
|
this.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Rectangle FindFreeArea(Point size) {
|
private Rectangle FindFreeArea(Request request) {
|
||||||
var pos = new Point(0, 0);
|
var size = new Point(request.Texture.Width, request.Texture.Height);
|
||||||
|
size.X += request.Padding * 2;
|
||||||
|
size.Y += request.Padding * 2;
|
||||||
|
|
||||||
|
var pos = this.firstPossiblePosForSizeCache.TryGetValue(size, out var first) ? first : Point.Zero;
|
||||||
var lowestY = int.MaxValue;
|
var lowestY = int.MaxValue;
|
||||||
while (true) {
|
while (true) {
|
||||||
var intersected = false;
|
var intersected = false;
|
||||||
var area = new Rectangle(pos, size);
|
var area = new Rectangle(pos.X, pos.Y, size.X, size.Y);
|
||||||
foreach (var tex in this.textures) {
|
foreach (var tex in this.alreadyPackedTextures) {
|
||||||
if (tex.PackedArea.Intersects(area)) {
|
if (tex.PackedArea.Intersects(area)) {
|
||||||
pos.X = tex.PackedArea.Right;
|
pos.X = tex.PackedArea.Right;
|
||||||
// when we move down, we want to move down by the smallest intersecting texture's height
|
// when we move down, we want to move down by the smallest intersecting texture's height
|
||||||
|
@ -179,18 +253,53 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyRegion(TextureExtensions.TextureData destination, Request request) {
|
private void CopyRegion(TextureData destination, Request request) {
|
||||||
using (var data = request.Texture.Texture.GetTextureData()) {
|
var data = this.GetCachedTextureData(request.Texture.Texture);
|
||||||
for (var x = 0; x < request.Texture.Width; x++) {
|
var location = request.PackedArea.Location + new Point(request.Padding, request.Padding);
|
||||||
for (var y = 0; y < request.Texture.Height; y++) {
|
for (var x = -request.Padding; x < request.Texture.Width + request.Padding; x++) {
|
||||||
var dest = request.PackedArea.Location + new Point(x, y);
|
for (var y = -request.Padding; y < request.Texture.Height + request.Padding; y++) {
|
||||||
var src = request.Texture.Position + new Point(x, y);
|
Color srcColor;
|
||||||
destination[dest] = data[src];
|
if (!request.PadWithPixels && (x < 0 || y < 0 || x >= request.Texture.Width || y >= request.Texture.Height)) {
|
||||||
|
// if we're out of bounds and not padding with pixels, we make it transparent
|
||||||
|
srcColor = Color.Transparent;
|
||||||
|
} else {
|
||||||
|
// otherwise, we just use the closest pixel that is actually in bounds, causing the border pixels to be doubled up
|
||||||
|
var src = new Point((int) MathHelper.Clamp(x, 0, request.Texture.Width - 1), (int) MathHelper.Clamp(y, 0, request.Texture.Height - 1));
|
||||||
|
srcColor = data[request.Texture.Position + src];
|
||||||
}
|
}
|
||||||
|
destination[location + new Point(x, y)] = srcColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TextureData GetCachedTextureData(Texture2D texture) {
|
||||||
|
// we cache texture data in case multiple requests use the same underlying texture
|
||||||
|
// this collection doesn't need to be disposed since we don't actually edit these textures
|
||||||
|
if (!this.dataCache.TryGetValue(texture, out var data)) {
|
||||||
|
data = texture.GetTextureData();
|
||||||
|
this.dataCache.Add(texture, data);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTransparent(TextureRegion region) {
|
||||||
|
var data = this.GetCachedTextureData(region.Texture);
|
||||||
|
for (var rX = 0; rX < region.Width; rX++) {
|
||||||
|
for (var rY = 0; rY < region.Height; rY++) {
|
||||||
|
if (data[region.U + rX, region.V + rY] != Color.Transparent)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearTempCollections() {
|
||||||
|
this.texturesToPack.Clear();
|
||||||
|
this.alreadyPackedTextures.Clear();
|
||||||
|
this.firstPossiblePosForSizeCache.Clear();
|
||||||
|
this.dataCache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
private static int ToPowerOfTwo(int value) {
|
private static int ToPowerOfTwo(int value) {
|
||||||
var ret = 1;
|
var ret = 1;
|
||||||
while (ret < value)
|
while (ret < value)
|
||||||
|
@ -202,14 +311,18 @@ namespace MLEM.Data {
|
||||||
|
|
||||||
public readonly TextureRegion Texture;
|
public readonly TextureRegion Texture;
|
||||||
public readonly Action<TextureRegion> Result;
|
public readonly Action<TextureRegion> Result;
|
||||||
|
public readonly int Padding;
|
||||||
|
public readonly bool PadWithPixels;
|
||||||
public Rectangle PackedArea;
|
public Rectangle PackedArea;
|
||||||
|
|
||||||
public Request(TextureRegion texture, Action<TextureRegion> result) {
|
public Request(TextureRegion texture, Action<TextureRegion> result, int padding, bool padWithPixels) {
|
||||||
this.Texture = texture;
|
this.Texture = texture;
|
||||||
this.Result = result;
|
this.Result = result;
|
||||||
|
this.Padding = padding;
|
||||||
|
this.PadWithPixels = padWithPixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,4 +41,4 @@ namespace MLEM.Extended.Extensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,4 +40,4 @@ namespace MLEM.Extended.Extensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,4 +62,4 @@ namespace MLEM.Extended.Extensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,4 @@ namespace MLEM.Extended.Extensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,4 +43,4 @@ namespace MLEM.Extended.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,4 +43,4 @@ namespace MLEM.Extended.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
MLEM.Extended/MLEM.Extended.FNA.csproj
Normal file
41
MLEM.Extended/MLEM.Extended.FNA.csproj
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Extended</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>MLEM Library for Extending FNA extension that ties in with other FNA libraries</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions extended</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\FontStashSharp\src\XNA\FontStashSharp.FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
|
||||||
|
<Compile Remove="Tiled/**" />
|
||||||
|
<Compile Remove="Extensions/**" />
|
||||||
|
<Compile Remove="Font/GenericBitmapFont.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -26,7 +26,7 @@
|
||||||
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0">
|
<PackageReference Include="MonoGame.Extended.Tiled" Version="3.8.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="FontStashSharp.MonoGame" Version="1.0.4">
|
<PackageReference Include="FontStashSharp.MonoGame" Version="1.1.6">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641">
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using MLEM.Cameras;
|
using MLEM.Cameras;
|
||||||
using MLEM.Extensions;
|
using MLEM.Extensions;
|
||||||
|
using MLEM.Graphics;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
using MonoGame.Extended.Tiled;
|
using MonoGame.Extended.Tiled;
|
||||||
using RectangleF = MonoGame.Extended.RectangleF;
|
using RectangleF = MonoGame.Extended.RectangleF;
|
||||||
|
@ -92,6 +93,20 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds this individual tiled map renderer to the given <see cref="StaticSpriteBatch"/>.
|
||||||
|
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The static sprite batch to use for drawing.</param>
|
||||||
|
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
||||||
|
/// <param name="addFunction">The add function to use, or null to use <see cref="DefaultAdd"/>.</param>
|
||||||
|
public void Add(StaticSpriteBatch batch, RectangleF? frustum = null, AddDelegate addFunction = null) {
|
||||||
|
for (var i = 0; i < this.map.TileLayers.Count; i++) {
|
||||||
|
if (this.map.TileLayers[i].IsVisible)
|
||||||
|
this.AddLayer(batch, i, frustum, addFunction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws the given layer of this individual tiled map renderer.
|
/// Draws the given layer of this individual tiled map renderer.
|
||||||
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
||||||
|
@ -101,12 +116,8 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
||||||
/// <param name="drawFunction">The draw function to use, or null to use <see cref="DefaultDraw"/></param>
|
/// <param name="drawFunction">The draw function to use, or null to use <see cref="DefaultDraw"/></param>
|
||||||
public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
public void DrawLayer(SpriteBatch batch, int layerIndex, RectangleF? frustum = null, DrawDelegate drawFunction = null) {
|
||||||
var draw = drawFunction ?? DefaultDraw;
|
var draw = drawFunction ?? IndividualTiledMapRenderer.DefaultDraw;
|
||||||
var frust = frustum ?? new RectangleF(0, 0, float.MaxValue, float.MaxValue);
|
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
|
||||||
var minX = Math.Max(0, frust.Left / this.map.TileWidth).Floor();
|
|
||||||
var minY = Math.Max(0, frust.Top / this.map.TileHeight).Floor();
|
|
||||||
var maxX = Math.Min(this.map.Width, frust.Right / this.map.TileWidth).Ceil();
|
|
||||||
var maxY = Math.Min(this.map.Height, frust.Bottom / this.map.TileHeight).Ceil();
|
|
||||||
for (var x = minX; x < maxX; x++) {
|
for (var x = minX; x < maxX; x++) {
|
||||||
for (var y = minY; y < maxY; y++) {
|
for (var y = minY; y < maxY; y++) {
|
||||||
var info = this.drawInfos[layerIndex, x, y];
|
var info = this.drawInfos[layerIndex, x, y];
|
||||||
|
@ -116,6 +127,26 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the given layer of this individual tiled map renderer to the given <see cref="StaticSpriteBatch"/>.
|
||||||
|
/// Optionally, a frustum can be supplied that determines which positions, in pixel space, are visible at this time. <see cref="Camera"/> provides <see cref="Camera.GetVisibleRectangle"/> for this purpose.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The static sprite batch to use for drawing.</param>
|
||||||
|
/// <param name="layerIndex">The index of the layer in <see cref="TiledMap.TileLayers"/>.</param>
|
||||||
|
/// <param name="frustum">The area that is visible, in pixel space.</param>
|
||||||
|
/// <param name="addFunction">The add function to use, or null to use <see cref="DefaultAdd"/>.</param>
|
||||||
|
public void AddLayer(StaticSpriteBatch batch, int layerIndex, RectangleF? frustum = null, AddDelegate addFunction = null) {
|
||||||
|
var add = addFunction ?? IndividualTiledMapRenderer.DefaultAdd;
|
||||||
|
var (minX, minY, maxX, maxY) = this.GetFrustum(frustum);
|
||||||
|
for (var x = minX; x < maxX; x++) {
|
||||||
|
for (var y = minY; y < maxY; y++) {
|
||||||
|
var info = this.drawInfos[layerIndex, x, y];
|
||||||
|
if (info != null)
|
||||||
|
add(batch, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update all of the animated tiles in this individual tiled map renderer
|
/// Update all of the animated tiles in this individual tiled map renderer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -125,8 +156,17 @@ namespace MLEM.Extended.Tiled {
|
||||||
animation.Update(time);
|
animation.Update(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private (int MinX, int MinY, int MaxX, int MaxY) GetFrustum(RectangleF? frustum) {
|
||||||
|
var frust = frustum ?? new RectangleF(0, 0, float.MaxValue, float.MaxValue);
|
||||||
|
var minX = Math.Max(0, frust.Left / this.map.TileWidth).Floor();
|
||||||
|
var minY = Math.Max(0, frust.Top / this.map.TileHeight).Floor();
|
||||||
|
var maxX = Math.Min(this.map.Width, frust.Right / this.map.TileWidth).Ceil();
|
||||||
|
var maxY = Math.Min(this.map.Height, frust.Bottom / this.map.TileHeight).Ceil();
|
||||||
|
return (minX, minY, maxX, maxY);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default implementation of <see cref="DrawDelegate"/> that is used by <see cref="SetMap"/> if no custom draw function is passed
|
/// The default implementation of <see cref="DrawDelegate"/> that is used by <see cref="Draw"/> if no custom draw function is passed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="batch">The sprite batch to use for drawing</param>
|
/// <param name="batch">The sprite batch to use for drawing</param>
|
||||||
/// <param name="info">The <see cref="TileDrawInfo"/> to draw</param>
|
/// <param name="info">The <see cref="TileDrawInfo"/> to draw</param>
|
||||||
|
@ -137,6 +177,18 @@ namespace MLEM.Extended.Tiled {
|
||||||
batch.Draw(info.Tileset.Texture, drawPos, region, Color.White, 0, Vector2.Zero, 1, effects, info.Depth);
|
batch.Draw(info.Tileset.Texture, drawPos, region, Color.White, 0, Vector2.Zero, 1, effects, info.Depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default implementation of <see cref="AddDelegate"/> that is used by <see cref="Add"/> if no custom add function is passed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The static sprite batch to use for drawing.</param>
|
||||||
|
/// <param name="info">The <see cref="TileDrawInfo"/> to add.</param>
|
||||||
|
public static void DefaultAdd(StaticSpriteBatch batch, TileDrawInfo info) {
|
||||||
|
var region = info.Tileset.GetTextureRegion(info.TilesetTile);
|
||||||
|
var effects = info.Tile.GetSpriteEffects();
|
||||||
|
var drawPos = new Vector2(info.Position.X * info.Renderer.map.TileWidth, info.Position.Y * info.Renderer.map.TileHeight);
|
||||||
|
batch.Add(info.Tileset.Texture, drawPos, region, Color.White, 0, Vector2.Zero, 1, effects, info.Depth);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A delegate method used for <see cref="IndividualTiledMapRenderer.depthFunction"/>.
|
/// A delegate method used for <see cref="IndividualTiledMapRenderer.depthFunction"/>.
|
||||||
/// The idea is to return a depth (between 0 and 1) for the given tile that determines where in the sprite batch it should be rendererd.
|
/// The idea is to return a depth (between 0 and 1) for the given tile that determines where in the sprite batch it should be rendererd.
|
||||||
|
@ -155,6 +207,13 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="info">The <see cref="TileDrawInfo"/> to draw</param>
|
/// <param name="info">The <see cref="TileDrawInfo"/> to draw</param>
|
||||||
public delegate void DrawDelegate(SpriteBatch batch, TileDrawInfo info);
|
public delegate void DrawDelegate(SpriteBatch batch, TileDrawInfo info);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate method used for adding an <see cref="IndividualTiledMapRenderer"/> to a <see cref="StaticSpriteBatch"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="batch">The static sprite batch to use for drawing.</param>
|
||||||
|
/// <param name="info">The <see cref="TileDrawInfo"/> to add.</param>
|
||||||
|
public delegate void AddDelegate(StaticSpriteBatch batch, TileDrawInfo info);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A tile draw info contains information about a tile at a given map location.
|
/// A tile draw info contains information about a tile at a given map location.
|
||||||
/// It caches a lot of data that is required for drawing a tile efficiently.
|
/// It caches a lot of data that is required for drawing a tile efficiently.
|
||||||
|
@ -198,4 +257,4 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ using MonoGame.Extended.Tiled;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A struct that represents a position on a <see cref="TiledMap"/> with multiple layers.
|
/// A struct that represents a position on a <see cref="TiledMap"/> with multiple layers, where the <see cref="X"/> and <see cref="Y"/> coordinates are 32-bit integer numbers.
|
||||||
|
/// See <see cref="LayerPositionF"/> for a floating point position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataContract]
|
[DataContract]
|
||||||
public struct LayerPosition : IEquatable<LayerPosition> {
|
public struct LayerPosition : IEquatable<LayerPosition> {
|
||||||
|
@ -53,8 +54,8 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||||
public override int GetHashCode() {
|
public override int GetHashCode() {
|
||||||
var hashCode = this.Layer.GetHashCode();
|
var hashCode = this.Layer.GetHashCode();
|
||||||
hashCode = (hashCode * 397) ^ this.X;
|
hashCode = hashCode * 397 ^ this.X;
|
||||||
hashCode = (hashCode * 397) ^ this.Y;
|
hashCode = hashCode * 397 ^ this.Y;
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="right">The right position.</param>
|
/// <param name="right">The right position.</param>
|
||||||
/// <returns>The sum of the positions.</returns>
|
/// <returns>The sum of the positions.</returns>
|
||||||
public static LayerPosition operator +(LayerPosition left, LayerPosition right) {
|
public static LayerPosition operator +(LayerPosition left, LayerPosition right) {
|
||||||
return Add(left, right);
|
return LayerPosition.Add(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -114,8 +115,17 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="right">The right position.</param>
|
/// <param name="right">The right position.</param>
|
||||||
/// <returns>The difference of the positions.</returns>
|
/// <returns>The difference of the positions.</returns>
|
||||||
public static LayerPosition operator -(LayerPosition left, LayerPosition right) {
|
public static LayerPosition operator -(LayerPosition left, LayerPosition right) {
|
||||||
return Add(left, -right);
|
return LayerPosition.Add(left, -right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implicitly converts a <see cref="LayerPosition"/> to a <see cref="LayerPositionF"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The position to convert.</param>
|
||||||
|
/// <returns>The converted position.</returns>
|
||||||
|
public static implicit operator LayerPositionF(LayerPosition position) {
|
||||||
|
return new LayerPositionF(position.Layer, position.X, position.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
132
MLEM.Extended/Tiled/LayerPositionF.cs
Normal file
132
MLEM.Extended/Tiled/LayerPositionF.cs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using MonoGame.Extended.Tiled;
|
||||||
|
|
||||||
|
namespace MLEM.Extended.Tiled {
|
||||||
|
/// <summary>
|
||||||
|
/// A struct that represents a position on a <see cref="TiledMap"/> with multiple layers, where the <see cref="X"/> and <see cref="Y"/> coordinates are 32-bit floating point numbers.
|
||||||
|
/// See <see cref="LayerPosition"/> for an integer position.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public struct LayerPositionF : IEquatable<LayerPositionF> {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the layer that this position is on
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public string Layer;
|
||||||
|
/// <summary>
|
||||||
|
/// The x coordinate of this position
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public float X;
|
||||||
|
/// <summary>
|
||||||
|
/// The y coordinate of this position
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public float Y;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new layer position with the given settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerName">The layer name</param>
|
||||||
|
/// <param name="x">The x coordinate</param>
|
||||||
|
/// <param name="y">The y coordinate</param>
|
||||||
|
public LayerPositionF(string layerName, float x, float y) {
|
||||||
|
this.Layer = layerName;
|
||||||
|
this.X = x;
|
||||||
|
this.Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(object)"/>
|
||||||
|
public bool Equals(LayerPositionF other) {
|
||||||
|
return this.Layer == other.Layer && this.X == other.X && this.Y == other.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Indicates whether this instance and a specified object are equal.</summary>
|
||||||
|
/// <param name="obj">The object to compare with the current instance.</param>
|
||||||
|
/// <returns>true if <paramref name="obj">obj</paramref> and this instance are the same type and represent the same value; otherwise, false.</returns>
|
||||||
|
public override bool Equals(object obj) {
|
||||||
|
return obj is LayerPositionF other && this.Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Returns the hash code for this instance.</summary>
|
||||||
|
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
|
||||||
|
public override int GetHashCode() {
|
||||||
|
var hashCode = this.Layer.GetHashCode();
|
||||||
|
hashCode = hashCode * 397 ^ this.X.GetHashCode();
|
||||||
|
hashCode = hashCode * 397 ^ this.Y.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Returns the fully qualified type name of this instance.</summary>
|
||||||
|
/// <returns>The fully qualified type name.</returns>
|
||||||
|
public override string ToString() {
|
||||||
|
return $"{nameof(this.Layer)}: {this.Layer}, {nameof(this.X)}: {this.X}, {nameof(this.Y)}: {this.Y}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the given layer positions together, returning a new layer position with the sum of their coordinates.
|
||||||
|
/// If the two layer positions' <see cref="Layer"/> differ, an <see cref="ArgumentException"/> is thrown.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The left position.</param>
|
||||||
|
/// <param name="right">The right position.</param>
|
||||||
|
/// <returns>The sum of the positions.</returns>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if the two positions' <see cref="Layer"/> are not the same.</exception>
|
||||||
|
public static LayerPositionF Add(LayerPositionF left, LayerPositionF right) {
|
||||||
|
if (left.Layer != right.Layer)
|
||||||
|
throw new ArgumentException("Cannot add layer positions on different layers");
|
||||||
|
return new LayerPositionF(left.Layer, left.X + right.X, left.Y + right.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(LayerPositionF)"/>
|
||||||
|
public static bool operator ==(LayerPositionF left, LayerPositionF right) {
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Equals(LayerPositionF)"/>
|
||||||
|
public static bool operator !=(LayerPositionF left, LayerPositionF right) {
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the negative of the given layer position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The position to negate.</param>
|
||||||
|
/// <returns>The negative position.</returns>
|
||||||
|
public static LayerPositionF operator -(LayerPositionF position) {
|
||||||
|
return new LayerPositionF(position.Layer, -position.X, -position.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the sum of the two layer positions using <see cref="Add"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The left position.</param>
|
||||||
|
/// <param name="right">The right position.</param>
|
||||||
|
/// <returns>The sum of the positions.</returns>
|
||||||
|
public static LayerPositionF operator +(LayerPositionF left, LayerPositionF right) {
|
||||||
|
return LayerPositionF.Add(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts the second from the first position using <see cref="Add"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The left position.</param>
|
||||||
|
/// <param name="right">The right position.</param>
|
||||||
|
/// <returns>The difference of the positions.</returns>
|
||||||
|
public static LayerPositionF operator -(LayerPositionF left, LayerPositionF right) {
|
||||||
|
return LayerPositionF.Add(left, -right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implicitly converts a <see cref="LayerPositionF"/> to a <see cref="LayerPosition"/>.
|
||||||
|
/// The coordinates are typecast to 32-bit integers in the process.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The position to convert.</param>
|
||||||
|
/// <returns>The converted position.</returns>
|
||||||
|
public static implicit operator LayerPosition(LayerPositionF position) {
|
||||||
|
return new LayerPosition(position.Layer, (int) position.X, (int) position.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using MonoGame.Extended;
|
using MonoGame.Extended;
|
||||||
using MonoGame.Extended.Tiled;
|
using MonoGame.Extended.Tiled;
|
||||||
using static MonoGame.Extended.Tiled.TiledMapTileFlipFlags;
|
|
||||||
using ColorHelper = MLEM.Extensions.ColorHelper;
|
using ColorHelper = MLEM.Extensions.ColorHelper;
|
||||||
|
|
||||||
namespace MLEM.Extended.Tiled {
|
namespace MLEM.Extended.Tiled {
|
||||||
|
@ -144,9 +143,9 @@ namespace MLEM.Extended.Tiled {
|
||||||
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, int localId, bool createStub = true) {
|
public static TiledMapTilesetTile GetTilesetTile(this TiledMapTileset tileset, int localId, bool createStub = true) {
|
||||||
var tilesetTile = tileset.Tiles.FirstOrDefault(t => t.LocalTileIdentifier == localId);
|
var tilesetTile = tileset.Tiles.FirstOrDefault(t => t.LocalTileIdentifier == localId);
|
||||||
if (tilesetTile == null && createStub) {
|
if (tilesetTile == null && createStub) {
|
||||||
if (!StubTilesetTiles.TryGetValue(localId, out tilesetTile)) {
|
if (!TiledExtensions.StubTilesetTiles.TryGetValue(localId, out tilesetTile)) {
|
||||||
tilesetTile = new TiledMapTilesetTile(localId);
|
tilesetTile = new TiledMapTilesetTile(localId);
|
||||||
StubTilesetTiles.Add(localId, tilesetTile);
|
TiledExtensions.StubTilesetTiles.Add(localId, tilesetTile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tilesetTile;
|
return tilesetTile;
|
||||||
|
@ -271,12 +270,12 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="position">The position to add to the object's position</param>
|
/// <param name="position">The position to add to the object's position</param>
|
||||||
/// <param name="flipFlags">The flipping of the tile that this object belongs to. If set, the returned area will be "flipped" in the tile's space so that it matches the flip flags.</param>
|
/// <param name="flipFlags">The flipping of the tile that this object belongs to. If set, the returned area will be "flipped" in the tile's space so that it matches the flip flags.</param>
|
||||||
/// <returns>The area that the tile covers</returns>
|
/// <returns>The area that the tile covers</returns>
|
||||||
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = None) {
|
public static RectangleF GetArea(this TiledMapObject obj, TiledMap map, Vector2? position = null, TiledMapTileFlipFlags flipFlags = TiledMapTileFlipFlags.None) {
|
||||||
var tileSize = map.GetTileSize();
|
var tileSize = map.GetTileSize();
|
||||||
var area = new RectangleF(obj.Position / tileSize, obj.Size / tileSize);
|
var area = new RectangleF(obj.Position / tileSize, obj.Size / tileSize);
|
||||||
if (flipFlags.HasFlag(FlipHorizontally))
|
if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipHorizontally))
|
||||||
area.X = 1 - area.X - area.Width;
|
area.X = 1 - area.X - area.Width;
|
||||||
if (flipFlags.HasFlag(FlipVertically))
|
if (flipFlags.HasFlag(TiledMapTileFlipFlags.FlipVertically))
|
||||||
area.Y = 1 - area.Y - area.Height;
|
area.Y = 1 - area.Y - area.Height;
|
||||||
if (position != null)
|
if (position != null)
|
||||||
area.Offset(position.Value);
|
area.Offset(position.Value);
|
||||||
|
@ -361,4 +360,4 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MLEM.Extended.Tiled {
|
||||||
/// <param name="collisionFunction">The function used to collect the collision info of a tile, or null to use <see cref="DefaultCollectCollisions"/></param>
|
/// <param name="collisionFunction">The function used to collect the collision info of a tile, or null to use <see cref="DefaultCollectCollisions"/></param>
|
||||||
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
|
public void SetMap(TiledMap map, CollectCollisions collisionFunction = null) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.collisionFunction = collisionFunction ?? DefaultCollectCollisions;
|
this.collisionFunction = collisionFunction ?? TiledMapCollisions.DefaultCollectCollisions;
|
||||||
this.collisionInfos = new TileCollisionInfo[map.Layers.Count, map.Width, map.Height];
|
this.collisionInfos = new TileCollisionInfo[map.Layers.Count, map.Width, map.Height];
|
||||||
for (var i = 0; i < map.TileLayers.Count; i++) {
|
for (var i = 0; i < map.TileLayers.Count; i++) {
|
||||||
for (var x = 0; x < map.Width; x++) {
|
for (var x = 0; x < map.Width; x++) {
|
||||||
|
@ -204,4 +204,4 @@ namespace MLEM.Extended.Tiled {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
70
MLEM.FNA.sln
Normal file
70
MLEM.FNA.sln
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.FNA", "MLEM\MLEM.FNA.csproj", "{C2C88AE6-6274-4395-8B03-52AE898BA070}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Ui.FNA", "MLEM.Ui\MLEM.Ui.FNA.csproj", "{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Startup.FNA", "MLEM.Startup\MLEM.Startup.FNA.csproj", "{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Data.FNA", "MLEM.Data\MLEM.Data.FNA.csproj", "{6587BC91-0640-43FB-988A-4F545B8ACFC5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos.FNA", "Demos\Demos.FNA.csproj", "{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos.DesktopGL.FNA", "Demos.DesktopGL\Demos.DesktopGL.FNA.csproj", "{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.FNA", "Tests\Tests.FNA.csproj", "{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Extended.FNA", "MLEM.Extended\MLEM.Extended.FNA.csproj", "{A5B22930-DF4B-4A62-93ED-A6549F7B666B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA.Core", "FNA\FNA.Core.csproj", "{06459F72-CEAA-4B45-B2B1-708FC28D04F8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FontStashSharp.FNA.Core", "FontStashSharp\src\XNA\FontStashSharp.FNA.Core.csproj", "{0B410591-3AED-4C82-A07A-516FF493709B}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2C88AE6-6274-4395-8B03-52AE898BA070}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1B47A40B-3BF6-4933-A7DB-57EADEBDFB61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FBE2C9B5-293D-47A7-9BA1-5A4BD1C4E816}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6587BC91-0640-43FB-988A-4F545B8ACFC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D83D7D24-14CB-4A7C-A80B-BA4FEC66AB55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AB08FEC7-3AC3-4FDE-B632-226FAAD7F73F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C74FC4C5-3BE0-42A7-8BA6-4A9AD438A9E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A5B22930-DF4B-4A62-93ED-A6549F7B666B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{06459F72-CEAA-4B45-B2B1-708FC28D04F8}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0B410591-3AED-4C82-A07A-516FF493709B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -24,4 +24,4 @@ namespace MLEM.Startup {
|
||||||
public static readonly Event Draw = new Event();
|
public static readonly Event Draw = new Event();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
MLEM.Startup/MLEM.Startup.FNA.csproj
Normal file
37
MLEM.Startup/MLEM.Startup.FNA.csproj
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||||
|
<RootNamespace>MLEM.Startup</RootNamespace>
|
||||||
|
<DefineConstants>$(DefineConstants);FNA</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Authors>Ellpeck</Authors>
|
||||||
|
<Description>MLEM Library for Extending FNA combined with some other useful libraries into a quick Game startup class</Description>
|
||||||
|
<PackageReleaseNotes>See the full changelog at https://mlem.ellpeck.de/CHANGELOG</PackageReleaseNotes>
|
||||||
|
<PackageTags>fna ellpeck mlem utility extensions</PackageTags>
|
||||||
|
<PackageProjectUrl>https://mlem.ellpeck.de/</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/Ellpeck/MLEM</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageIcon>Logo.png</PackageIcon>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Coroutine" Version="2.1.3" />
|
||||||
|
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.FNA.csproj" />
|
||||||
|
<ProjectReference Include="..\MLEM\MLEM.FNA.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\FNA\FNA.Core.csproj">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="../Media/Logo.png" Pack="true" PackagePath="" />
|
||||||
|
<None Include="../Docs/index.md" Pack="true" PackagePath="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -18,7 +18,7 @@ namespace MLEM.Startup {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The static game instance's input handler
|
/// The static game instance's input handler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static InputHandler Input => instance.InputHandler;
|
public static InputHandler Input => MlemGame.instance.InputHandler;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This game's graphics device manager, initialized in the constructor
|
/// This game's graphics device manager, initialized in the constructor
|
||||||
|
@ -64,12 +64,14 @@ namespace MLEM.Startup {
|
||||||
/// <param name="windowWidth">The default window width</param>
|
/// <param name="windowWidth">The default window width</param>
|
||||||
/// <param name="windowHeight">The default window height</param>
|
/// <param name="windowHeight">The default window height</param>
|
||||||
public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
|
public MlemGame(int windowWidth = 1280, int windowHeight = 720) {
|
||||||
instance = this;
|
MlemGame.instance = this;
|
||||||
|
|
||||||
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
|
this.GraphicsDeviceManager = new GraphicsDeviceManager(this) {
|
||||||
PreferredBackBufferWidth = windowWidth,
|
PreferredBackBufferWidth = windowWidth,
|
||||||
PreferredBackBufferHeight = windowHeight,
|
PreferredBackBufferHeight = windowHeight,
|
||||||
|
#if !FNA
|
||||||
HardwareModeSwitch = false
|
HardwareModeSwitch = false
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
this.Window.AllowUserResizing = true;
|
this.Window.AllowUserResizing = true;
|
||||||
this.Content.RootDirectory = "Content";
|
this.Content.RootDirectory = "Content";
|
||||||
|
@ -160,7 +162,7 @@ namespace MLEM.Startup {
|
||||||
/// <typeparam name="T">The type of content to load</typeparam>
|
/// <typeparam name="T">The type of content to load</typeparam>
|
||||||
/// <returns>The loaded content</returns>
|
/// <returns>The loaded content</returns>
|
||||||
public static T LoadContent<T>(string name) {
|
public static T LoadContent<T>(string name) {
|
||||||
return instance.Content.Load<T>(name);
|
return MlemGame.instance.Content.Load<T>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -177,4 +179,4 @@ namespace MLEM.Startup {
|
||||||
public delegate void TimeCallback(MlemGame game, GameTime time);
|
public delegate void TimeCallback(MlemGame game, GameTime time);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-mgcb": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-linux": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-windows": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-windows"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-mgcb-editor-mac": {
|
||||||
|
"version": "3.8.1.263",
|
||||||
|
"commands": [
|
||||||
|
"mgcb-editor-mac"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +0,0 @@
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,13 +1,13 @@
|
||||||
using MLEM.Startup;
|
using MLEM.Startup;
|
||||||
|
|
||||||
namespace TemplateNamespace {
|
namespace TemplateNamespace;
|
||||||
public class GameImpl : MlemGame {
|
|
||||||
|
|
||||||
public static GameImpl Instance { get; private set; }
|
public class GameImpl : MlemGame {
|
||||||
|
|
||||||
public GameImpl() {
|
public static GameImpl Instance { get; private set; }
|
||||||
Instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public GameImpl() {
|
||||||
|
Instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using MLEM.Misc;
|
using MLEM.Misc;
|
||||||
|
|
||||||
namespace TemplateNamespace {
|
namespace TemplateNamespace;
|
||||||
public static class Program {
|
|
||||||
|
|
||||||
public static void Main() {
|
public static class Program {
|
||||||
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
|
||||||
using var game = new GameImpl();
|
|
||||||
game.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public static void Main() {
|
||||||
|
MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
|
||||||
|
using var game = new GameImpl();
|
||||||
|
game.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,24 +1,27 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<PublishReadyToRun>false</PublishReadyToRun>
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
<TieredCompilation>false</TieredCompilation>
|
<TieredCompilation>false</TieredCompilation>
|
||||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Contentless" Version="3.*" />
|
<PackageReference Include="Contentless" Version="3.*" />
|
||||||
<PackageReference Include="MLEM.Startup" Version="5.*" />
|
<PackageReference Include="MLEM.Startup" Version="6.*" />
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.263" />
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.*" />
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.263" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MonoGameContentReference Include="Content\Content.mgcb" />
|
|
||||||
<Content Include="Content\*\**" />
|
|
||||||
<EmbeddedResource Include="Icon.ico" />
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
<EmbeddedResource Include="Icon.bmp" />
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
|
||||||
|
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
|
||||||
|
<Message Text="Restoring dotnet tools" Importance="High" />
|
||||||
|
<Exec Command="dotnet tool restore" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,13 +1,13 @@
|
||||||
using MLEM.Startup;
|
using MLEM.Startup;
|
||||||
|
|
||||||
namespace TemplateNamespace {
|
namespace TemplateNamespace;
|
||||||
public class GameImpl : MlemGame {
|
|
||||||
|
|
||||||
public static GameImpl Instance { get; private set; }
|
public class GameImpl : MlemGame {
|
||||||
|
|
||||||
public GameImpl() {
|
public static GameImpl Instance { get; private set; }
|
||||||
Instance = this;
|
|
||||||
}
|
public GameImpl() {
|
||||||
|
Instance = this;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MLEM.Startup" Version="5.*" />
|
<PackageReference Include="MLEM.Startup" Version="6.*" />
|
||||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*">
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.263">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue