From a3a2afd7b92e67b090cd8da3735e3855e896abc0 Mon Sep 17 00:00:00 2001 From: Albin Johansson Date: Fri, 27 Oct 2023 18:12:11 +0200 Subject: [PATCH] Tweak CI scripts --- .github/workflows/macos.yml | 10 ++- .github/workflows/ubuntu.yml | 12 ++- .github/workflows/windows.yml | 12 ++- .../tmj-format/emit/tmj_tile_emitter.hpp | 34 ++++++++ .../tmj-format/emit/tmj_tile_emitter.cpp | 82 +++++++++++++++++++ .../test/emit/tmj_tile_emitter_test.cpp | 75 +++++++++++++++++ 6 files changed, 214 insertions(+), 11 deletions(-) create mode 100644 modules/tmj-format/inc/tactile/tmj-format/emit/tmj_tile_emitter.hpp create mode 100644 modules/tmj-format/src/tactile/tmj-format/emit/tmj_tile_emitter.cpp create mode 100644 modules/tmj-format/test/emit/tmj_tile_emitter_test.cpp diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 42fc63f95e..7b2c36bb10 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -45,7 +45,7 @@ jobs: run: mkdir -p ${{env.VCPKG_DEFAULT_BINARY_CACHE}} - name: Register custom Vcpkg triplet file - run: cp "cmake/x64-osx-tactile.cmake" "$VCPKG_ROOT/triplets/x64-osx-tactile.cmake" + run: cp "cmake/x64-osx-tactile.cmake" "$VCPKG_ROOT/triplets/community/x64-osx-tactile.cmake" - name: Generate build files run: | @@ -62,6 +62,10 @@ jobs: - name: Build run: ninja -C build - - name: Run core tests - working-directory: ./build/debug + - name: Run core unit tests + working-directory: ./build/debug/test run: ./tactile-core-test + + - name: Run TMJ format unit tests + working-directory: ./build/debug/test + run: ./tactile-tmj-format-test diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index d8e7f62bef..7413eb1af3 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -55,7 +55,7 @@ jobs: run: mkdir -p ${{env.VCPKG_DEFAULT_BINARY_CACHE}} - name: Register custom Vcpkg triplet file - run: cp "cmake/x64-linux-tactile.cmake" "$VCPKG_ROOT/triplets/x64-linux-tactile.cmake" + run: cp "cmake/x64-linux-tactile.cmake" "$VCPKG_ROOT/triplets/community/x64-linux-tactile.cmake" - name: Emulate video device run: | @@ -81,6 +81,10 @@ jobs: - name: Build run: ninja -C build - - name: Run core tests - working-directory: ./build/debug - run: ./tactile-core-test \ No newline at end of file + - name: Run core unit tests + working-directory: ./build/debug/test + run: ./tactile-core-test + + - name: Run TMJ format unit tests + working-directory: ./build/debug/test + run: ./tactile-tmj-format-test \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 15fe3b1dfe..787029ffde 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -42,7 +42,7 @@ jobs: - name: Register custom Vcpkg triplet file run: Copy-Item -Path "cmake\x64-windows-tactile.cmake" ` - -Destination "$ENV:VCPKG_ROOT\triplets\x64-windows-tactile.cmake" + -Destination "$ENV:VCPKG_ROOT\triplets\community\x64-windows-tactile.cmake" - name: Generate build files env: @@ -60,6 +60,10 @@ jobs: - name: Build run: ninja -C build - - name: Run core tests - working-directory: ./build/debug - run: tactile-core-test.exe \ No newline at end of file + - name: Run core unit tests + working-directory: ./build/debug/test + run: .\tactile-core-test.exe + + - name: Run TMJ format unit tests + working-directory: ./build/debug/test + run: .\tactile-tmj-format-test.exe \ No newline at end of file diff --git a/modules/tmj-format/inc/tactile/tmj-format/emit/tmj_tile_emitter.hpp b/modules/tmj-format/inc/tactile/tmj-format/emit/tmj_tile_emitter.hpp new file mode 100644 index 0000000000..7de3f47b07 --- /dev/null +++ b/modules/tmj-format/inc/tactile/tmj-format/emit/tmj_tile_emitter.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0) + +#pragma once + +#include "tactile/core/io/ir.hpp" +#include "tactile/core/prelude.hpp" +#include "tactile/tmj-format/api.hpp" +#include "tactile/tmj-format/common/json.hpp" + +namespace tactile::tmj { + +/** + * \brief Converts a tile definition to a TMJ JSON object. + * + * \param tile the tile definition. + * \param tile_index the index of the tile in the associated tileset. + * + * \return a JSON object. + */ +[[nodiscard]] +TACTILE_TMJ_API auto emit_tile_definition(const ir::Tile& tile, TileIndex tile_index) + -> JSON; + +/** + * \brief Converts a collection of tile definitions to a TMJ JSON array. + * + * \param tiles the tile definitions. + * + * \return a JSON array. + */ +[[nodiscard]] +TACTILE_TMJ_API auto emit_tile_definition_array(const Vector& tiles) -> JSON; + +} // namespace tactile::tmj diff --git a/modules/tmj-format/src/tactile/tmj-format/emit/tmj_tile_emitter.cpp b/modules/tmj-format/src/tactile/tmj-format/emit/tmj_tile_emitter.cpp new file mode 100644 index 0000000000..33983494f7 --- /dev/null +++ b/modules/tmj-format/src/tactile/tmj-format/emit/tmj_tile_emitter.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0) + +#include "tactile/tmj-format/emit/tmj_tile_emitter.hpp" + +#include // move + +#include "tactile/tmj-format/emit/tmj_meta_emitter.hpp" +#include "tactile/tmj-format/emit/tmj_object_emitter.hpp" + +namespace tactile::tmj { +namespace { + +[[nodiscard]] +auto _emit_tile_nested_object_layer(const ir::Tile& tile) -> JSON +{ + auto object_layer_json = JSON::object(); + + object_layer_json["type"] = "objectgroup"; + object_layer_json["draworder"] = "index"; + object_layer_json["name"] = ""; + object_layer_json["opacity"] = 1; + object_layer_json["visible"] = true; + object_layer_json["x"] = 0; + object_layer_json["y"] = 0; + object_layer_json["objects"] = emit_object_array(tile.objects); + + return object_layer_json; +} + +[[nodiscard]] +auto _emit_tile_animation_array(const ir::Tile& tile) -> JSON +{ + auto animation_json_array = JSON::array(); + + for (const auto& animation_frame : tile.animation) { + auto animation_frame_json = JSON::object(); + + animation_frame_json["tileid"] = animation_frame.tile_index; + animation_frame_json["duration"] = animation_frame.duration_ms; + + animation_json_array += std::move(animation_frame_json); + } + + return animation_json_array; +} + +} // namespace + +auto emit_tile_definition(const ir::Tile& tile, const TileIndex tile_index) -> JSON +{ + auto tile_json = JSON::object(); + tile_json["id"] = tile_index; + + if (!tile.meta.properties.empty()) { + tile_json["properties"] = emit_property_array(tile.meta); + } + + if (!tile.animation.empty()) { + tile_json["animation"] = _emit_tile_animation_array(tile); + } + + if (!tile.objects.empty()) { + tile_json["objectgroup"] = _emit_tile_nested_object_layer(tile); + } + + return tile_json; +} + +auto emit_tile_definition_array(const Vector& tiles) -> JSON +{ + auto tile_json_array = JSON::array(); + + TileIndex tile_index = 0; + for (const auto& tile : tiles) { + tile_json_array += emit_tile_definition(tile, tile_index); + ++tile_index; + } + + return tile_json_array; +} + +} // namespace tactile::tmj diff --git a/modules/tmj-format/test/emit/tmj_tile_emitter_test.cpp b/modules/tmj-format/test/emit/tmj_tile_emitter_test.cpp new file mode 100644 index 0000000000..05d07e414f --- /dev/null +++ b/modules/tmj-format/test/emit/tmj_tile_emitter_test.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0) + +#include "tactile/tmj-format/emit/tmj_tile_emitter.hpp" + +#include + +using namespace tactile; + +TEST(TmjTileEmitter, EmitEmptyTileDefinition) +{ + const TileIndex tile_index = 182; + const ir::Tile tile {}; + + const auto tile_json = tmj::emit_tile_definition(tile, tile_index); + + EXPECT_EQ(tile_json["id"], tile_index); + EXPECT_FALSE(tile_json.contains("properties")); + EXPECT_FALSE(tile_json.contains("animation")); + EXPECT_FALSE(tile_json.contains("objectgroup")); +} + +TEST(TmjTileEmitter, EmitComplexTileDefinition) +{ + const TileIndex tile_index = 42; + + const ir::Tile tile { + .meta = + { + .name = "T42", + .properties = + { + ir::NamedAttribute {.name = "P1", .value = 100}, + }, + .components = {}, + }, + .objects = + { + ir::Object {}, + ir::Object {}, + ir::Object {}, + }, + .animation = + { + ir::AnimationFrame {.tile_index = 42, .duration_ms = 500}, + ir::AnimationFrame {.tile_index = 50, .duration_ms = 600}, + ir::AnimationFrame {.tile_index = 93, .duration_ms = 300}, + ir::AnimationFrame {.tile_index = 6, .duration_ms = 123}, + }, + }; + + const auto tile_json = tmj::emit_tile_definition(tile, tile_index); + + EXPECT_EQ(tile_json["id"], tile_index); + ASSERT_TRUE(tile_json.contains("properties")); + ASSERT_TRUE(tile_json.contains("animation")); + ASSERT_TRUE(tile_json.contains("objectgroup")); + + const auto& properties_json = tile_json.at("properties"); + EXPECT_EQ(properties_json.size(), tile.meta.properties.size()); + EXPECT_EQ(properties_json.at(0).at("name"), "P1"); + EXPECT_EQ(properties_json.at(0).at("value"), 100); + + const auto& animation_json = tile_json.at("animation"); + EXPECT_EQ(animation_json.size(), tile.animation.size()); + EXPECT_EQ(animation_json.at(0).at("tileid"), tile.animation.at(0).tile_index); + EXPECT_EQ(animation_json.at(0).at("duration"), tile.animation.at(0).duration_ms); + EXPECT_EQ(animation_json.at(1).at("tileid"), tile.animation.at(1).tile_index); + EXPECT_EQ(animation_json.at(1).at("duration"), tile.animation.at(1).duration_ms); + EXPECT_EQ(animation_json.at(2).at("tileid"), tile.animation.at(2).tile_index); + EXPECT_EQ(animation_json.at(2).at("duration"), tile.animation.at(2).duration_ms); + EXPECT_EQ(animation_json.at(3).at("tileid"), tile.animation.at(3).tile_index); + EXPECT_EQ(animation_json.at(3).at("duration"), tile.animation.at(3).duration_ms); + + EXPECT_EQ(tile_json.at("objectgroup").at("objects").size(), tile.objects.size()); +}