mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 08:52:50 +02:00
commit
e00f48fab8
165 changed files with 5089 additions and 2675 deletions
238
.editorconfig
238
.editorconfig
|
@ -1,11 +1,247 @@
|
|||
root = true
|
||||
|
||||
[*.cs]
|
||||
|
||||
#### Core EditorConfig Options ####
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
|
||||
# New line preferences
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
#### .NET Coding Conventions ####
|
||||
dotnet_separate_import_directive_groups = false
|
||||
dotnet_sort_system_directives_first = true
|
||||
file_header_template = unset
|
||||
|
||||
# this. and Me. preferences
|
||||
dotnet_style_qualification_for_event = false
|
||||
dotnet_style_qualification_for_field = false
|
||||
dotnet_style_qualification_for_method = false
|
||||
dotnet_style_qualification_for_property = false
|
||||
|
||||
# Language keywords vs BCL types preferences
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true
|
||||
dotnet_style_predefined_type_for_member_access = true
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
|
||||
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_coalesce_expression = true
|
||||
dotnet_style_collection_initializer = false
|
||||
dotnet_style_explicit_tuple_names = true
|
||||
dotnet_style_namespace_match_folder = false
|
||||
dotnet_style_null_propagation = true
|
||||
dotnet_style_object_initializer = true
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
dotnet_style_prefer_auto_properties = true
|
||||
dotnet_style_prefer_collection_expression = false
|
||||
dotnet_style_prefer_compound_assignment = true
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = false
|
||||
dotnet_style_prefer_conditional_expression_over_return = false
|
||||
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true
|
||||
dotnet_style_prefer_inferred_tuple_names = true
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true
|
||||
dotnet_style_prefer_simplified_interpolation = true
|
||||
|
||||
# Field preferences
|
||||
dotnet_style_readonly_field = true
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all:silent
|
||||
|
||||
# Suppression preferences
|
||||
dotnet_remove_unnecessary_suppression_exclusions = none
|
||||
|
||||
# New line preferences
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = true
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = true
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_elsewhere = false
|
||||
csharp_style_var_for_built_in_types = false
|
||||
csharp_style_var_when_type_is_apparent = false
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true
|
||||
csharp_style_expression_bodied_constructors = false
|
||||
csharp_style_expression_bodied_indexers = true
|
||||
csharp_style_expression_bodied_lambdas = true
|
||||
csharp_style_expression_bodied_local_functions = false
|
||||
csharp_style_expression_bodied_methods = when_on_single_line
|
||||
csharp_style_expression_bodied_operators = false
|
||||
csharp_style_expression_bodied_properties = true
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true
|
||||
csharp_style_prefer_extended_property_pattern = true
|
||||
csharp_style_prefer_not_pattern = true
|
||||
csharp_style_prefer_pattern_matching = true
|
||||
csharp_style_prefer_switch_expression = true
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true
|
||||
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_local_function = true
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
csharp_style_prefer_readonly_struct_member = true
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = when_multiline
|
||||
csharp_prefer_simple_using_statement = true
|
||||
csharp_style_namespace_declarations = block_scoped
|
||||
csharp_style_prefer_method_group_conversion = true
|
||||
csharp_style_prefer_primary_constructors = false
|
||||
csharp_style_prefer_top_level_statements = true
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true
|
||||
csharp_style_deconstructed_variable_declaration = true
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = false
|
||||
csharp_style_inlined_variable_declaration = true
|
||||
csharp_style_prefer_index_operator = true
|
||||
csharp_style_prefer_local_over_anonymous_function = true
|
||||
csharp_style_prefer_null_check_over_type_check = true
|
||||
csharp_style_prefer_range_operator = true
|
||||
csharp_style_prefer_tuple_swap = true
|
||||
csharp_style_prefer_utf8_string_literals = true
|
||||
csharp_style_throw_expression = true
|
||||
csharp_style_unused_value_assignment_preference = discard_variable
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace
|
||||
|
||||
# New line preferences
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
|
||||
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
|
||||
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
|
||||
csharp_style_allow_embedded_statements_on_same_line_experimental = true
|
||||
|
||||
#### C# Formatting Rules ####
|
||||
|
||||
# New line preferences
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = false
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
|
||||
# Diagnostics
|
||||
dotnet_analyzer_diagnostic.severity = warning
|
||||
|
||||
dotnet_diagnostic.IDE0001.severity = none
|
||||
dotnet_diagnostic.IDE0004.severity = silent
|
||||
dotnet_diagnostic.IDE0005.severity = error
|
||||
dotnet_diagnostic.IDE0008.severity = silent
|
||||
dotnet_diagnostic.IDE0055.severity = silent
|
||||
dotnet_diagnostic.IDE0160.severity = none
|
||||
dotnet_diagnostic.CA1707.severity = silent
|
||||
dotnet_diagnostic.CA1852.severity = none
|
||||
dotnet_diagnostic.CA1805.severity = none
|
||||
dotnet_diagnostic.CA1720.severity = silent
|
||||
dotnet_diagnostic.CA1711.severity = silent
|
||||
dotnet_diagnostic.CA1716.severity = silent
|
||||
|
||||
[.github/**/*.yml]
|
||||
charset = utf-8
|
||||
|
|
37
.github/workflows/master-pr.yml
vendored
Normal file
37
.github/workflows/master-pr.yml
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
check-pr-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout PR branch
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get version from PR branch
|
||||
id: pr_version
|
||||
run: |
|
||||
PR_VERSION=$(grep '<Version>' **/*.csproj | sed -E 's/.*<Version>(.*)<\/Version>.*/\1/')
|
||||
echo "PR_VERSION=$PR_VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout master branch
|
||||
run: |
|
||||
git fetch origin master
|
||||
git checkout origin/master
|
||||
|
||||
- name: Get version from master branch
|
||||
id: master_version
|
||||
run: |
|
||||
MASTER_VERSION=$(grep '<Version>' **/*.csproj | sed -E 's/.*<Version>(.*)<\/Version>.*/\1/')
|
||||
echo "MASTER_VERSION=$MASTER_VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Compare versions
|
||||
run: |
|
||||
if [ "$(printf '%s\n' "$PR_VERSION" "$MASTER_VERSION" | sort -V | head -n1)" = "$PR_VERSION" ] && [ "$PR_VERSION" != "$MASTER_VERSION" ]; then
|
||||
echo "Version in PR is not higher than master."
|
||||
exit 1
|
||||
else
|
||||
echo "Version in PR is higher than master."
|
||||
fi
|
|
@ -5,7 +5,7 @@ on:
|
|||
- dev
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -19,4 +19,7 @@ jobs:
|
|||
run: dotnet build --no-restore src/DotTiled.sln
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal src/DotTiled.sln
|
||||
|
||||
- name: Lint style
|
||||
run: dotnet format style --verify-no-changes --verbosity diagnostic src/DotTiled.sln
|
||||
- name: Lint analyzers
|
||||
run: dotnet format analyzers --verify-no-changes --verbosity diagnostic src/DotTiled.sln
|
30
.github/workflows/release-nuget.yml
vendored
Normal file
30
.github/workflows/release-nuget.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
release-nuget:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore src/DotTiled.sln
|
||||
- name: Build
|
||||
run: dotnet build --no-restore src/DotTiled.sln
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal src/DotTiled.sln
|
||||
- name: Lint style
|
||||
run: dotnet format style --verify-no-changes --verbosity diagnostic src/DotTiled.sln
|
||||
- name: Lint analyzers
|
||||
run: dotnet format analyzers --verify-no-changes --verbosity diagnostic src/DotTiled.sln
|
||||
- name: Pack
|
||||
run: make pack
|
||||
- name: Publish to NuGet.org
|
||||
run: |
|
||||
dotnet nuget push ./nupkg/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push ./nupkg/*.snupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Daniel Cronqvist (daniel@dcronqvist.se)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
18
Makefile
18
Makefile
|
@ -1,17 +1,25 @@
|
|||
test:
|
||||
dotnet build src/DotTiled.sln
|
||||
dotnet test src/DotTiled.sln
|
||||
|
||||
docs-serve: docs-build
|
||||
docs-serve:
|
||||
docfx docs/docfx.json --serve
|
||||
|
||||
docs-build:
|
||||
cp README.md docs/index.md
|
||||
docfx docs/docfx.json
|
||||
|
||||
BENCHMARK_SOURCES = DotTiled.Benchmark/Program.cs DotTiled.Benchmark/DotTiled.Benchmark.csproj
|
||||
BENCHMARK_OUTPUTDIR = DotTiled.Benchmark/BenchmarkDotNet.Artifacts
|
||||
lint:
|
||||
dotnet format style --verify-no-changes src/DotTiled.sln
|
||||
dotnet format analyzers --verify-no-changes src/DotTiled.sln
|
||||
|
||||
pack:
|
||||
dotnet pack src/DotTiled/DotTiled.csproj -c Release -o ./nupkg -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
|
||||
|
||||
BENCHMARK_SOURCES = src/DotTiled.Benchmark/Program.cs src/DotTiled.Benchmark/DotTiled.Benchmark.csproj
|
||||
BENCHMARK_OUTPUTDIR = src/DotTiled.Benchmark/BenchmarkDotNet.Artifacts
|
||||
.PHONY: benchmark
|
||||
benchmark: $(BENCHMARK_OUTPUTDIR)/results/MyBenchmarks.MapLoading-report-github.md
|
||||
|
||||
|
||||
$(BENCHMARK_OUTPUTDIR)/results/MyBenchmarks.MapLoading-report-github.md: $(BENCHMARK_SOURCES)
|
||||
dotnet run --project DotTiled.Benchmark/DotTiled.Benchmark.csproj -c Release -- $(BENCHMARK_OUTPUTDIR)
|
||||
dotnet run --project src/DotTiled.Benchmark/DotTiled.Benchmark.csproj -c Release -- $(BENCHMARK_OUTPUTDIR)
|
10
README.md
10
README.md
|
@ -4,11 +4,11 @@
|
|||
|
||||
DotTiled is a simple and easy-to-use library for loading, saving, and managing [Tiled maps and tilesets](https://mapeditor.org) in your .NET projects. After [TiledCS](https://github.com/TheBoneJarmer/TiledCS) unfortunately became unmaintained (since 2022), I aimed to create a new library that could fill its shoes. DotTiled is the result of that effort.
|
||||
|
||||
DotTiled is designed to be a lightweight and efficient library that provides a simple API for loading and managing Tiled maps and tilesets. It is built with performance in mind and aims to be as fast and memory-efficient as possible. Targeting `netstandard2.0` and `net8.0` allows DotTiled to be used in popular game engines like Unity and Godot, as well as in popular game development frameworks like MonoGame.
|
||||
DotTiled is designed to be a lightweight and efficient library that provides a simple API for loading and managing Tiled maps and tilesets. It is built with performance in mind and aims to be as fast and memory-efficient as possible.
|
||||
|
||||
- [Alternative libraries and comparison + benchmarks](#alternative-libraries-and-comparison)
|
||||
- [Feature coverage comparison](#feature-coverage-comparison)
|
||||
- [Installing DotTiled](#installing-dottiled)
|
||||
- [Quick Start](#quick-start)
|
||||
|
||||
# Alternative libraries and comparison
|
||||
|
||||
|
@ -20,7 +20,7 @@ Other similar libraries exist, and you may want to consider them for your projec
|
|||
| Benchmark (time)* | 1.00 | 1.83 | 2.16 | - | - | - |
|
||||
| Benchmark (memory)* | 1.00 | 1.43 | 2.03 | - | - | - |
|
||||
| .NET Targets | `net8.0` |`net6.0`<br>`net7.0`|`netstandard2.1`|`netstandard2.0`|`netstandard2.0`|`net45`|
|
||||
| Docs |Usage,<br>XML Docs|Usage|Usage, API,<br>XML Docs|Usage, API|Usage, XML Docs|Usage, XML Docs|
|
||||
| Docs |Usage, API,<br>XML Docs|Usage|Usage, API,<br>XML Docs|Usage, API|Usage, XML Docs|Usage, XML Docs|
|
||||
| License | MIT | MIT | MIT | Apache-2.0 | MIT | BSD 3-Clause |
|
||||
|
||||
> [!NOTE]
|
||||
|
@ -73,10 +73,12 @@ Below is a comparison of the feature coverage of DotTiled and other similar libr
|
|||
> [!NOTE]
|
||||
> ✅ Full support. ⚠️ Partial support, see respective library for details about supported features. ❌ No support.
|
||||
|
||||
# Installing DotTiled
|
||||
# Quick Start
|
||||
|
||||
DotTiled is available as a NuGet package. You can install it by using the NuGet Package Manager UI in Visual Studio, or equivalent, or using the following command for the .NET CLI:
|
||||
|
||||
```pwsh
|
||||
dotnet add package DotTiled
|
||||
```
|
||||
|
||||
Then head to the detailed [documentation](https://dcronqvist.github.io/DotTiled/docs/quickstart.html) for more information on how to use DotTiled in your project.
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"dest": "api"
|
||||
"dest": "api",
|
||||
"enumSortOrder": "declaringOrder"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
|
|
161
docs/docs/essentials/custom-properties.md
Normal file
161
docs/docs/essentials/custom-properties.md
Normal file
|
@ -0,0 +1,161 @@
|
|||
# Custom properties
|
||||
|
||||
[Tiled facilitates a very flexible way to store custom data in your maps using properties](https://doc.mapeditor.org/en/stable/manual/custom-properties/#custom-properties). Accessing these properties is a common task when working with Tiled maps in your game since it will allow you to fully utilize the strengths of Tiled, such as customizing the behavior of your game objects or setting up the initial state of your game world.
|
||||
|
||||
## All classes that can contain properties
|
||||
|
||||
All classes that can contain custom properties implement the interface <xref:DotTiled.IHasProperties> in some way. Below is an exhaustive list of all classes that can contain custom properties:
|
||||
|
||||
- <xref:DotTiled.BaseLayer>
|
||||
- <xref:DotTiled.TileLayer>
|
||||
- <xref:DotTiled.ObjectLayer>
|
||||
- <xref:DotTiled.ImageLayer>
|
||||
- <xref:DotTiled.Group>
|
||||
- <xref:DotTiled.ClassProperty> (allows for recursive property objects)
|
||||
- <xref:DotTiled.CustomClassDefinition> (used to define custom Tiled property types)
|
||||
- <xref:DotTiled.Object>
|
||||
- <xref:DotTiled.EllipseObject>
|
||||
- <xref:DotTiled.PointObject>
|
||||
- <xref:DotTiled.PolygonObject>
|
||||
- <xref:DotTiled.PolylineObject>
|
||||
- <xref:DotTiled.RectangleObject>
|
||||
- <xref:DotTiled.TextObject>
|
||||
- <xref:DotTiled.TileObject>
|
||||
- <xref:DotTiled.Tileset>
|
||||
- <xref:DotTiled.Tile>
|
||||
- <xref:DotTiled.WangTile>
|
||||
- <xref:DotTiled.WangColor>
|
||||
|
||||
## How to access properties
|
||||
|
||||
To access the properties on one of the classes listed above, you will make use of the <xref:DotTiled.IHasProperties> interface.
|
||||
|
||||
In situations where you know that a property must exist, and you simply want to retrieve it, you can use the <xref:DotTiled.IHasProperties.GetProperty``1(System.String)> method like so:
|
||||
|
||||
```csharp
|
||||
var map = LoadMap();
|
||||
var propertyValue = map.GetProperty<BoolProperty>("boolPropertyInMap").Value;
|
||||
```
|
||||
|
||||
If you are unsure whether a property exists, or you want to provide some kind of default behaviour if the property is not present, you can instead use the <xref:DotTiled.IHasProperties.TryGetProperty``1(System.String,``0@)> method like so:
|
||||
|
||||
```csharp
|
||||
var map = LoadMap();
|
||||
if (map.TryGetProperty<BoolProperty>("boolPropertyInMap", out var property))
|
||||
{
|
||||
// Do something with existing property
|
||||
var propertyValue = property.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do something if property does not exist
|
||||
}
|
||||
```
|
||||
|
||||
For both methods, you can replace `BoolProperty` with any of the property types that Tiled supports. You can find a list of all property types and their corresponding classes in the [next section](#all-types-of-properties).
|
||||
|
||||
## All types of properties
|
||||
|
||||
Tiled supports a variety of property types, which are represented in the DotTiled library as classes that implement the <xref:DotTiled.IProperty`1> interface. Below is a list of all property types that Tiled supports and their corresponding classes in DotTiled:
|
||||
|
||||
- `bool` - <xref:DotTiled.BoolProperty>
|
||||
- `color` - <xref:DotTiled.ColorProperty>
|
||||
- `float` - <xref:DotTiled.FloatProperty>
|
||||
- `file` - <xref:DotTiled.FileProperty>
|
||||
- `int` - <xref:DotTiled.IntProperty>
|
||||
- `object` - <xref:DotTiled.ObjectProperty>
|
||||
- `string` - <xref:DotTiled.StringProperty>
|
||||
|
||||
In addition to these primitive property types, [Tiled also supports more complex property types](https://doc.mapeditor.org/en/stable/manual/custom-properties/#custom-types). These custom property types are defined in Tiled according to the linked documentation, and to work with them in DotTiled, you *must* define their equivalences as a <xref:DotTiled.ICustomTypeDefinition>. You must then provide a resolving function to a defined type given a custom type name, as it is defined in Tiled.
|
||||
|
||||
## Custom types
|
||||
|
||||
Tiled allows you to define custom property types that can be used in your maps. These custom property types can be of type `class` or `enum`. DotTiled supports custom property types by allowing you to define the equivalent in C# and then providing a custom type resolver function that will return the equivalent definition given a custom type name.
|
||||
|
||||
### Class properties
|
||||
|
||||
Whenever DotTiled encounters a property that is of type `class` in a Tiled file, it will use the supplied custom type resolver function to retrieve the custom type definition. It will then use that definition to know the default values of the properties of that class, and then override those defaults with the values found in the Tiled file when populating a <xref:DotTiled.ClassProperty> instance. `class` properties allow you to create hierarchical structures of properties.
|
||||
|
||||
For example, if you have a `class` property in Tiled that looks like this:
|
||||
|
||||
![MonsterSpawner class in Tiled UI](../../images/monster-spawner-class.png)
|
||||
|
||||
The equivalent definition in DotTiled would look like the following:
|
||||
|
||||
```csharp
|
||||
var monsterSpawnerDefinition = new CustomClassDefinition
|
||||
{
|
||||
Name = "MonsterSpawner",
|
||||
UseAs = CustomClassUseAs.All, // Not really validated by DotTiled
|
||||
Members = [ // Make sure that the default values match the Tiled UI
|
||||
new BoolProperty { Name = "enabled", Value = true },
|
||||
new IntProperty { Name = "maxSpawnAmount", Value = 10 },
|
||||
new IntProperty { Name = "minSpawnAmount", Value = 0 },
|
||||
new StringProperty { Name = "monsterNames", Value = "" }
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### Enum properties
|
||||
|
||||
Tiled also allows you to define custom property types that work as enums. Similarly to `class` properties, you must define the equivalent in DotTiled as a <xref:DotTiled.CustomEnumDefinition>. You can then return the corresponding definition in the resolving function.
|
||||
|
||||
For example, if you have a custom property type in Tiled that looks like this:
|
||||
|
||||
![EntityType enum in Tiled UI](../../images/entity-type-enum.png)
|
||||
|
||||
The equivalent definition in DotTiled would look like the following:
|
||||
|
||||
```csharp
|
||||
var entityTypeDefinition = new CustomEnumDefinition
|
||||
{
|
||||
Name = "EntityType",
|
||||
StorageType = CustomEnumStorageType.String,
|
||||
ValueAsFlags = false,
|
||||
Values = [
|
||||
"Bomb",
|
||||
"Chest",
|
||||
"Flower",
|
||||
"Chair"
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### [Future] Automatically map custom property `class` types to C# classes
|
||||
|
||||
In the future, DotTiled will support automatically mapping custom property `class` types to C# classes. This will allow you to define a C# class that matches the structure of the `class` property in Tiled, and DotTiled will automatically map the properties of the `class` property to the properties of the C# class. This will make working with `class` properties much easier and more intuitive.
|
||||
|
||||
The idea is to expand on the <xref:DotTiled.IHasProperties> interface with a method like `GetMappedProperty<T>(string propertyName)`, where `T` is a class that matches the structure of the `class` property in Tiled.
|
||||
|
||||
This functionality would be accompanied by a way to automatically create a matching <xref:DotTiled.ICustomTypeDefinition> given a C# class or enum. Something like this would then be possible:
|
||||
|
||||
```csharp
|
||||
class MonsterSpawner
|
||||
{
|
||||
public bool Enabled { get; set; } = true;
|
||||
public int MaxSpawnAmount { get; set; } = 10;
|
||||
public int MinSpawnAmount { get; set; } = 0;
|
||||
public string MonsterNames { get; set; } = "";
|
||||
}
|
||||
|
||||
enum EntityType
|
||||
{
|
||||
Bomb,
|
||||
Chest,
|
||||
Flower,
|
||||
Chair
|
||||
}
|
||||
|
||||
var monsterSpawnerDefinition = CustomClassDefinition.FromClass<MonsterSpawner>();
|
||||
var entityTypeDefinition = CustomEnumDefinition.FromEnum<EntityType>();
|
||||
|
||||
// ...
|
||||
|
||||
var map = LoadMap();
|
||||
var monsterSpawner = map.GetMappedProperty<MonsterSpawner>("monsterSpawnerPropertyInMap");
|
||||
var entityType = map.GetMappedProperty<EntityType>("entityTypePropertyInMap");
|
||||
```
|
||||
|
||||
Finally, it might be possible to also make some kind of exporting functionality for <xref:DotTiled.ICustomTypeDefinition>. Given a collection of custom type definitions, DotTiled could generate a corresponding `propertytypes.json` file that you then can import into Tiled. This would make it so that you only have to define your custom property types once (in C#) and then import them into Tiled to use them in your maps.
|
||||
|
||||
Depending on implementation this might become something that can inhibit native AOT compilation due to potential reflection usage. Source generators could be used to mitigate this, but it is not yet clear how this will be implemented.
|
86
docs/docs/essentials/loading-maps.md
Normal file
86
docs/docs/essentials/loading-maps.md
Normal file
|
@ -0,0 +1,86 @@
|
|||
# Loading maps
|
||||
|
||||
Loading maps with DotTiled is straightforward and easy. The <xref:DotTiled.Map> class is a representation of a Tiled map, mimicking the structure of a Tiled map file. Map files can either be in the [`.tmx`/XML](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/) or [`.tmj`/json](https://doc.mapeditor.org/en/stable/reference/json-map-format/) format. DotTiled supports **both** formats fully.
|
||||
|
||||
> [!NOTE]
|
||||
> Using the `.tmj` file format will result in <xref:DotTiled.ImageLayer.Image> not having the same amount of information as for the `.tmx` format. This is due to the fact that the `.tmj` format does not include the full information that the `.tmx` format does. This is not a problem with DotTiled, but rather a limitation of the `.tmj` format.
|
||||
|
||||
## External resolution
|
||||
|
||||
Tiled maps may consist of several external files, such as tilesets or object templates. In Tiled map files, they are typically referenced by their path relative to the map file. It would be annoying to have to first load all these external resources before loading a map (which is how some other similar libraries work), so loading a map with DotTiled is designed in a way that you only have to provide a function that resolves these external resources. This way, DotTiled will figure out which external resources are needed and will invoke the corresponding resolver function to load them.
|
||||
|
||||
Loading a map, tileset, or template will require you to specify **three** resolver functions. We'll go through each of them below.
|
||||
|
||||
### `Func<string, Tileset>` - Tileset resolver
|
||||
|
||||
This function is used to resolve external tilesets by their source path. The function should return a <xref:DotTiled.Tileset> instance given the source path of the tileset. If you just want to load tilesets from the file system, you can use something like this:
|
||||
|
||||
```csharp
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
using var tilesetFileReader = new StreamReader(source);
|
||||
var tilesetString = tilesetReader.ReadToEnd();
|
||||
using var tilesetReader = new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
```
|
||||
|
||||
But, DotTiled is designed this way so you can retrieve your external resources from anywhere, such as a database or a custom file format, by implementing your own resolver function however you like. If you have some other means of accessing resources, you can use that instead of the file system.
|
||||
|
||||
```csharp
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
var tilesetString = ContentManager.GetString($"tilesets/{source}");
|
||||
using var tilesetReader = new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
```
|
||||
|
||||
### `Func<string, Template>` - Template resolver
|
||||
|
||||
This function is used to resolve external object templates by their source path. The function should return a <xref:DotTiled.Template> instance given the source path of the template. If you just want to load templates from the file system, you can use something very similar to the tileset resolver by replacing <xref:DotTiled.Serialization.TilesetReader> with <xref:DotTiled.Serialization.TemplateReader>.
|
||||
|
||||
### `Func<string, CustomType>` - Custom type resolver
|
||||
|
||||
This function is used to resolve custom types that are defined in Tiled maps. Please refer to the [custom properties](custom-properties.md) documentation for more information on custom types. The function should return a <xref:DotTiled.ICustomTypeDefinition> instance given the custom type's name.
|
||||
|
||||
## Putting it all together
|
||||
|
||||
The following classes are the readers that you will need to use to read the map, tileset, and template: <xref:DotTiled.Serialization.MapReader>, <xref:DotTiled.Serialization.TilesetReader>, and <xref:DotTiled.Serialization.TemplateReader>.
|
||||
|
||||
Here is an example of how you can load a map with DotTiled:
|
||||
|
||||
```csharp
|
||||
string mapPath = "path/to/map.tmx";
|
||||
string mapDirectory = Path.GetDirectoryName(mapPath);
|
||||
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
string tilesetPath = Path.Combine(mapDirectory, source);
|
||||
using var tilesetFileReader = new StreamReader(tilesetPath);
|
||||
var tilesetString = tilesetReader.ReadToEnd();
|
||||
using var tilesetReader = new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
|
||||
Template ResolveTemplate(string source)
|
||||
{
|
||||
string templatePath = Path.Combine(mapDirectory, source);
|
||||
using var templateFileReader = new StreamReader(templatePath);
|
||||
var templateString = templateReader.ReadToEnd();
|
||||
using var templateReader = new TemplateReader(templateString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return templateReader.ReadTemplate();
|
||||
}
|
||||
|
||||
ICustomTypeDefinition ResolveCustomType(string name)
|
||||
{
|
||||
var allDefinedTypes = [ ... ];
|
||||
return allDefinedTypes.FirstOrDefault(type => type.Name == name);
|
||||
}
|
||||
|
||||
using var mapFileReader = new StreamReader(mapPath);
|
||||
var mapString = mapFileReader.ReadToEnd();
|
||||
using var mapReader = new MapReader(mapString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
var map = mapReader.ReadMap();
|
||||
```
|
|
@ -1 +0,0 @@
|
|||
# Loading a map
|
|
@ -1 +1,46 @@
|
|||
# Quick Start
|
||||
# Quick Start
|
||||
|
||||
Install DotTiled from NuGet:
|
||||
|
||||
```bash
|
||||
dotnet add package DotTiled
|
||||
```
|
||||
|
||||
Load a map from file system:
|
||||
|
||||
```csharp
|
||||
string mapPath = "path/to/map.tmx";
|
||||
string mapDirectory = Path.GetDirectoryName(mapPath);
|
||||
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
string tilesetPath = Path.Combine(mapDirectory, source);
|
||||
using var tilesetFileReader = new StreamReader(tilesetPath);
|
||||
var tilesetString = tilesetReader.ReadToEnd();
|
||||
using var tilesetReader = new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
|
||||
Template ResolveTemplate(string source)
|
||||
{
|
||||
string templatePath = Path.Combine(mapDirectory, source);
|
||||
using var templateFileReader = new StreamReader(templatePath);
|
||||
var templateString = templateReader.ReadToEnd();
|
||||
using var templateReader = new TemplateReader(templateString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return templateReader.ReadTemplate();
|
||||
}
|
||||
|
||||
ICustomTypeDefinition ResolveCustomType(string name)
|
||||
{
|
||||
var allDefinedTypes = [ ... ];
|
||||
return allDefinedTypes.FirstOrDefault(type => type.Name == name);
|
||||
}
|
||||
|
||||
using var mapFileReader = new StreamReader(mapPath);
|
||||
var mapString = mapFileReader.ReadToEnd();
|
||||
using var mapReader = new MapReader(mapString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
var map = mapReader.ReadMap();
|
||||
```
|
||||
|
||||
If the above looks intimidating, don't worry! DotTiled is designed to be flexible and allow you to load maps from any source, such as a database or a custom file format. The above example is just one way to load a map from a file system. Please look at [Loading Maps](essentials/loading-maps.md) for more information on how to load maps from different sources.
|
|
@ -3,4 +3,5 @@
|
|||
- href: quickstart.md
|
||||
|
||||
- name: Essentials
|
||||
- href: loading-a-map.md
|
||||
- href: essentials/loading-maps.md
|
||||
- href: essentials/custom-properties.md
|
BIN
docs/images/entity-type-enum.png
Normal file
BIN
docs/images/entity-type-enum.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
docs/images/monster-spawner-class.png
Normal file
BIN
docs/images/monster-spawner-class.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
docs/images/resolve-types.png
Normal file
BIN
docs/images/resolve-types.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
|
@ -1,17 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Columns;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Order;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using BenchmarkDotNet.Running;
|
||||
|
||||
namespace MyBenchmarks
|
||||
namespace DotTiled.Benchmark
|
||||
{
|
||||
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
|
||||
[CategoriesColumn]
|
||||
|
@ -19,11 +15,11 @@ namespace MyBenchmarks
|
|||
[HideColumns(["StdDev", "Error", "RatioSD"])]
|
||||
public class MapLoading
|
||||
{
|
||||
private string _tmxPath = @"DotTiled.Tests/Serialization/TestData/Map/default-map/default-map.tmx";
|
||||
private string _tmxContents = "";
|
||||
private readonly string _tmxPath = @"DotTiled.Tests/Serialization/TestData/Map/default-map/default-map.tmx";
|
||||
private readonly string _tmxContents = "";
|
||||
|
||||
private string _tmjPath = @"DotTiled.Tests/Serialization/TestData/Map/default-map/default-map.tmj";
|
||||
private string _tmjContents = "";
|
||||
private readonly string _tmjPath = @"DotTiled.Tests/Serialization/TestData/Map/default-map/default-map.tmj";
|
||||
private readonly string _tmjContents = "";
|
||||
|
||||
public MapLoading()
|
||||
{
|
||||
|
@ -31,27 +27,27 @@ namespace MyBenchmarks
|
|||
var tmxPath = Path.Combine(basePath, $"../{_tmxPath}");
|
||||
var tmjPath = Path.Combine(basePath, $"../{_tmjPath}");
|
||||
|
||||
_tmxContents = System.IO.File.ReadAllText(tmxPath);
|
||||
_tmjContents = System.IO.File.ReadAllText(tmjPath);
|
||||
_tmxContents = File.ReadAllText(tmxPath);
|
||||
_tmjContents = File.ReadAllText(tmjPath);
|
||||
}
|
||||
|
||||
static string WhereAmI([CallerFilePath] string callerFilePath = "") => callerFilePath;
|
||||
private static string WhereAmI([CallerFilePath] string callerFilePath = "") => callerFilePath;
|
||||
|
||||
[BenchmarkCategory("MapFromInMemoryTmxString")]
|
||||
[Benchmark(Baseline = true, Description = "DotTiled")]
|
||||
public DotTiled.Model.Map LoadWithDotTiledFromInMemoryTmxString()
|
||||
public DotTiled.Map LoadWithDotTiledFromInMemoryTmxString()
|
||||
{
|
||||
using var stringReader = new StringReader(_tmxContents);
|
||||
using var xmlReader = XmlReader.Create(stringReader);
|
||||
using var mapReader = new DotTiled.Serialization.Tmx.TmxMapReader(xmlReader, _ => throw new Exception(), _ => throw new Exception(), []);
|
||||
using var mapReader = new DotTiled.Serialization.Tmx.TmxMapReader(xmlReader, _ => throw new NotSupportedException(), _ => throw new NotSupportedException(), _ => throw new NotSupportedException());
|
||||
return mapReader.ReadMap();
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromInMemoryTmjString")]
|
||||
[Benchmark(Baseline = true, Description = "DotTiled")]
|
||||
public DotTiled.Model.Map LoadWithDotTiledFromInMemoryTmjString()
|
||||
public DotTiled.Map LoadWithDotTiledFromInMemoryTmjString()
|
||||
{
|
||||
using var mapReader = new DotTiled.Serialization.Tmj.TmjMapReader(_tmjContents, _ => throw new Exception(), _ => throw new Exception(), []);
|
||||
using var mapReader = new DotTiled.Serialization.Tmj.TmjMapReader(_tmjContents, _ => throw new NotSupportedException(), _ => throw new NotSupportedException(), _ => throw new NotSupportedException());
|
||||
return mapReader.ReadMap();
|
||||
}
|
||||
|
||||
|
@ -84,11 +80,11 @@ namespace MyBenchmarks
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var config = BenchmarkDotNet.Configs.DefaultConfig.Instance
|
||||
var config = DefaultConfig.Instance
|
||||
.WithArtifactsPath(args[0])
|
||||
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||
.AddDiagnoser(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default);
|
||||
var summary = BenchmarkRunner.Run<MapLoading>(config);
|
||||
_ = BenchmarkRunner.Run<MapLoading>(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
using DotTiled.Model.Layers;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
using DotTiled.Model.Layers;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections;
|
||||
using System.Numerics;
|
||||
using DotTiled.Model;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -91,7 +90,7 @@ public static partial class DotTiledAssert
|
|||
AssertEqual(expected.NextObjectID, actual.NextObjectID, nameof(Map.NextObjectID));
|
||||
AssertEqual(expected.Infinite, actual.Infinite, nameof(Map.Infinite));
|
||||
|
||||
AssertProperties(actual.Properties, expected.Properties);
|
||||
AssertProperties(expected.Properties, actual.Properties);
|
||||
|
||||
Assert.NotNull(actual.Tilesets);
|
||||
AssertEqual(expected.Tilesets.Count, actual.Tilesets.Count, "Tilesets.Count");
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
using DotTiled.Model.Layers.Objects;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
{
|
||||
internal static void AssertObject(Model.Layers.Objects.Object expected, Model.Layers.Objects.Object actual)
|
||||
internal static void AssertObject(DotTiled.Object expected, DotTiled.Object actual)
|
||||
{
|
||||
// Attributes
|
||||
AssertEqual(expected.ID, actual.ID, nameof(Model.Layers.Objects.Object.ID));
|
||||
AssertEqual(expected.Name, actual.Name, nameof(Model.Layers.Objects.Object.Name));
|
||||
AssertEqual(expected.Type, actual.Type, nameof(Model.Layers.Objects.Object.Type));
|
||||
AssertEqual(expected.X, actual.X, nameof(Model.Layers.Objects.Object.X));
|
||||
AssertEqual(expected.Y, actual.Y, nameof(Model.Layers.Objects.Object.Y));
|
||||
AssertEqual(expected.Width, actual.Width, nameof(Model.Layers.Objects.Object.Width));
|
||||
AssertEqual(expected.Height, actual.Height, nameof(Model.Layers.Objects.Object.Height));
|
||||
AssertEqual(expected.Rotation, actual.Rotation, nameof(Model.Layers.Objects.Object.Rotation));
|
||||
AssertEqual(expected.Visible, actual.Visible, nameof(Model.Layers.Objects.Object.Visible));
|
||||
AssertEqual(expected.Template, actual.Template, nameof(Model.Layers.Objects.Object.Template));
|
||||
#pragma warning disable IDE0002
|
||||
AssertEqual(expected.ID, actual.ID, nameof(DotTiled.Object.ID));
|
||||
AssertEqual(expected.Name, actual.Name, nameof(DotTiled.Object.Name));
|
||||
AssertEqual(expected.Type, actual.Type, nameof(DotTiled.Object.Type));
|
||||
AssertEqual(expected.X, actual.X, nameof(DotTiled.Object.X));
|
||||
AssertEqual(expected.Y, actual.Y, nameof(DotTiled.Object.Y));
|
||||
AssertEqual(expected.Width, actual.Width, nameof(DotTiled.Object.Width));
|
||||
AssertEqual(expected.Height, actual.Height, nameof(DotTiled.Object.Height));
|
||||
AssertEqual(expected.Rotation, actual.Rotation, nameof(DotTiled.Object.Rotation));
|
||||
AssertEqual(expected.Visible, actual.Visible, nameof(DotTiled.Object.Visible));
|
||||
AssertEqual(expected.Template, actual.Template, nameof(DotTiled.Object.Template));
|
||||
#pragma warning restore IDE0002
|
||||
|
||||
AssertProperties(expected.Properties, actual.Properties);
|
||||
|
||||
|
@ -24,30 +24,15 @@ public static partial class DotTiledAssert
|
|||
AssertObject((dynamic)expected, (dynamic)actual);
|
||||
}
|
||||
|
||||
private static void AssertObject(RectangleObject expected, RectangleObject actual)
|
||||
{
|
||||
Assert.True(true); // A rectangle object is the same as the abstract Object
|
||||
}
|
||||
private static void AssertObject(RectangleObject _, RectangleObject __) => Assert.True(true); // A rectangle object is the same as the abstract Object
|
||||
|
||||
private static void AssertObject(EllipseObject expected, EllipseObject actual)
|
||||
{
|
||||
Assert.True(true); // An ellipse object is the same as the abstract Object
|
||||
}
|
||||
private static void AssertObject(EllipseObject _, EllipseObject __) => Assert.True(true); // An ellipse object is the same as the abstract Object
|
||||
|
||||
private static void AssertObject(PointObject expected, PointObject actual)
|
||||
{
|
||||
Assert.True(true); // A point object is the same as the abstract Object
|
||||
}
|
||||
private static void AssertObject(PointObject _, PointObject __) => Assert.True(true); // A point object is the same as the abstract Object
|
||||
|
||||
private static void AssertObject(PolygonObject expected, PolygonObject actual)
|
||||
{
|
||||
AssertEqual(expected.Points, actual.Points, nameof(PolygonObject.Points));
|
||||
}
|
||||
private static void AssertObject(PolygonObject expected, PolygonObject actual) => AssertEqual(expected.Points, actual.Points, nameof(PolygonObject.Points));
|
||||
|
||||
private static void AssertObject(PolylineObject expected, PolylineObject actual)
|
||||
{
|
||||
AssertEqual(expected.Points, actual.Points, nameof(PolylineObject.Points));
|
||||
}
|
||||
private static void AssertObject(PolylineObject expected, PolylineObject actual) => AssertEqual(expected.Points, actual.Points, nameof(PolylineObject.Points));
|
||||
|
||||
private static void AssertObject(TextObject expected, TextObject actual)
|
||||
{
|
||||
|
@ -67,9 +52,5 @@ public static partial class DotTiledAssert
|
|||
AssertEqual(expected.Text, actual.Text, nameof(TextObject.Text));
|
||||
}
|
||||
|
||||
private static void AssertObject(TileObject expected, TileObject actual)
|
||||
{
|
||||
// Attributes
|
||||
AssertEqual(expected.GID, actual.GID, nameof(TileObject.GID));
|
||||
}
|
||||
private static void AssertObject(TileObject expected, TileObject actual) => AssertEqual(expected.GID, actual.GID, nameof(TileObject.GID));
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
{
|
||||
internal static void AssertProperties(Dictionary<string, IProperty>? expected, Dictionary<string, IProperty>? actual)
|
||||
internal static void AssertProperties(IList<IProperty>? expected, IList<IProperty>? actual)
|
||||
{
|
||||
if (expected is null)
|
||||
{
|
||||
|
@ -14,58 +12,45 @@ public static partial class DotTiledAssert
|
|||
|
||||
Assert.NotNull(actual);
|
||||
AssertEqual(expected.Count, actual.Count, "Properties.Count");
|
||||
foreach (var kvp in expected)
|
||||
foreach (var prop in expected)
|
||||
{
|
||||
Assert.Contains(kvp.Key, actual.Keys);
|
||||
AssertProperty((dynamic)kvp.Value, (dynamic)actual[kvp.Key]);
|
||||
Assert.Contains(actual, p => p.Name == prop.Name);
|
||||
|
||||
var actualProp = actual.First(p => p.Name == prop.Name);
|
||||
AssertEqual(prop.Type, actualProp.Type, "Property.Type");
|
||||
AssertEqual(prop.Name, actualProp.Name, "Property.Name");
|
||||
|
||||
AssertProperty((dynamic)prop, (dynamic)actualProp);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertProperty(IProperty expected, IProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Type, actual.Type, "Property.Type");
|
||||
AssertEqual(expected.Name, actual.Name, "Property.Name");
|
||||
AssertProperties((dynamic)actual, (dynamic)expected);
|
||||
}
|
||||
private static void AssertProperty(StringProperty expected, StringProperty actual) => AssertEqual(expected.Value, actual.Value, "StringProperty.Value");
|
||||
|
||||
private static void AssertProperty(StringProperty expected, StringProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "StringProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(IntProperty expected, IntProperty actual) => AssertEqual(expected.Value, actual.Value, "IntProperty.Value");
|
||||
|
||||
private static void AssertProperty(IntProperty expected, IntProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "IntProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(FloatProperty expected, FloatProperty actual) => AssertEqual(expected.Value, actual.Value, "FloatProperty.Value");
|
||||
|
||||
private static void AssertProperty(FloatProperty expected, FloatProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "FloatProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(BoolProperty expected, BoolProperty actual) => AssertEqual(expected.Value, actual.Value, "BoolProperty.Value");
|
||||
|
||||
private static void AssertProperty(BoolProperty expected, BoolProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "BoolProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(ColorProperty expected, ColorProperty actual) => AssertEqual(expected.Value, actual.Value, "ColorProperty.Value");
|
||||
|
||||
private static void AssertProperty(ColorProperty expected, ColorProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "ColorProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(FileProperty expected, FileProperty actual) => AssertEqual(expected.Value, actual.Value, "FileProperty.Value");
|
||||
|
||||
private static void AssertProperty(FileProperty expected, FileProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "FileProperty.Value");
|
||||
}
|
||||
|
||||
private static void AssertProperty(ObjectProperty expected, ObjectProperty actual)
|
||||
{
|
||||
AssertEqual(expected.Value, actual.Value, "ObjectProperty.Value");
|
||||
}
|
||||
private static void AssertProperty(ObjectProperty expected, ObjectProperty actual) => AssertEqual(expected.Value, actual.Value, "ObjectProperty.Value");
|
||||
|
||||
private static void AssertProperty(ClassProperty expected, ClassProperty actual)
|
||||
{
|
||||
AssertEqual(expected.PropertyType, actual.PropertyType, "ClassProperty.PropertyType");
|
||||
AssertProperties(expected.Properties, actual.Properties);
|
||||
AssertProperties(expected.Value, actual.Value);
|
||||
}
|
||||
|
||||
private static void AssertProperty(EnumProperty expected, EnumProperty actual)
|
||||
{
|
||||
AssertEqual(expected.PropertyType, actual.PropertyType, "EnumProperty.PropertyType");
|
||||
AssertEqual(expected.Value.Count, actual.Value.Count, "EnumProperty.Value.Count");
|
||||
foreach (var value in expected.Value)
|
||||
{
|
||||
Assert.Contains(actual.Value, v => v == value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public static partial class DotTiledAssert
|
||||
|
@ -142,9 +139,9 @@ public static partial class DotTiledAssert
|
|||
AssertEqual(expected.Height, actual.Height, nameof(Tile.Height));
|
||||
|
||||
// Elements
|
||||
AssertProperties(actual.Properties, expected.Properties);
|
||||
AssertImage(actual.Image, expected.Image);
|
||||
AssertLayer((BaseLayer?)actual.ObjectLayer, (BaseLayer?)expected.ObjectLayer);
|
||||
AssertProperties(expected.Properties, actual.Properties);
|
||||
AssertImage(expected.Image, actual.Image);
|
||||
AssertLayer((BaseLayer?)expected.ObjectLayer, (BaseLayer?)actual.ObjectLayer);
|
||||
if (expected.Animation is not null)
|
||||
{
|
||||
Assert.NotNull(actual.Animation);
|
||||
|
|
49
src/DotTiled.Tests/Serialization/MapReaderTests.cs
Normal file
49
src/DotTiled.Tests/Serialization/MapReaderTests.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using DotTiled.Serialization;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public partial class MapReaderTests
|
||||
{
|
||||
public static IEnumerable<object[]> Maps => TestData.MapTests;
|
||||
[Theory]
|
||||
[MemberData(nameof(Maps))]
|
||||
public void MapReaderReadMap_ValidFilesExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected(
|
||||
string testDataFile,
|
||||
Func<string, Map> expectedMap,
|
||||
IReadOnlyCollection<ICustomTypeDefinition> customTypeDefinitions)
|
||||
{
|
||||
// Arrange
|
||||
string[] fileFormats = [".tmx", ".tmj"];
|
||||
|
||||
foreach (var fileFormat in fileFormats)
|
||||
{
|
||||
var testDataFileWithFormat = testDataFile + fileFormat;
|
||||
var fileDir = Path.GetDirectoryName(testDataFileWithFormat);
|
||||
var mapString = TestData.GetRawStringFor(testDataFileWithFormat);
|
||||
Template ResolveTemplate(string source)
|
||||
{
|
||||
var templateString = TestData.GetRawStringFor($"{fileDir}/{source}");
|
||||
using var templateReader = new TemplateReader(templateString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return templateReader.ReadTemplate();
|
||||
}
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
var tilesetString = TestData.GetRawStringFor($"{fileDir}/{source}");
|
||||
using var tilesetReader = new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
ICustomTypeDefinition ResolveCustomType(string name)
|
||||
{
|
||||
return customTypeDefinitions.FirstOrDefault(ctd => ctd.Name == name)!;
|
||||
}
|
||||
using var mapReader = new MapReader(mapString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
// Act
|
||||
var map = mapReader.ReadMap();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(map);
|
||||
DotTiledAssert.AssertMap(expectedMap(fileFormat[1..]), map);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
using System.Xml;
|
||||
using DotTiled.Model.Properties;
|
||||
using DotTiled.Model.Properties.CustomTypes;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -33,49 +31,15 @@ public static partial class TestData
|
|||
|
||||
public static IEnumerable<object[]> MapTests =>
|
||||
[
|
||||
["Serialization/TestData/Map/default_map/default-map", (string f) => TestData.DefaultMap(), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_common_props/map-with-common-props", (string f) => TestData.MapWithCommonProps(), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_custom_type_props/map-with-custom-type-props", (string f) => TestData.MapWithCustomTypeProps(), TestData.MapWithCustomTypePropsCustomTypeDefinitions()],
|
||||
["Serialization/TestData/Map/map_with_embedded_tileset/map-with-embedded-tileset", (string f) => TestData.MapWithEmbeddedTileset(), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_external_tileset/map-with-external-tileset", (string f) => TestData.MapWithExternalTileset(f), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_flippingflags/map-with-flippingflags", (string f) => TestData.MapWithFlippingFlags(f), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_external_tileset_multi/map-external-tileset-multi", (string f) => TestData.MapExternalTilesetMulti(f), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_external_tileset_wangset/map-external-tileset-wangset", (string f) => TestData.MapExternalTilesetWangset(f), Array.Empty<CustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_many_layers/map-with-many-layers", (string f) => TestData.MapWithManyLayers(f), Array.Empty<CustomTypeDefinition>()],
|
||||
];
|
||||
|
||||
private static CustomTypeDefinition[] typedefs = [
|
||||
new CustomClassDefinition
|
||||
{
|
||||
Name = "TestClass",
|
||||
ID = 1,
|
||||
UseAs = CustomClassUseAs.Property,
|
||||
Members = [
|
||||
new StringProperty
|
||||
{
|
||||
Name = "Name",
|
||||
Value = ""
|
||||
},
|
||||
new FloatProperty
|
||||
{
|
||||
Name = "Amount",
|
||||
Value = 0f
|
||||
}
|
||||
]
|
||||
},
|
||||
new CustomClassDefinition
|
||||
{
|
||||
Name = "Test",
|
||||
ID = 2,
|
||||
UseAs = CustomClassUseAs.All,
|
||||
Members = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "Yep",
|
||||
PropertyType = "TestClass",
|
||||
Properties = []
|
||||
}
|
||||
]
|
||||
}
|
||||
["Serialization/TestData/Map/default_map/default-map", (string f) => DefaultMap(), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_common_props/map-with-common-props", (string f) => MapWithCommonProps(), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_custom_type_props/map-with-custom-type-props", (string f) => MapWithCustomTypeProps(), MapWithCustomTypePropsCustomTypeDefinitions()],
|
||||
["Serialization/TestData/Map/map_with_embedded_tileset/map-with-embedded-tileset", (string f) => MapWithEmbeddedTileset(), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_external_tileset/map-with-external-tileset", (string f) => MapWithExternalTileset(f), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_flippingflags/map-with-flippingflags", (string f) => MapWithFlippingFlags(f), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_external_tileset_multi/map-external-tileset-multi", (string f) => MapExternalTilesetMulti(f), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_external_tileset_wangset/map-external-tileset-wangset", (string f) => MapExternalTilesetWangset(f), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_many_layers/map-with-many-layers", (string f) => MapWithManyLayers(f), Array.Empty<ICustomTypeDefinition>()],
|
||||
["Serialization/TestData/Map/map_with_deep_props/map-with-deep-props", (string f) => MapWithDeepProps(), MapWithDeepPropsCustomTypeDefinitions()],
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public partial class TestData
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Properties;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -52,16 +48,15 @@ public partial class TestData
|
|||
Width = 1,
|
||||
Height = 1
|
||||
},
|
||||
Properties = new Dictionary<string, IProperty>
|
||||
{
|
||||
["tilesetbool"] = new BoolProperty { Name = "tilesetbool", Value = true },
|
||||
["tilesetcolor"] = new ColorProperty { Name = "tilesetcolor", Value = Color.Parse("#ffff0000", CultureInfo.InvariantCulture) },
|
||||
["tilesetfile"] = new FileProperty { Name = "tilesetfile", Value = "" },
|
||||
["tilesetfloat"] = new FloatProperty { Name = "tilesetfloat", Value = 5.2f },
|
||||
["tilesetint"] = new IntProperty { Name = "tilesetint", Value = 9 },
|
||||
["tilesetobject"] = new ObjectProperty { Name = "tilesetobject", Value = 0 },
|
||||
["tilesetstring"] = new StringProperty { Name = "tilesetstring", Value = "hello world!" }
|
||||
},
|
||||
Properties = [
|
||||
new BoolProperty { Name = "tilesetbool", Value = true },
|
||||
new ColorProperty { Name = "tilesetcolor", Value = Color.Parse("#ffff0000", CultureInfo.InvariantCulture) },
|
||||
new FileProperty { Name = "tilesetfile", Value = "" },
|
||||
new FloatProperty { Name = "tilesetfloat", Value = 5.2f },
|
||||
new IntProperty { Name = "tilesetint", Value = 9 },
|
||||
new ObjectProperty { Name = "tilesetobject", Value = 0 },
|
||||
new StringProperty { Name = "tilesetstring", Value = "hello world!" }
|
||||
],
|
||||
Tiles = [
|
||||
new Tile
|
||||
{
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -57,15 +54,15 @@ public partial class TestData
|
|||
}
|
||||
}
|
||||
],
|
||||
Properties = new Dictionary<string, IProperty>
|
||||
{
|
||||
["boolprop"] = new BoolProperty { Name = "boolprop", Value = true },
|
||||
["colorprop"] = new ColorProperty { Name = "colorprop", Value = Color.Parse("#ff55ffff", CultureInfo.InvariantCulture) },
|
||||
["fileprop"] = new FileProperty { Name = "fileprop", Value = "file.txt" },
|
||||
["floatprop"] = new FloatProperty { Name = "floatprop", Value = 4.2f },
|
||||
["intprop"] = new IntProperty { Name = "intprop", Value = 8 },
|
||||
["objectprop"] = new ObjectProperty { Name = "objectprop", Value = 5 },
|
||||
["stringprop"] = new StringProperty { Name = "stringprop", Value = "This is a string, hello world!" }
|
||||
}
|
||||
Properties =
|
||||
[
|
||||
new BoolProperty { Name = "boolprop", Value = true },
|
||||
new ColorProperty { Name = "colorprop", Value = Color.Parse("#ff55ffff", CultureInfo.InvariantCulture) },
|
||||
new FileProperty { Name = "fileprop", Value = "file.txt" },
|
||||
new FloatProperty { Name = "floatprop", Value = 4.2f },
|
||||
new IntProperty { Name = "intprop", Value = 8 },
|
||||
new ObjectProperty { Name = "objectprop", Value = 5 },
|
||||
new StringProperty { Name = "stringprop", Value = "This is a string, hello world!" }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Properties;
|
||||
using DotTiled.Model.Properties.CustomTypes;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -58,28 +54,50 @@ public partial class TestData
|
|||
}
|
||||
}
|
||||
],
|
||||
Properties = new Dictionary<string, IProperty>
|
||||
{
|
||||
["customclassprop"] = new ClassProperty
|
||||
Properties = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customclassprop",
|
||||
PropertyType = "CustomClass",
|
||||
Properties = new Dictionary<string, IProperty>
|
||||
{
|
||||
["boolinclass"] = new BoolProperty { Name = "boolinclass", Value = true },
|
||||
["colorinclass"] = new ColorProperty { Name = "colorinclass", Value = Color.Parse("#000000ff", CultureInfo.InvariantCulture) },
|
||||
["fileinclass"] = new FileProperty { Name = "fileinclass", Value = "" },
|
||||
["floatinclass"] = new FloatProperty { Name = "floatinclass", Value = 13.37f },
|
||||
["intinclass"] = new IntProperty { Name = "intinclass", Value = 0 },
|
||||
["objectinclass"] = new ObjectProperty { Name = "objectinclass", Value = 0 },
|
||||
["stringinclass"] = new StringProperty { Name = "stringinclass", Value = "This is a set string" }
|
||||
}
|
||||
Value = [
|
||||
new BoolProperty { Name = "boolinclass", Value = true },
|
||||
new ColorProperty { Name = "colorinclass", Value = Color.Parse("#000000ff", CultureInfo.InvariantCulture) },
|
||||
new FileProperty { Name = "fileinclass", Value = "" },
|
||||
new FloatProperty { Name = "floatinclass", Value = 13.37f },
|
||||
new IntProperty { Name = "intinclass", Value = 0 },
|
||||
new ObjectProperty { Name = "objectinclass", Value = 0 },
|
||||
new StringProperty { Name = "stringinclass", Value = "This is a set string" }
|
||||
]
|
||||
},
|
||||
new EnumProperty
|
||||
{
|
||||
Name = "customenumstringprop",
|
||||
PropertyType = "CustomEnumString",
|
||||
Value = new HashSet<string> { "CustomEnumString_2" }
|
||||
},
|
||||
new EnumProperty
|
||||
{
|
||||
Name = "customenumstringflagsprop",
|
||||
PropertyType = "CustomEnumStringFlags",
|
||||
Value = new HashSet<string> { "CustomEnumStringFlags_1", "CustomEnumStringFlags_2" }
|
||||
},
|
||||
new EnumProperty
|
||||
{
|
||||
Name = "customenumintprop",
|
||||
PropertyType = "CustomEnumInt",
|
||||
Value = new HashSet<string> { "CustomEnumInt_4" }
|
||||
},
|
||||
new EnumProperty
|
||||
{
|
||||
Name = "customenumintflagsprop",
|
||||
PropertyType = "CustomEnumIntFlags",
|
||||
Value = new HashSet<string> { "CustomEnumIntFlags_2", "CustomEnumIntFlags_3" }
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// This comes from map-with-custom-type-props/propertytypes.json
|
||||
public static IReadOnlyCollection<CustomTypeDefinition> MapWithCustomTypePropsCustomTypeDefinitions() => [
|
||||
public static IReadOnlyCollection<ICustomTypeDefinition> MapWithCustomTypePropsCustomTypeDefinitions() => [
|
||||
new CustomClassDefinition
|
||||
{
|
||||
Name = "CustomClass",
|
||||
|
@ -121,6 +139,50 @@ public partial class TestData
|
|||
Value = ""
|
||||
}
|
||||
]
|
||||
},
|
||||
new CustomEnumDefinition
|
||||
{
|
||||
Name = "CustomEnumString",
|
||||
StorageType = CustomEnumStorageType.String,
|
||||
ValueAsFlags = false,
|
||||
Values = [
|
||||
"CustomEnumString_1",
|
||||
"CustomEnumString_2",
|
||||
"CustomEnumString_3"
|
||||
]
|
||||
},
|
||||
new CustomEnumDefinition
|
||||
{
|
||||
Name = "CustomEnumStringFlags",
|
||||
StorageType = CustomEnumStorageType.String,
|
||||
ValueAsFlags = true,
|
||||
Values = [
|
||||
"CustomEnumStringFlags_1",
|
||||
"CustomEnumStringFlags_2"
|
||||
]
|
||||
},
|
||||
new CustomEnumDefinition
|
||||
{
|
||||
Name = "CustomEnumInt",
|
||||
StorageType = CustomEnumStorageType.Int,
|
||||
ValueAsFlags = false,
|
||||
Values = [
|
||||
"CustomEnumInt_1",
|
||||
"CustomEnumInt_2",
|
||||
"CustomEnumInt_3",
|
||||
"CustomEnumInt_4",
|
||||
]
|
||||
},
|
||||
new CustomEnumDefinition
|
||||
{
|
||||
Name = "CustomEnumIntFlags",
|
||||
StorageType = CustomEnumStorageType.Int,
|
||||
ValueAsFlags = true,
|
||||
Values = [
|
||||
"CustomEnumIntFlags_1",
|
||||
"CustomEnumIntFlags_2",
|
||||
"CustomEnumIntFlags_3"
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -32,6 +32,30 @@
|
|||
"floatinclass":13.37,
|
||||
"stringinclass":"This is a set string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"customenumintflagsprop",
|
||||
"propertytype":"CustomEnumIntFlags",
|
||||
"type":"int",
|
||||
"value":6
|
||||
},
|
||||
{
|
||||
"name":"customenumintprop",
|
||||
"propertytype":"CustomEnumInt",
|
||||
"type":"int",
|
||||
"value":3
|
||||
},
|
||||
{
|
||||
"name":"customenumstringflagsprop",
|
||||
"propertytype":"CustomEnumStringFlags",
|
||||
"type":"string",
|
||||
"value":"CustomEnumStringFlags_1,CustomEnumStringFlags_2"
|
||||
},
|
||||
{
|
||||
"name":"customenumstringprop",
|
||||
"propertytype":"CustomEnumString",
|
||||
"type":"string",
|
||||
"value":"CustomEnumString_2"
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.11.0",
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
<property name="stringinclass" value="This is a set string"/>
|
||||
</properties>
|
||||
</property>
|
||||
<property name="customenumintflagsprop" type="int" propertytype="CustomEnumIntFlags" value="6"/>
|
||||
<property name="customenumintprop" type="int" propertytype="CustomEnumInt" value="3"/>
|
||||
<property name="customenumstringflagsprop" propertytype="CustomEnumStringFlags" value="CustomEnumStringFlags_1,CustomEnumStringFlags_2"/>
|
||||
<property name="customenumstringprop" propertytype="CustomEnumString" value="CustomEnumString_2"/>
|
||||
</properties>
|
||||
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||
<data encoding="csv">
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
public partial class TestData
|
||||
{
|
||||
public static Map MapWithDeepProps() => new Map
|
||||
{
|
||||
Class = "",
|
||||
Orientation = MapOrientation.Orthogonal,
|
||||
Width = 5,
|
||||
Height = 5,
|
||||
TileWidth = 32,
|
||||
TileHeight = 32,
|
||||
Infinite = false,
|
||||
HexSideLength = null,
|
||||
StaggerAxis = null,
|
||||
StaggerIndex = null,
|
||||
ParallaxOriginX = 0,
|
||||
ParallaxOriginY = 0,
|
||||
RenderOrder = RenderOrder.RightDown,
|
||||
CompressionLevel = -1,
|
||||
BackgroundColor = Color.Parse("#00000000", CultureInfo.InvariantCulture),
|
||||
Version = "1.10",
|
||||
TiledVersion = "1.11.0",
|
||||
NextLayerID = 2,
|
||||
NextObjectID = 1,
|
||||
Layers = [
|
||||
new TileLayer
|
||||
{
|
||||
ID = 1,
|
||||
Name = "Tile Layer 1",
|
||||
Width = 5,
|
||||
Height = 5,
|
||||
Data = new Data
|
||||
{
|
||||
Encoding = DataEncoding.Csv,
|
||||
Chunks = null,
|
||||
Compression = null,
|
||||
GlobalTileIDs = [
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0
|
||||
],
|
||||
FlippingFlags = [
|
||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
|
||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
|
||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
|
||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
|
||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
Properties = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customouterclassprop",
|
||||
PropertyType = "CustomOuterClass",
|
||||
Value = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customclasspropinclass",
|
||||
PropertyType = "CustomClass",
|
||||
Value = [
|
||||
new BoolProperty { Name = "boolinclass", Value = false },
|
||||
new ColorProperty { Name = "colorinclass", Value = Color.Parse("#000000ff", CultureInfo.InvariantCulture) },
|
||||
new FileProperty { Name = "fileinclass", Value = "" },
|
||||
new FloatProperty { Name = "floatinclass", Value = 0f },
|
||||
new IntProperty { Name = "intinclass", Value = 0 },
|
||||
new ObjectProperty { Name = "objectinclass", Value = 0 },
|
||||
new StringProperty { Name = "stringinclass", Value = "" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customouterclasspropset",
|
||||
PropertyType = "CustomOuterClass",
|
||||
Value = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customclasspropinclass",
|
||||
PropertyType = "CustomClass",
|
||||
Value = [
|
||||
new BoolProperty { Name = "boolinclass", Value = true },
|
||||
new ColorProperty { Name = "colorinclass", Value = Color.Parse("#000000ff", CultureInfo.InvariantCulture) },
|
||||
new FileProperty { Name = "fileinclass", Value = "" },
|
||||
new FloatProperty { Name = "floatinclass", Value = 13.37f },
|
||||
new IntProperty { Name = "intinclass", Value = 0 },
|
||||
new ObjectProperty { Name = "objectinclass", Value = 0 },
|
||||
new StringProperty { Name = "stringinclass", Value = "" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
public static IReadOnlyCollection<ICustomTypeDefinition> MapWithDeepPropsCustomTypeDefinitions() => [
|
||||
new CustomClassDefinition
|
||||
{
|
||||
Name = "CustomClass",
|
||||
UseAs = CustomClassUseAs.Property,
|
||||
Members = [
|
||||
new BoolProperty
|
||||
{
|
||||
Name = "boolinclass",
|
||||
Value = false
|
||||
},
|
||||
new ColorProperty
|
||||
{
|
||||
Name = "colorinclass",
|
||||
Value = Color.Parse("#000000ff", CultureInfo.InvariantCulture)
|
||||
},
|
||||
new FileProperty
|
||||
{
|
||||
Name = "fileinclass",
|
||||
Value = ""
|
||||
},
|
||||
new FloatProperty
|
||||
{
|
||||
Name = "floatinclass",
|
||||
Value = 0f
|
||||
},
|
||||
new IntProperty
|
||||
{
|
||||
Name = "intinclass",
|
||||
Value = 0
|
||||
},
|
||||
new ObjectProperty
|
||||
{
|
||||
Name = "objectinclass",
|
||||
Value = 0
|
||||
},
|
||||
new StringProperty
|
||||
{
|
||||
Name = "stringinclass",
|
||||
Value = ""
|
||||
}
|
||||
]
|
||||
},
|
||||
new CustomClassDefinition
|
||||
{
|
||||
Name = "CustomOuterClass",
|
||||
UseAs = CustomClassUseAs.Property,
|
||||
Members = [
|
||||
new ClassProperty
|
||||
{
|
||||
Name = "customclasspropinclass",
|
||||
PropertyType = "CustomClass",
|
||||
Value = [] // So no overrides of defaults in CustomClass
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
{ "compressionlevel":-1,
|
||||
"height":5,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0],
|
||||
"height":5,
|
||||
"id":1,
|
||||
"name":"Tile Layer 1",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":5,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":2,
|
||||
"nextobjectid":1,
|
||||
"orientation":"orthogonal",
|
||||
"properties":[
|
||||
{
|
||||
"name":"customouterclassprop",
|
||||
"propertytype":"CustomOuterClass",
|
||||
"type":"class",
|
||||
"value":
|
||||
{
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"customouterclasspropset",
|
||||
"propertytype":"CustomOuterClass",
|
||||
"type":"class",
|
||||
"value":
|
||||
{
|
||||
"customclasspropinclass":
|
||||
{
|
||||
"boolinclass":true,
|
||||
"floatinclass":13.37
|
||||
}
|
||||
}
|
||||
}],
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.11.0",
|
||||
"tileheight":32,
|
||||
"tilesets":[],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":"1.10",
|
||||
"width":5
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||
<properties>
|
||||
<property name="customouterclassprop" type="class" propertytype="CustomOuterClass"/>
|
||||
<property name="customouterclasspropset" type="class" propertytype="CustomOuterClass">
|
||||
<properties>
|
||||
<property name="customclasspropinclass" type="class" propertytype="CustomClass">
|
||||
<properties>
|
||||
<property name="boolinclass" type="bool" value="true"/>
|
||||
<property name="floatinclass" type="float" value="13.37"/>
|
||||
</properties>
|
||||
</property>
|
||||
</properties>
|
||||
</property>
|
||||
</properties>
|
||||
<layer id="1" name="Tile Layer 1" width="5" height="5">
|
||||
<data encoding="csv">
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
|
@ -1,7 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System.Globalization;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
using System.Numerics;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Layers.Objects;
|
||||
using DotTiled.Model.Properties;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
||||
|
@ -99,10 +94,9 @@ public partial class TestData
|
|||
new Vector2(35.6667f, 32.3333f)
|
||||
],
|
||||
Template = fileExt == "tmx" ? "poly.tx" : "poly.tj",
|
||||
Properties = new Dictionary<string, IProperty>
|
||||
{
|
||||
["templateprop"] = new StringProperty { Name = "templateprop", Value = "helo there" }
|
||||
}
|
||||
Properties = [
|
||||
new StringProperty { Name = "templateprop", Value = "helo there" }
|
||||
]
|
||||
},
|
||||
new TileObject
|
||||
{
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
using DotTiled.Model;
|
||||
using DotTiled.Model.Properties.CustomTypes;
|
||||
using DotTiled.Model.Tilesets;
|
||||
using DotTiled.Serialization.Tmj;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
@ -13,7 +10,7 @@ public partial class TmjMapReaderTests
|
|||
public void TmxMapReaderReadMap_ValidTmjExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected(
|
||||
string testDataFile,
|
||||
Func<string, Map> expectedMap,
|
||||
IReadOnlyCollection<CustomTypeDefinition> customTypeDefinitions)
|
||||
IReadOnlyCollection<ICustomTypeDefinition> customTypeDefinitions)
|
||||
{
|
||||
// Arrange
|
||||
testDataFile += ".tmj";
|
||||
|
@ -22,16 +19,20 @@ public partial class TmjMapReaderTests
|
|||
Template ResolveTemplate(string source)
|
||||
{
|
||||
var templateJson = TestData.GetRawStringFor($"{fileDir}/{source}");
|
||||
using var templateReader = new TjTemplateReader(templateJson, ResolveTileset, ResolveTemplate, customTypeDefinitions);
|
||||
using var templateReader = new TjTemplateReader(templateJson, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return templateReader.ReadTemplate();
|
||||
}
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
var tilesetJson = TestData.GetRawStringFor($"{fileDir}/{source}");
|
||||
using var tilesetReader = new TsjTilesetReader(tilesetJson, ResolveTemplate, customTypeDefinitions);
|
||||
using var tilesetReader = new TsjTilesetReader(tilesetJson, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
using var mapReader = new TmjMapReader(json, ResolveTileset, ResolveTemplate, customTypeDefinitions);
|
||||
ICustomTypeDefinition ResolveCustomType(string name)
|
||||
{
|
||||
return customTypeDefinitions.FirstOrDefault(ctd => ctd.Name == name)!;
|
||||
}
|
||||
using var mapReader = new TmjMapReader(json, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
// Act
|
||||
var map = mapReader.ReadMap();
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
using System.Xml;
|
||||
using DotTiled.Model;
|
||||
using DotTiled.Model.Properties.CustomTypes;
|
||||
using DotTiled.Model.Tilesets;
|
||||
using DotTiled.Serialization.Tmx;
|
||||
|
||||
namespace DotTiled.Tests;
|
||||
|
@ -14,7 +10,7 @@ public partial class TmxMapReaderTests
|
|||
public void TmxMapReaderReadMap_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected(
|
||||
string testDataFile,
|
||||
Func<string, Map> expectedMap,
|
||||
IReadOnlyCollection<CustomTypeDefinition> customTypeDefinitions)
|
||||
IReadOnlyCollection<ICustomTypeDefinition> customTypeDefinitions)
|
||||
{
|
||||
// Arrange
|
||||
testDataFile += ".tmx";
|
||||
|
@ -23,16 +19,20 @@ public partial class TmxMapReaderTests
|
|||
Template ResolveTemplate(string source)
|
||||
{
|
||||
using var xmlTemplateReader = TestData.GetXmlReaderFor($"{fileDir}/{source}");
|
||||
using var templateReader = new TxTemplateReader(xmlTemplateReader, ResolveTileset, ResolveTemplate, customTypeDefinitions);
|
||||
using var templateReader = new TxTemplateReader(xmlTemplateReader, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return templateReader.ReadTemplate();
|
||||
}
|
||||
Tileset ResolveTileset(string source)
|
||||
{
|
||||
using var xmlTilesetReader = TestData.GetXmlReaderFor($"{fileDir}/{source}");
|
||||
using var tilesetReader = new TsxTilesetReader(xmlTilesetReader, ResolveTemplate, customTypeDefinitions);
|
||||
using var tilesetReader = new TsxTilesetReader(xmlTilesetReader, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
using var mapReader = new TmxMapReader(reader, ResolveTileset, ResolveTemplate, customTypeDefinitions);
|
||||
ICustomTypeDefinition ResolveCustomType(string name)
|
||||
{
|
||||
return customTypeDefinitions.FirstOrDefault(ctd => ctd.Name == name)!;
|
||||
}
|
||||
using var mapReader = new TmxMapReader(reader, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
// Act
|
||||
var map = mapReader.ReadMap();
|
||||
|
|
|
@ -2,21 +2,55 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
|
||||
namespace DotTiled.Model;
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Tiled color.
|
||||
/// </summary>
|
||||
public class Color : IParsable<Color>, IEquatable<Color>
|
||||
{
|
||||
/// <summary>
|
||||
/// The red component of the color.
|
||||
/// </summary>
|
||||
public required byte R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The green component of the color.
|
||||
/// </summary>
|
||||
public required byte G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The blue component of the color.
|
||||
/// </summary>
|
||||
public required byte B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The alpha component of the color.
|
||||
/// </summary>
|
||||
public byte A { get; set; } = 255;
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse the specified string into a <see cref="Color"/>. Expects strings in the format <c>#RRGGBB</c> or <c>#AARRGGBB</c>.
|
||||
/// The leading <c>#</c> is optional.
|
||||
/// </summary>
|
||||
/// <param name="s">A string value to parse into a <see cref="Color"/></param>
|
||||
/// <param name="provider">An object that supplies culture-specific information about the format of s.</param>
|
||||
/// <returns>The parsed <see cref="Color"/></returns>
|
||||
/// <exception cref="FormatException">Thrown in case the provided string <paramref name="s"/> is not in a valid format.</exception>
|
||||
public static Color Parse(string s, IFormatProvider? provider)
|
||||
{
|
||||
TryParse(s, provider, out var result);
|
||||
_ = TryParse(s, provider, out var result);
|
||||
return result ?? throw new FormatException($"Invalid format for TiledColor: {s}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse the specified string into a <see cref="Color"/>. Expects strings in the format <c>#RRGGBB</c> or <c>#AARRGGBB</c>.
|
||||
/// The leading <c>#</c> is optional.
|
||||
/// </summary>
|
||||
/// <param name="s">A string value to parse into a <see cref="Color"/></param>
|
||||
/// <param name="provider">An object that supplies culture-specific information about the format of s.</param>
|
||||
/// <param name="result">When this method returns, contains the parsed <see cref="Color"/> or <c>null</c> on failure.</param>
|
||||
/// <returns><c>true</c> if <paramref name="s"/> was successfully parsed; otherwise, <c>false</c>.</returns>
|
||||
public static bool TryParse(
|
||||
[NotNullWhen(true)] string? s,
|
||||
IFormatProvider? provider,
|
||||
|
@ -26,7 +60,7 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
|||
return TryParse($"#{s}", provider, out result);
|
||||
|
||||
// Format: #RRGGBB or #AARRGGBB
|
||||
if (s is null || s.Length != 7 && s.Length != 9 || s[0] != '#')
|
||||
if (s is null || (s.Length != 7 && s.Length != 9) || s[0] != '#')
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
|
@ -55,6 +89,7 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(Color? other)
|
||||
{
|
||||
if (other is null)
|
||||
|
@ -63,9 +98,12 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
|||
return R == other.R && G == other.G && B == other.B && A == other.A;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj) => obj is Color other && Equals(other);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => HashCode.Combine(R, G, B, A);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"#{A:x2}{R:x2}{G:x2}{B:x2}";
|
||||
}
|
|
@ -3,6 +3,28 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageId>DotTiled</PackageId>
|
||||
<Authors>dcronqvist</Authors>
|
||||
<Title>DotTiled</Title>
|
||||
<Description>DotTiled is a general-purpose Tiled map parser for all your .NET needs.</Description>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/dcronqvist/DotTiled</RepositoryUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageTags>gamedev;window;parser;tiled;mapeditor</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/dcronqvist/DotTiled</PackageProjectUrl>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<Copyright>Copyright © 2024 dcronqvist</Copyright>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<Version>0.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../README.md" Pack="true" PackagePath="" />
|
||||
<None Include="../../LICENSE" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
69
src/DotTiled/Layers/BaseLayer.cs
Normal file
69
src/DotTiled/Layers/BaseLayer.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all layer types in a map.
|
||||
/// To check the type of a layer, <see href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching">use C# pattern matching</see>,
|
||||
/// or some other mechanism to determine the type of the layer at runtime.
|
||||
/// </summary>
|
||||
public abstract class BaseLayer : HasPropertiesBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique ID of the layer. Each layer that is added to a map gets a unique ID. Even if a layer is deleted, no layer ever gets the same ID.
|
||||
/// </summary>
|
||||
public required uint ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the layer.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The class of the layer.
|
||||
/// </summary>
|
||||
public string Class { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The opacity of the layer as a value from 0 (fully transparent) to 1 (fully opaque).
|
||||
/// </summary>
|
||||
public float Opacity { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the layer is shown (true) or hidden (false).
|
||||
/// </summary>
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// A tint color that is multiplied with any tiles drawn by this layer.
|
||||
/// </summary>
|
||||
public Color? TintColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal offset for this layer in pixels.
|
||||
/// </summary>
|
||||
public float OffsetX { get; set; } = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical offset for this layer in pixels.
|
||||
/// </summary>
|
||||
public float OffsetY { get; set; } = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal parallax factor for this layer.
|
||||
/// </summary>
|
||||
public float ParallaxX { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical parallax factor for this layer.
|
||||
/// </summary>
|
||||
public float ParallaxY { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Layer properties.
|
||||
/// </summary>
|
||||
public List<IProperty> Properties { get; set; } = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IList<IProperty> GetProperties() => Properties;
|
||||
}
|
144
src/DotTiled/Layers/Data.cs
Normal file
144
src/DotTiled/Layers/Data.cs
Normal file
|
@ -0,0 +1,144 @@
|
|||
using System;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the encoding used to encode the tile layer data.
|
||||
/// </summary>
|
||||
public enum DataEncoding
|
||||
{
|
||||
/// <summary>
|
||||
/// The data is stored as comma-separated values.
|
||||
/// </summary>
|
||||
Csv,
|
||||
|
||||
/// <summary>
|
||||
/// The data is stored as base64-encoded binary data.
|
||||
/// </summary>
|
||||
Base64
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the compression algorithm used to compress the tile layer data.
|
||||
/// </summary>
|
||||
public enum DataCompression
|
||||
{
|
||||
/// <summary>
|
||||
/// GZip compression.
|
||||
/// </summary>
|
||||
GZip,
|
||||
|
||||
/// <summary>
|
||||
/// ZLib compression.
|
||||
/// </summary>
|
||||
ZLib,
|
||||
|
||||
/// <summary>
|
||||
/// ZStandard compression. Currently not supported by DotTiled and will throw an exception if encountered.
|
||||
/// </summary>
|
||||
ZStd
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The flipping flags for a tile. These can be used to check how a tile is flipped or rotated. Uses the
|
||||
/// <see href="https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-flagsattribute">FlagsAttribute, for which there is plenty of documentation.</see>
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FlippingFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// No flipping.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The tile is flipped horizontally.
|
||||
/// </summary>
|
||||
FlippedHorizontally = 0x80000000u,
|
||||
|
||||
/// <summary>
|
||||
/// The tile is flipped vertically.
|
||||
/// </summary>
|
||||
FlippedVertically = 0x40000000u,
|
||||
|
||||
/// <summary>
|
||||
/// The tile is flipped diagonally.
|
||||
/// </summary>
|
||||
FlippedDiagonally = 0x20000000u,
|
||||
|
||||
/// <summary>
|
||||
/// In hexagonal maps, the tile is rotated 120 degrees clockwise.
|
||||
/// </summary>
|
||||
RotatedHexagonal120 = 0x10000000u
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents part of a tile layer of a map that is infinite.
|
||||
/// </summary>
|
||||
public class Chunk
|
||||
{
|
||||
/// <summary>
|
||||
/// The X coordinate of the chunk in tiles.
|
||||
/// </summary>
|
||||
public required int X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Y coordinate of the chunk in tiles.
|
||||
/// </summary>
|
||||
public required int Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The width of the chunk in tiles.
|
||||
/// </summary>
|
||||
public required uint Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the chunk in tiles.
|
||||
/// </summary>
|
||||
public required uint Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parsed chunk data, as a list of tile GIDs.
|
||||
/// To get an actual tile ID, you map it to a local tile ID using the correct tileset. Please refer to
|
||||
/// <see href="https://doc.mapeditor.org/en/stable/reference/global-tile-ids/#mapping-a-gid-to-a-local-tile-id">the documentation on how to do this</see>.
|
||||
/// </summary>
|
||||
public required uint[] GlobalTileIDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parsed flipping flags for each tile in the chunk. Appear in the same order as the tiles in the layer in <see cref="GlobalTileIDs"/>.
|
||||
/// </summary>
|
||||
public required FlippingFlags[] FlippingFlags { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the data of a tile layer.
|
||||
/// </summary>
|
||||
public class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The encoding used to encode the tile layer data.
|
||||
/// </summary>
|
||||
public DataEncoding? Encoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression method used to compress the tile layer data.
|
||||
/// </summary>
|
||||
public DataCompression? Compression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parsed tile layer data, as a list of tile GIDs.
|
||||
/// To get an actual tile ID, you map it to a local tile ID using the correct tileset. Please refer to
|
||||
/// <see href="https://doc.mapeditor.org/en/stable/reference/global-tile-ids/#mapping-a-gid-to-a-local-tile-id">the documentation on how to do this</see>.
|
||||
/// </summary>
|
||||
public uint[]? GlobalTileIDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parsed flipping flags for each tile in the layer. Appear in the same order as the tiles in the layer in <see cref="GlobalTileIDs"/>.
|
||||
/// </summary>
|
||||
public FlippingFlags[]? FlippingFlags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the map is infinite, it will instead contain a list of chunks.
|
||||
/// </summary>
|
||||
public Chunk[]? Chunks { get; set; }
|
||||
}
|
14
src/DotTiled/Layers/Group.cs
Normal file
14
src/DotTiled/Layers/Group.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a group of layers, to form a hierarchy.
|
||||
/// </summary>
|
||||
public class Group : BaseLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// The contained sub-layers in the group.
|
||||
/// </summary>
|
||||
public List<BaseLayer> Layers { get; set; } = [];
|
||||
}
|
32
src/DotTiled/Layers/ImageLayer.cs
Normal file
32
src/DotTiled/Layers/ImageLayer.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an image layer in a map.
|
||||
/// </summary>
|
||||
public class ImageLayer : BaseLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// The X position of the image layer in pixels.
|
||||
/// </summary>
|
||||
public uint X { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The Y position of the image layer in pixels.
|
||||
/// </summary>
|
||||
public uint Y { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the image drawn by this layer is repeated along the X axis.
|
||||
/// </summary>
|
||||
public bool RepeatX { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the image drawn by this layer is repeated along the Y axis.
|
||||
/// </summary>
|
||||
public bool RepeatY { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The image to be drawn by this image layer.
|
||||
/// </summary>
|
||||
public Image? Image { get; set; }
|
||||
}
|
60
src/DotTiled/Layers/ObjectLayer.cs
Normal file
60
src/DotTiled/Layers/ObjectLayer.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the order in which objects can be drawn.
|
||||
/// </summary>
|
||||
public enum DrawOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Objects are drawn sorted by their Y coordinate.
|
||||
/// </summary>
|
||||
TopDown,
|
||||
|
||||
/// <summary>
|
||||
/// Objects are drawn in the order of appearance in the object layer.
|
||||
/// </summary>
|
||||
Index
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an object layer in a map. In Tiled documentation, it is often called an "object group".
|
||||
/// </summary>
|
||||
public class ObjectLayer : BaseLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// The X coordinate of the object layer in tiles.
|
||||
/// </summary>
|
||||
public uint X { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The Y coordinate of the object layer in tiles.
|
||||
/// </summary>
|
||||
public uint Y { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the object layer in tiles. Meaningless.
|
||||
/// </summary>
|
||||
public uint? Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the object layer in tiles. Meaningless.
|
||||
/// </summary>
|
||||
public uint? Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A color that is multiplied with any tile objects drawn by this layer.
|
||||
/// </summary>
|
||||
public Color? Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the objects are drawn according to the order of appearance (<see cref="DrawOrder.Index"/>) or sorted by their Y coordinate (<see cref="DrawOrder.TopDown"/>).
|
||||
/// </summary>
|
||||
public DrawOrder DrawOrder { get; set; } = DrawOrder.TopDown;
|
||||
|
||||
/// <summary>
|
||||
/// The objects in the object layer.
|
||||
/// </summary>
|
||||
public required List<Object> Objects { get; set; }
|
||||
}
|
7
src/DotTiled/Layers/Objects/EllipseObject.cs
Normal file
7
src/DotTiled/Layers/Objects/EllipseObject.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// An ellipse object in a map. The existing <see cref="Object.X"/>, <see cref="Object.Y"/>, <see cref="Object.Width"/>,
|
||||
/// and <see cref="Object.Height"/> properties are used to determine the size of the ellipse.
|
||||
/// </summary>
|
||||
public class EllipseObject : Object { }
|
67
src/DotTiled/Layers/Objects/Object.cs
Normal file
67
src/DotTiled/Layers/Objects/Object.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for objects in object layers.
|
||||
/// </summary>
|
||||
public abstract class Object : HasPropertiesBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique ID of the objects. Each object that is placed on a map gets a unique ID. Even if an object was deleted, no object gets the same ID.
|
||||
/// </summary>
|
||||
public uint? ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the object. An arbitrary string.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The class of the object. An arbitrary string.
|
||||
/// </summary>
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The X coordinate of the object in pixels.
|
||||
/// </summary>
|
||||
public float X { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The Y coordinate of the object in pixels.
|
||||
/// </summary>
|
||||
public float Y { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the object in pixels.
|
||||
/// </summary>
|
||||
public float Width { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the object in pixels.
|
||||
/// </summary>
|
||||
public float Height { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of the object in degrees clockwise around (X, Y).
|
||||
/// </summary>
|
||||
public float Rotation { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the object is shown (true) or hidden (false).
|
||||
/// </summary>
|
||||
public bool Visible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// A reference to a template file.
|
||||
/// </summary>
|
||||
public string? Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Object properties.
|
||||
/// </summary>
|
||||
public List<IProperty> Properties { get; set; } = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IList<IProperty> GetProperties() => Properties;
|
||||
}
|
7
src/DotTiled/Layers/Objects/PointObject.cs
Normal file
7
src/DotTiled/Layers/Objects/PointObject.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// A point object in a map. The existing <see cref="Object.X"/> and <see cref="Object.Y"/> properties are used to
|
||||
/// determine the position of the point.
|
||||
/// </summary>
|
||||
public class PointObject : Object { }
|
17
src/DotTiled/Layers/Objects/PolygonObject.cs
Normal file
17
src/DotTiled/Layers/Objects/PolygonObject.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// A polygon object in a map. The existing <see cref="Object.X"/> and <see cref="Object.Y"/> properties are used as
|
||||
/// the origin of the polygon.
|
||||
/// </summary>
|
||||
public class PolygonObject : Object
|
||||
{
|
||||
/// <summary>
|
||||
/// The points that make up the polygon.
|
||||
/// <see cref="Object.X"/> and <see cref="Object.Y"/> are used as the origin of the polygon.
|
||||
/// </summary>
|
||||
public required List<Vector2> Points { get; set; }
|
||||
}
|
16
src/DotTiled/Layers/Objects/PolylineObject.cs
Normal file
16
src/DotTiled/Layers/Objects/PolylineObject.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// A polyline object in a map. The existing <see cref="Object.X"/> and <see cref="Object.Y"/> properties are used as
|
||||
/// the origin of the polyline.
|
||||
/// </summary>
|
||||
public class PolylineObject : Object
|
||||
{
|
||||
/// <summary>
|
||||
/// The points that make up the polyline. <see cref="Object.X"/> and <see cref="Object.Y"/> are used as the origin of the polyline.
|
||||
/// </summary>
|
||||
public required List<Vector2> Points { get; set; }
|
||||
}
|
7
src/DotTiled/Layers/Objects/RectangleObject.cs
Normal file
7
src/DotTiled/Layers/Objects/RectangleObject.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// A rectangle object in a map. The existing <see cref="Object.X"/>, <see cref="Object.Y"/>, <see cref="Object.Width"/>,
|
||||
/// and <see cref="Object.Height"/> properties are used to determine the size of the rectangle.
|
||||
/// </summary>
|
||||
public class RectangleObject : Object { }
|
116
src/DotTiled/Layers/Objects/TextObject.cs
Normal file
116
src/DotTiled/Layers/Objects/TextObject.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// The horizontal alignment of text.
|
||||
/// </summary>
|
||||
public enum TextHorizontalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// The text is aligned to the left.
|
||||
/// </summary>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// The text is aligned to the center.
|
||||
/// </summary>
|
||||
Center,
|
||||
|
||||
/// <summary>
|
||||
/// The text is aligned to the right.
|
||||
/// </summary>
|
||||
Right,
|
||||
|
||||
/// <summary>
|
||||
/// The text is justified.
|
||||
/// </summary>
|
||||
Justify
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The vertical alignment of text.
|
||||
/// </summary>
|
||||
public enum TextVerticalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// The text is aligned to the top.
|
||||
/// </summary>
|
||||
Top,
|
||||
|
||||
/// <summary>
|
||||
/// The text is aligned to the center.
|
||||
/// </summary>
|
||||
Center,
|
||||
|
||||
/// <summary>
|
||||
/// The text is aligned to the bottom.
|
||||
/// </summary>
|
||||
Bottom
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A text object in a map.
|
||||
/// </summary>
|
||||
public class TextObject : Object
|
||||
{
|
||||
/// <summary>
|
||||
/// The font family used for the text.
|
||||
/// </summary>
|
||||
public string FontFamily { get; set; } = "sans-serif";
|
||||
|
||||
/// <summary>
|
||||
/// The size of the font in pixels.
|
||||
/// </summary>
|
||||
public int PixelSize { get; set; } = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Whether word wrapping is enabled.
|
||||
/// </summary>
|
||||
public bool Wrap { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the text.
|
||||
/// </summary>
|
||||
public Color Color { get; set; } = Color.Parse("#000000", CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the text is bold.
|
||||
/// </summary>
|
||||
public bool Bold { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the text is italic.
|
||||
/// </summary>
|
||||
public bool Italic { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether a line should be drawn below the text.
|
||||
/// </summary>
|
||||
public bool Underline { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether a line should be drawn through the text.
|
||||
/// </summary>
|
||||
public bool Strikeout { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether kerning should be used while rendering the text.
|
||||
/// </summary>
|
||||
public bool Kerning { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The horizontal alignment of the text.
|
||||
/// </summary>
|
||||
public TextHorizontalAlignment HorizontalAlignment { get; set; } = TextHorizontalAlignment.Left;
|
||||
|
||||
/// <summary>
|
||||
/// The vertical alignment of the text.
|
||||
/// </summary>
|
||||
public TextVerticalAlignment VerticalAlignment { get; set; } = TextVerticalAlignment.Top;
|
||||
|
||||
/// <summary>
|
||||
/// The text to be displayed.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = "";
|
||||
}
|
12
src/DotTiled/Layers/Objects/TileObject.cs
Normal file
12
src/DotTiled/Layers/Objects/TileObject.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// A tile object in a map.
|
||||
/// </summary>
|
||||
public class TileObject : Object
|
||||
{
|
||||
/// <summary>
|
||||
/// A reference to a tile.
|
||||
/// </summary>
|
||||
public uint GID { get; set; }
|
||||
}
|
32
src/DotTiled/Layers/TileLayer.cs
Normal file
32
src/DotTiled/Layers/TileLayer.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a tile layer in a map.
|
||||
/// </summary>
|
||||
public class TileLayer : BaseLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// The X coordinate of the layer in tiles.
|
||||
/// </summary>
|
||||
public uint X { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The Y coordinate of the layer in tiles.
|
||||
/// </summary>
|
||||
public uint Y { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the layer in tiles. Always the same as the map width for fixed-size maps.
|
||||
/// </summary>
|
||||
public required uint Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the layer in tiles. Always the same as the map height for fixed-size maps.
|
||||
/// </summary>
|
||||
public required uint Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tile layer data.
|
||||
/// </summary>
|
||||
public Data? Data { get; set; }
|
||||
}
|
208
src/DotTiled/Map.cs
Normal file
208
src/DotTiled/Map.cs
Normal file
|
@ -0,0 +1,208 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Map orientation enumeration. The map orientation determines the alignment of the tiles in the map.
|
||||
/// </summary>
|
||||
public enum MapOrientation
|
||||
{
|
||||
/// <summary>
|
||||
/// Orthogonal orientation. This is the typical top-down grid-based layout.
|
||||
/// </summary>
|
||||
Orthogonal,
|
||||
|
||||
/// <summary>
|
||||
/// Isometric orientation. This is a type of axonometric projection where the tiles are shown as rhombuses, as seen from a side-on view.
|
||||
/// </summary>
|
||||
Isometric,
|
||||
|
||||
/// <summary>
|
||||
/// Staggered orientation. This is an isometric projection with a side-on view where the tiles are arranged in a staggered grid.
|
||||
/// </summary>
|
||||
Staggered,
|
||||
|
||||
/// <summary>
|
||||
/// Hexagonal orientation. This is a type of axial projection where the tiles are shown as hexagons, as seen from a top-down view.
|
||||
/// </summary>
|
||||
Hexagonal
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render order enumeration. The order in which tiles on tile layers are rendered.
|
||||
/// </summary>
|
||||
public enum RenderOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// Right-down render order. Starts at top-left and proceeds right then down.
|
||||
/// </summary>
|
||||
RightDown,
|
||||
|
||||
/// <summary>
|
||||
/// Right-up render order. Starts at bottom-left and proceeds right then up.
|
||||
/// </summary>
|
||||
RightUp,
|
||||
|
||||
/// <summary>
|
||||
/// Left-down render order. Starts at top-right and proceeds left then down.
|
||||
/// </summary>
|
||||
LeftDown,
|
||||
|
||||
/// <summary>
|
||||
/// Left-up render order. Starts at bottom-right and proceeds left then up.
|
||||
/// </summary>
|
||||
LeftUp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stagger axis enumeration. For staggered and hexagonal maps, determines which axis (X or Y) is staggered.
|
||||
/// </summary>
|
||||
public enum StaggerAxis
|
||||
{
|
||||
/// <summary>
|
||||
/// X stagger axis.
|
||||
/// </summary>
|
||||
X,
|
||||
|
||||
/// <summary>
|
||||
/// Y stagger axis.
|
||||
/// </summary>
|
||||
Y
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stagger index enumeration. For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted.
|
||||
/// </summary>
|
||||
public enum StaggerIndex
|
||||
{
|
||||
/// <summary>
|
||||
/// Even stagger index.
|
||||
/// </summary>
|
||||
Odd,
|
||||
|
||||
/// <summary>
|
||||
/// Odd stagger index.
|
||||
/// </summary>
|
||||
Even
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Tiled map.
|
||||
/// </summary>
|
||||
public class Map : HasPropertiesBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The TMX format version. Is incremented to match minor Tiled releases.
|
||||
/// </summary>
|
||||
public required string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Tiled version used to save the file.
|
||||
/// </summary>
|
||||
public required string TiledVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The class of this map.
|
||||
/// </summary>
|
||||
public string Class { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Map orientation.
|
||||
/// </summary>
|
||||
public required MapOrientation Orientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The order in which tiles on tile layers are rendered.
|
||||
/// </summary>
|
||||
public RenderOrder RenderOrder { get; set; } = RenderOrder.RightDown;
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to use for tile layer data (defaults to -1, which means to use the algorithm default).
|
||||
/// Typically only useful for parsing, but may be interesting for certain use cases.
|
||||
/// </summary>
|
||||
public int CompressionLevel { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the map in tiles.
|
||||
/// </summary>
|
||||
public required uint Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the map in tiles.
|
||||
/// </summary>
|
||||
public required uint Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The width of a tile.
|
||||
/// </summary>
|
||||
public required uint TileWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of a tile.
|
||||
/// </summary>
|
||||
public required uint TileHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels.
|
||||
/// </summary>
|
||||
public uint? HexSideLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For staggered and hexagonal maps, determines which axis (X or Y) is staggered.
|
||||
/// </summary>
|
||||
public StaggerAxis? StaggerAxis { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted.
|
||||
/// </summary>
|
||||
public StaggerIndex? StaggerIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X coordinate of the parallax origin in pixels.
|
||||
/// </summary>
|
||||
public float ParallaxOriginX { get; set; } = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Y coordinate of the parallax origin in pixels.
|
||||
/// </summary>
|
||||
public float ParallaxOriginY { get; set; } = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The background color of the map.
|
||||
/// </summary>
|
||||
public Color BackgroundColor { get; set; } = Color.Parse("#00000000", CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>
|
||||
/// Stores the next available ID for new layers. This number is used to prevent reuse of the same ID after layers have been removed.
|
||||
/// </summary>
|
||||
public required uint NextLayerID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the next available ID for new objects. This number is used to prevent reuse of the same ID after objects have been removed.
|
||||
/// </summary>
|
||||
public required uint NextObjectID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this map is infinite. An infinite map has no fixed size and can grow in all directions. Its layer data is stored in chunks.
|
||||
/// </summary>
|
||||
public bool Infinite { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Map properties.
|
||||
/// </summary>
|
||||
public List<IProperty> Properties { get; set; } = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IList<IProperty> GetProperties() => Properties;
|
||||
|
||||
/// <summary>
|
||||
/// List of tilesets used by the map.
|
||||
/// </summary>
|
||||
public List<Tileset> Tilesets { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Hierarchical list of layers. <see cref="Group"/> is a layer type which can contain sub-layers to create a hierarchy.
|
||||
/// </summary>
|
||||
public List<BaseLayer> Layers { get; set; } = [];
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public abstract class BaseLayer
|
||||
{
|
||||
// Attributes
|
||||
public required uint ID { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Class { get; set; } = "";
|
||||
public float Opacity { get; set; } = 1.0f;
|
||||
public bool Visible { get; set; } = true;
|
||||
public Color? TintColor { get; set; }
|
||||
public float OffsetX { get; set; } = 0.0f;
|
||||
public float OffsetY { get; set; } = 0.0f;
|
||||
public float ParallaxX { get; set; } = 1.0f;
|
||||
public float ParallaxY { get; set; } = 1.0f;
|
||||
|
||||
// At most one of
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public enum DataEncoding
|
||||
{
|
||||
Csv,
|
||||
Base64
|
||||
}
|
||||
|
||||
public enum DataCompression
|
||||
{
|
||||
GZip,
|
||||
ZLib,
|
||||
ZStd
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FlippingFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
FlippedHorizontally = 0x80000000u,
|
||||
FlippedVertically = 0x40000000u,
|
||||
FlippedDiagonally = 0x20000000u,
|
||||
RotatedHexagonal120 = 0x10000000u
|
||||
}
|
||||
|
||||
public class Chunk
|
||||
{
|
||||
// Attributes
|
||||
public required int X { get; set; }
|
||||
public required int Y { get; set; }
|
||||
public required uint Width { get; set; }
|
||||
public required uint Height { get; set; }
|
||||
|
||||
// Data
|
||||
public required uint[] GlobalTileIDs { get; set; }
|
||||
public required FlippingFlags[] FlippingFlags { get; set; }
|
||||
}
|
||||
|
||||
public class Data
|
||||
{
|
||||
// Attributes
|
||||
public DataEncoding? Encoding { get; set; }
|
||||
public DataCompression? Compression { get; set; }
|
||||
|
||||
// Data
|
||||
public uint[]? GlobalTileIDs { get; set; }
|
||||
public FlippingFlags[]? FlippingFlags { get; set; }
|
||||
public Chunk[]? Chunks { get; set; }
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public class Group : BaseLayer
|
||||
{
|
||||
// Uses same attributes as BaseLayer
|
||||
|
||||
// Any number of
|
||||
public List<BaseLayer> Layers { get; set; } = [];
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public class ImageLayer : BaseLayer
|
||||
{
|
||||
// Attributes
|
||||
public uint X { get; set; } = 0;
|
||||
public uint Y { get; set; } = 0;
|
||||
public bool RepeatX { get; set; } = false;
|
||||
public bool RepeatY { get; set; } = false;
|
||||
|
||||
// At most one of
|
||||
public Image? Image { get; set; }
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Layers.Objects;
|
||||
|
||||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public enum DrawOrder
|
||||
{
|
||||
TopDown,
|
||||
Index
|
||||
}
|
||||
|
||||
public class ObjectLayer : BaseLayer
|
||||
{
|
||||
// Attributes
|
||||
public uint X { get; set; } = 0;
|
||||
public uint Y { get; set; } = 0;
|
||||
public uint? Width { get; set; }
|
||||
public uint? Height { get; set; }
|
||||
public Color? Color { get; set; }
|
||||
public DrawOrder DrawOrder { get; set; } = DrawOrder.TopDown;
|
||||
|
||||
// Elements
|
||||
public required List<Object> Objects { get; set; }
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class EllipseObject : Object { }
|
|
@ -1,22 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public abstract class Object
|
||||
{
|
||||
// Attributes
|
||||
public uint? ID { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Type { get; set; } = "";
|
||||
public float X { get; set; } = 0f;
|
||||
public float Y { get; set; } = 0f;
|
||||
public float Width { get; set; } = 0f;
|
||||
public float Height { get; set; } = 0f;
|
||||
public float Rotation { get; set; } = 0f;
|
||||
public bool Visible { get; set; } = true;
|
||||
public string? Template { get; set; }
|
||||
|
||||
// Elements
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class PointObject : Object { }
|
|
@ -1,10 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class PolygonObject : Object
|
||||
{
|
||||
// Attributes
|
||||
public required List<Vector2> Points { get; set; }
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class PolylineObject : Object
|
||||
{
|
||||
// Attributes
|
||||
public required List<Vector2> Points { get; set; }
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class RectangleObject : Object { }
|
|
@ -1,38 +0,0 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
|
||||
public enum TextHorizontalAlignment
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
Justify
|
||||
}
|
||||
|
||||
public enum TextVerticalAlignment
|
||||
{
|
||||
Top,
|
||||
Center,
|
||||
Bottom
|
||||
}
|
||||
|
||||
public class TextObject : Object
|
||||
{
|
||||
// Attributes
|
||||
public string FontFamily { get; set; } = "sans-serif";
|
||||
public int PixelSize { get; set; } = 16;
|
||||
public bool Wrap { get; set; } = false;
|
||||
public Color Color { get; set; } = Color.Parse("#000000", CultureInfo.InvariantCulture);
|
||||
public bool Bold { get; set; } = false;
|
||||
public bool Italic { get; set; } = false;
|
||||
public bool Underline { get; set; } = false;
|
||||
public bool Strikeout { get; set; } = false;
|
||||
public bool Kerning { get; set; } = true;
|
||||
public TextHorizontalAlignment HorizontalAlignment { get; set; } = TextHorizontalAlignment.Left;
|
||||
public TextVerticalAlignment VerticalAlignment { get; set; } = TextVerticalAlignment.Top;
|
||||
|
||||
// Elements
|
||||
public string Text { get; set; } = "";
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
namespace DotTiled.Model.Layers.Objects;
|
||||
|
||||
public class TileObject : Object
|
||||
{
|
||||
public uint GID { get; set; }
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
namespace DotTiled.Model.Layers;
|
||||
|
||||
public class TileLayer : BaseLayer
|
||||
{
|
||||
// Attributes
|
||||
public uint X { get; set; } = 0;
|
||||
public uint Y { get; set; } = 0;
|
||||
public required uint Width { get; set; }
|
||||
public required uint Height { get; set; }
|
||||
|
||||
// At most one of
|
||||
public Data? Data { get; set; }
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Properties;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Model;
|
||||
|
||||
public enum MapOrientation
|
||||
{
|
||||
Orthogonal,
|
||||
Isometric,
|
||||
Staggered,
|
||||
Hexagonal
|
||||
}
|
||||
|
||||
public enum RenderOrder
|
||||
{
|
||||
RightDown,
|
||||
RightUp,
|
||||
LeftDown,
|
||||
LeftUp
|
||||
}
|
||||
|
||||
public enum StaggerAxis
|
||||
{
|
||||
X,
|
||||
Y
|
||||
}
|
||||
|
||||
public enum StaggerIndex
|
||||
{
|
||||
Odd,
|
||||
Even
|
||||
}
|
||||
|
||||
public class Map
|
||||
{
|
||||
// Attributes
|
||||
public required string Version { get; set; }
|
||||
public required string TiledVersion { get; set; }
|
||||
public string Class { get; set; } = "";
|
||||
public required MapOrientation Orientation { get; set; }
|
||||
public RenderOrder RenderOrder { get; set; } = RenderOrder.RightDown;
|
||||
public int CompressionLevel { get; set; } = -1;
|
||||
public required uint Width { get; set; }
|
||||
public required uint Height { get; set; }
|
||||
public required uint TileWidth { get; set; }
|
||||
public required uint TileHeight { get; set; }
|
||||
public uint? HexSideLength { get; set; }
|
||||
public StaggerAxis? StaggerAxis { get; set; }
|
||||
public StaggerIndex? StaggerIndex { get; set; }
|
||||
public float ParallaxOriginX { get; set; } = 0.0f;
|
||||
public float ParallaxOriginY { get; set; } = 0.0f;
|
||||
public Color BackgroundColor { get; set; } = Color.Parse("#00000000", CultureInfo.InvariantCulture);
|
||||
public required uint NextLayerID { get; set; }
|
||||
public required uint NextObjectID { get; set; }
|
||||
public bool Infinite { get; set; } = false;
|
||||
|
||||
// At most one of
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
|
||||
// Any number of
|
||||
public List<Tileset> Tilesets { get; set; } = [];
|
||||
public List<BaseLayer> Layers { get; set; } = [];
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class BoolProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.Bool;
|
||||
public required bool Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new BoolProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class ClassProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => Model.Properties.PropertyType.Class;
|
||||
public required string PropertyType { get; set; }
|
||||
public required Dictionary<string, IProperty> Properties { get; set; }
|
||||
|
||||
public IProperty Clone() => new ClassProperty
|
||||
{
|
||||
Name = Name,
|
||||
PropertyType = PropertyType,
|
||||
Properties = Properties.ToDictionary(p => p.Key, p => p.Value.Clone())
|
||||
};
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class ColorProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.Color;
|
||||
public required Color Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new ColorProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled.Model.Properties.CustomTypes;
|
||||
|
||||
[Flags]
|
||||
public enum CustomClassUseAs
|
||||
{
|
||||
Property,
|
||||
Map,
|
||||
Layer,
|
||||
Object,
|
||||
Tile,
|
||||
Tileset,
|
||||
WangColor,
|
||||
Wangset,
|
||||
Project,
|
||||
All = Property | Map | Layer | Object | Tile | Tileset | WangColor | Wangset | Project
|
||||
}
|
||||
|
||||
public class CustomClassDefinition : CustomTypeDefinition
|
||||
{
|
||||
public Color? Color { get; set; }
|
||||
public bool DrawFill { get; set; }
|
||||
public CustomClassUseAs UseAs { get; set; }
|
||||
public List<IProperty> Members { get; set; } = [];
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace DotTiled.Model.Properties.CustomTypes;
|
||||
|
||||
public enum CustomEnumStorageType
|
||||
{
|
||||
Int,
|
||||
String
|
||||
}
|
||||
|
||||
public class CustomEnumDefinition : CustomTypeDefinition
|
||||
{
|
||||
public CustomEnumStorageType StorageType { get; set; }
|
||||
public List<string> Values { get; set; } = [];
|
||||
public bool ValueAsFlags { get; set; }
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace DotTiled.Model.Properties.CustomTypes;
|
||||
|
||||
public abstract class CustomTypeDefinition
|
||||
{
|
||||
public uint ID { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class FileProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.File;
|
||||
public required string Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new FileProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class FloatProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.Float;
|
||||
public required float Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new FloatProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public interface IProperty
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public PropertyType Type { get; }
|
||||
|
||||
IProperty Clone();
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class IntProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.Int;
|
||||
public required int Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new IntProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class ObjectProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.Object;
|
||||
public required uint Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new ObjectProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public enum PropertyType
|
||||
{
|
||||
String,
|
||||
Int,
|
||||
Float,
|
||||
Bool,
|
||||
Color,
|
||||
File,
|
||||
Object,
|
||||
Class
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
namespace DotTiled.Model.Properties;
|
||||
|
||||
public class StringProperty : IProperty
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public PropertyType Type => PropertyType.String;
|
||||
public required string Value { get; set; }
|
||||
|
||||
public IProperty Clone() => new StringProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
using DotTiled.Model.Layers.Objects;
|
||||
using DotTiled.Model.Tilesets;
|
||||
|
||||
namespace DotTiled.Model;
|
||||
|
||||
public class Template
|
||||
{
|
||||
// At most one of (if the template is a tile object)
|
||||
public Tileset? Tileset { get; set; }
|
||||
public required Object Object { get; set; }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class Frame
|
||||
{
|
||||
// Attributes
|
||||
public required uint TileID { get; set; }
|
||||
public required uint Duration { get; set; }
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public enum GridOrientation
|
||||
{
|
||||
Orthogonal,
|
||||
Isometric
|
||||
}
|
||||
|
||||
public class Grid
|
||||
{
|
||||
// Attributes
|
||||
public GridOrientation Orientation { get; set; } = GridOrientation.Orthogonal;
|
||||
public required uint Width { get; set; }
|
||||
public required uint Height { get; set; }
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public enum ImageFormat
|
||||
{
|
||||
Png,
|
||||
Gif,
|
||||
Jpg,
|
||||
Bmp
|
||||
}
|
||||
|
||||
public class Image
|
||||
{
|
||||
// Attributes
|
||||
public ImageFormat? Format { get; set; }
|
||||
public string? Source { get; set; }
|
||||
public Color? TransparentColor { get; set; }
|
||||
public uint? Width { get; set; }
|
||||
public uint? Height { get; set; }
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Layers;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class Tile
|
||||
{
|
||||
// Attributes
|
||||
public required uint ID { get; set; }
|
||||
public string Type { get; set; } = "";
|
||||
public float Probability { get; set; } = 0f;
|
||||
public uint X { get; set; } = 0;
|
||||
public uint Y { get; set; } = 0;
|
||||
public required uint Width { get; set; }
|
||||
public required uint Height { get; set; }
|
||||
|
||||
// Elements
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
public Image? Image { get; set; }
|
||||
public ObjectLayer? ObjectLayer { get; set; }
|
||||
public List<Frame>? Animation { get; set; }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class TileOffset
|
||||
{
|
||||
// Attributes
|
||||
public float X { get; set; } = 0f;
|
||||
public float Y { get; set; } = 0f;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public enum ObjectAlignment
|
||||
{
|
||||
Unspecified,
|
||||
TopLeft,
|
||||
Top,
|
||||
TopRight,
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
BottomLeft,
|
||||
Bottom,
|
||||
BottomRight
|
||||
}
|
||||
|
||||
public enum TileRenderSize
|
||||
{
|
||||
Tile,
|
||||
Grid
|
||||
}
|
||||
|
||||
public enum FillMode
|
||||
{
|
||||
Stretch,
|
||||
PreserveAspectFit
|
||||
}
|
||||
|
||||
public class Tileset
|
||||
{
|
||||
// Attributes
|
||||
public string? Version { get; set; }
|
||||
public string? TiledVersion { get; set; }
|
||||
public uint? FirstGID { get; set; }
|
||||
public string? Source { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string Class { get; set; } = "";
|
||||
public uint? TileWidth { get; set; }
|
||||
public uint? TileHeight { get; set; }
|
||||
public float? Spacing { get; set; } = 0f;
|
||||
public float? Margin { get; set; } = 0f;
|
||||
public uint? TileCount { get; set; }
|
||||
public uint? Columns { get; set; }
|
||||
public ObjectAlignment ObjectAlignment { get; set; } = ObjectAlignment.Unspecified;
|
||||
public TileRenderSize RenderSize { get; set; } = TileRenderSize.Tile;
|
||||
public FillMode FillMode { get; set; } = FillMode.Stretch;
|
||||
|
||||
// At most one of
|
||||
public Image? Image { get; set; }
|
||||
public TileOffset? TileOffset { get; set; }
|
||||
public Grid? Grid { get; set; }
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
// public List<Terrain>? TerrainTypes { get; set; } TODO: Implement Terrain -> Wangset conversion during deserialization
|
||||
public List<Wangset>? Wangsets { get; set; }
|
||||
public Transformations? Transformations { get; set; }
|
||||
|
||||
// Any number of
|
||||
public List<Tile> Tiles { get; set; } = [];
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class Transformations
|
||||
{
|
||||
// Attributes
|
||||
public bool HFlip { get; set; } = false;
|
||||
public bool VFlip { get; set; } = false;
|
||||
public bool Rotate { get; set; } = false;
|
||||
public bool PreferUntransformed { get; set; } = false;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class WangColor
|
||||
{
|
||||
// Attributes
|
||||
public required string Name { get; set; }
|
||||
public string Class { get; set; } = "";
|
||||
public required Color Color { get; set; }
|
||||
public required int Tile { get; set; }
|
||||
public float Probability { get; set; } = 0f;
|
||||
|
||||
// Elements
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class WangTile
|
||||
{
|
||||
// Attributes
|
||||
public required uint TileID { get; set; }
|
||||
public required byte[] WangID { get; set; }
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using DotTiled.Model.Properties;
|
||||
|
||||
namespace DotTiled.Model.Tilesets;
|
||||
|
||||
public class Wangset
|
||||
{
|
||||
// Attributes
|
||||
public required string Name { get; set; }
|
||||
public string Class { get; set; } = "";
|
||||
public required int Tile { get; set; }
|
||||
|
||||
// Elements
|
||||
// At most one of
|
||||
public Dictionary<string, IProperty>? Properties { get; set; }
|
||||
|
||||
// Up to 254 Wang colors
|
||||
public List<WangColor>? WangColors { get; set; } = [];
|
||||
|
||||
// Any number of
|
||||
public List<WangTile> WangTiles { get; set; } = [];
|
||||
}
|
25
src/DotTiled/Properties/BoolProperty.cs
Normal file
25
src/DotTiled/Properties/BoolProperty.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a boolean property.
|
||||
/// </summary>
|
||||
public class BoolProperty : IProperty<bool>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public required string Name { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyType Type => PropertyType.Bool;
|
||||
|
||||
/// <summary>
|
||||
/// The boolean value of the property.
|
||||
/// </summary>
|
||||
public required bool Value { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IProperty Clone() => new BoolProperty
|
||||
{
|
||||
Name = Name,
|
||||
Value = Value
|
||||
};
|
||||
}
|
65
src/DotTiled/Properties/ClassProperty.cs
Normal file
65
src/DotTiled/Properties/ClassProperty.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a class property.
|
||||
/// </summary>
|
||||
public class ClassProperty : IHasProperties, IProperty<IList<IProperty>>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public required string Name { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public PropertyType Type => DotTiled.PropertyType.Class;
|
||||
|
||||
/// <summary>
|
||||
/// The type of the class property. This will be the name of a custom defined
|
||||
/// type in Tiled.
|
||||
/// </summary>
|
||||
public required string PropertyType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The properties of the class property.
|
||||
/// </summary>
|
||||
public required IList<IProperty> Value { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IProperty Clone() => new ClassProperty
|
||||
{
|
||||
Name = Name,
|
||||
PropertyType = PropertyType,
|
||||
Value = Value.Select(property => property.Clone()).ToList()
|
||||
};
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IList<IProperty> GetProperties() => Value;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T GetProperty<T>(string name) where T : IProperty
|
||||
{
|
||||
var property = Value.FirstOrDefault(_properties => _properties.Name == name) ?? throw new InvalidOperationException($"Property '{name}' not found.");
|
||||
if (property is T prop)
|
||||
{
|
||||
return prop;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Property '{name}' is not of type '{typeof(T).Name}'.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetProperty<T>(string name, [NotNullWhen(true)] out T? property) where T : IProperty
|
||||
{
|
||||
if (Value.FirstOrDefault(_properties => _properties.Name == name) is T prop)
|
||||
{
|
||||
property = prop;
|
||||
return true;
|
||||
}
|
||||
|
||||
property = default;
|
||||
return false;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue