diff --git a/.clang_complete b/.clang_complete index fad17bfe..2bd003f9 100644 --- a/.clang_complete +++ b/.clang_complete @@ -14,7 +14,6 @@ -Imodules/glew/include -Imodules/glfw/include --Imodules/spine/spine-c/spine-c/include -std=c++17 -stdlib=libc++ diff --git a/.gitmodules b/.gitmodules index 2053c371..a36ae902 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,9 +34,6 @@ [submodule "modules/flat.hpp"] path = modules/flat.hpp url = https://github.com/BlackMATov/flat.hpp -[submodule "modules/spine"] - path = modules/spine - url = https://github.com/EsotericSoftware/spine-runtimes.git [submodule "modules/enum.hpp"] path = modules/enum.hpp url = https://github.com/BlackMATov/enum.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1162ddc9..3b1c0959 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,9 +136,6 @@ set(glew-cmake_BUILD_MULTI_CONTEXT OFF CACHE INTERNAL "" FORCE) add_subdirectory(modules/glew) set_target_properties(libglew_static PROPERTIES FOLDER modules) -add_subdirectory(modules/spine/spine-c) -set_target_properties(spine-c PROPERTIES FOLDER modules) - # # e2d library target # @@ -163,7 +160,6 @@ target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE glfw PRIVATE libglew_static - PRIVATE spine-c PRIVATE $<$:winmm.lib>) target_include_directories(${PROJECT_NAME} diff --git a/headers/enduro2d/high/_all.hpp b/headers/enduro2d/high/_all.hpp index 1d5b0a6b..35af7524 100644 --- a/headers/enduro2d/high/_all.hpp +++ b/headers/enduro2d/high/_all.hpp @@ -21,7 +21,6 @@ #include "assets/shader_asset.hpp" #include "assets/shape_asset.hpp" #include "assets/sound_asset.hpp" -#include "assets/spine_asset.hpp" #include "assets/sprite_asset.hpp" #include "assets/text_asset.hpp" #include "assets/texture_asset.hpp" @@ -40,7 +39,6 @@ #include "components/named.hpp" #include "components/renderer.hpp" #include "components/scene.hpp" -#include "components/spine_player.hpp" #include "components/sprite_renderer.hpp" #include "components/touchable.hpp" #include "components/widget.hpp" @@ -49,7 +47,6 @@ #include "resources/flipbook.hpp" #include "resources/model.hpp" #include "resources/prefab.hpp" -#include "resources/spine.hpp" #include "resources/sprite.hpp" #include "systems/camera_system.hpp" @@ -59,7 +56,6 @@ #include "systems/label_system.hpp" #include "systems/layout_system.hpp" #include "systems/render_system.hpp" -#include "systems/spine_system.hpp" #include "systems/touch_system.hpp" #include "systems/world_system.hpp" diff --git a/headers/enduro2d/high/_high.hpp b/headers/enduro2d/high/_high.hpp index a67d1f51..62e10dd2 100644 --- a/headers/enduro2d/high/_high.hpp +++ b/headers/enduro2d/high/_high.hpp @@ -33,7 +33,6 @@ namespace e2d class shader_asset; class shape_asset; class sound_asset; - class spine_asset; class sprite_asset; class text_asset; class texture_asset; @@ -57,7 +56,6 @@ namespace e2d class named; class renderer; class scene; - class spine_player; class sprite_renderer; class touchable; class widget; @@ -66,7 +64,6 @@ namespace e2d class flipbook; class model; class prefab; - class spine; class sprite; class camera_system; @@ -76,7 +73,6 @@ namespace e2d class label_system; class layout_system; class render_system; - class spine_system; class touch_system; class world_system; diff --git a/headers/enduro2d/high/assets/spine_asset.hpp b/headers/enduro2d/high/assets/spine_asset.hpp deleted file mode 100644 index d94731d6..00000000 --- a/headers/enduro2d/high/assets/spine_asset.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "../_high.hpp" - -#include "../library.hpp" -#include "../resources/spine.hpp" - -namespace e2d -{ - class spine_asset final : public content_asset { - public: - static const char* type_name() noexcept { return "spine_asset"; } - static load_async_result load_async(const library& library, str_view address); - }; -} diff --git a/headers/enduro2d/high/components/spine_player.hpp b/headers/enduro2d/high/components/spine_player.hpp deleted file mode 100644 index c86a7b20..00000000 --- a/headers/enduro2d/high/components/spine_player.hpp +++ /dev/null @@ -1,376 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "_components.hpp" - -#include "../assets/spine_asset.hpp" -#include "../assets/material_asset.hpp" - -struct spSkeleton; -struct spSkeletonClipping; -struct spAnimationState; - -namespace e2d::spine_player_events -{ - class custom_evt; - class end_evt; - class complete_evt; - - using event = std::variant< - custom_evt, - end_evt, - complete_evt>; -} - -namespace e2d::spine_player_commands -{ - class clear_track_cmd; - class set_anim_cmd; - class add_anim_cmd; - class set_empty_anim_cmd; - class add_empty_anim_cmd; - - using command = std::variant< - clear_track_cmd, - set_anim_cmd, - add_anim_cmd, - set_empty_anim_cmd, - add_empty_anim_cmd>; -} - -namespace e2d -{ - class bad_spine_player_access final : public exception { - public: - const char* what() const noexcept final { - return "bad spine player access"; - } - }; - - class spine_player final { - public: - using clipping_ptr = std::shared_ptr; - using skeleton_ptr = std::shared_ptr; - using animation_ptr = std::shared_ptr; - public: - spine_player() = default; - spine_player(const spine_asset::ptr& spine); - - spine_player& spine( - const spine_asset::ptr& value); - - bool skin(str_view name); - bool attachment(str_view slot, str_view name); - - bool has_skin(str_view name) const noexcept; - bool has_animation(str_view name) const noexcept; - - const spine_asset::ptr& spine() const noexcept; - const clipping_ptr& clipper() const noexcept; - const skeleton_ptr& skeleton() const noexcept; - const animation_ptr& animation() const noexcept; - - spine_player& materials(flat_map value) noexcept; - const flat_map& materials() const noexcept; - material_asset::ptr find_material(str_hash name) const noexcept; - private: - spine_asset::ptr spine_; - clipping_ptr clipping_; - skeleton_ptr skeleton_; - animation_ptr animation_; - flat_map materials_; - }; -} - -namespace e2d -{ - template <> - class factory_loader final : factory_loader<> { - public: - static const char* schema_source; - - bool operator()( - spine_player& component, - const fill_context& ctx) const; - - bool operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const; - }; - - template <> - class factory_loader> final : factory_loader<> { - public: - static const char* schema_source; - - bool operator()( - events& component, - const fill_context& ctx) const; - - bool operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const; - }; - - template <> - class factory_loader> final : factory_loader<> { - public: - static const char* schema_source; - - bool operator()( - commands& component, - const fill_context& ctx) const; - - bool operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const; - }; -} - -namespace e2d -{ - template <> - class component_inspector final : component_inspector<> { - public: - static const char* title; - - void operator()(gcomponent& c) const; - }; -} - -namespace e2d::spine_player_events -{ - class custom_evt final { - public: - custom_evt() = default; - - custom_evt(str name) - : name_(std::move(name)) {} - - custom_evt& name(str value) noexcept { - name_ = std::move(value); - return *this; - } - - custom_evt& int_value(i32 value) noexcept { - int_value_ = value; - return *this; - } - - custom_evt& float_value(f32 value) noexcept { - float_value_ = value; - return *this; - } - - custom_evt& string_value(str value) noexcept { - string_value_ = std::move(value); - return *this; - } - - [[nodiscard]] const str& name() const noexcept { return name_; } - [[nodiscard]] i32 int_value() const noexcept { return int_value_; } - [[nodiscard]] f32 float_value() const noexcept { return float_value_; } - [[nodiscard]] const str& string_value() const noexcept { return string_value_; } - private: - str name_; - i32 int_value_{0}; - f32 float_value_{0.f}; - str string_value_; - }; - - class end_evt final { - public: - end_evt() = default; - - end_evt(str message) - : message_(std::move(message)) {} - - end_evt& message(str value) noexcept { - message_ = std::move(value); - return *this; - } - - [[nodiscard]] const str& message() const noexcept { return message_; } - private: - str message_; - }; - - class complete_evt final { - public: - complete_evt() = default; - - complete_evt(str message) - : message_(std::move(message)) {} - - complete_evt& message(str value) noexcept { - message_ = std::move(value); - return *this; - } - - [[nodiscard]] const str& message() const noexcept { return message_; } - private: - str message_; - }; -} - -namespace e2d::spine_player_commands -{ - class clear_track_cmd final { - public: - clear_track_cmd(u32 track) - : track_(track) {} - - [[nodiscard]] u32 track() const noexcept { return track_; } - private: - u32 track_{0u}; - }; - - class set_anim_cmd final { - public: - set_anim_cmd(u32 track, str name) - : track_(track) - , name_(std::move(name)) {} - - set_anim_cmd& loop(bool value) noexcept { - loop_ = value; - return *this; - } - - set_anim_cmd& end_message(str value) noexcept { - end_message_ = std::move(value); - return *this; - } - - set_anim_cmd& complete_message(str value) noexcept { - complete_message_ = std::move(value); - return *this; - } - - [[nodiscard]] u32 track() const noexcept { return track_; } - [[nodiscard]] const str& name() const noexcept { return name_; } - [[nodiscard]] bool loop() const noexcept { return loop_; } - [[nodiscard]] const str& end_message() const noexcept { return complete_message_; } - [[nodiscard]] const str& complete_message() const noexcept { return complete_message_; } - private: - u32 track_{0u}; - str name_; - bool loop_{false}; - str end_message_; - str complete_message_; - }; - - class add_anim_cmd final { - public: - add_anim_cmd(u32 track, str name) - : track_(track) - , name_(std::move(name)) {} - - add_anim_cmd& loop(bool value) noexcept { - loop_ = value; - return *this; - } - - add_anim_cmd& delay(f32 value) noexcept { - delay_ = value; - return *this; - } - - add_anim_cmd& end_message(str value) noexcept { - end_message_ = std::move(value); - return *this; - } - - add_anim_cmd& complete_message(str value) noexcept { - complete_message_ = std::move(value); - return *this; - } - - [[nodiscard]] u32 track() const noexcept { return track_; } - [[nodiscard]] const str& name() const noexcept { return name_; } - [[nodiscard]] bool loop() const noexcept { return loop_; } - [[nodiscard]] f32 delay() const noexcept { return delay_; } - [[nodiscard]] const str& end_message() const noexcept { return end_message_; } - [[nodiscard]] const str& complete_message() const noexcept { return complete_message_; } - private: - u32 track_{0u}; - str name_; - bool loop_{false}; - f32 delay_{0.f}; - str end_message_; - str complete_message_; - }; - - class set_empty_anim_cmd final { - public: - set_empty_anim_cmd(u32 track) - : track_(track) {} - - set_empty_anim_cmd& mix_duration(f32 value) noexcept { - mix_duration_ = value; - return *this; - } - - set_empty_anim_cmd& end_message(str value) noexcept { - end_message_ = std::move(value); - return *this; - } - - set_empty_anim_cmd& complete_message(str value) noexcept { - complete_message_ = std::move(value); - return *this; - } - - [[nodiscard]] u32 track() const noexcept { return track_; } - [[nodiscard]] f32 mix_duration() const noexcept { return mix_duration_; } - [[nodiscard]] const str& end_message() const noexcept { return end_message_; } - [[nodiscard]] const str& complete_message() const noexcept { return complete_message_; } - private: - u32 track_{0u}; - f32 mix_duration_{0.f}; - str end_message_; - str complete_message_; - }; - - class add_empty_anim_cmd final { - public: - add_empty_anim_cmd(u32 track) - : track_(track) {} - - add_empty_anim_cmd& delay(f32 value) noexcept { - delay_ = value; - return *this; - } - - add_empty_anim_cmd& mix_duration(f32 value) noexcept { - mix_duration_ = value; - return *this; - } - - add_empty_anim_cmd& end_message(str value) noexcept { - end_message_ = std::move(value); - return *this; - } - - add_empty_anim_cmd& complete_message(str value) noexcept { - complete_message_ = std::move(value); - return *this; - } - - [[nodiscard]] u32 track() const noexcept { return track_; } - [[nodiscard]] f32 delay() const noexcept { return delay_; } - [[nodiscard]] f32 mix_duration() const noexcept { return mix_duration_; } - [[nodiscard]] const str& end_message() const noexcept { return end_message_; } - [[nodiscard]] const str& complete_message() const noexcept { return complete_message_; } - private: - u32 track_{0u}; - f32 delay_{0.f}; - f32 mix_duration_{0.f}; - str end_message_; - str complete_message_; - }; -} diff --git a/headers/enduro2d/high/resources/spine.hpp b/headers/enduro2d/high/resources/spine.hpp deleted file mode 100644 index 326072d1..00000000 --- a/headers/enduro2d/high/resources/spine.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "../_high.hpp" - -struct spAtlas; -struct spSkeletonData; -struct spAnimationStateData; - -namespace e2d -{ - class bad_spine_access final : public exception { - public: - const char* what() const noexcept final { - return "bad spine access"; - } - }; - - class spine final { - public: - using atlas_ptr = std::shared_ptr; - using skeleton_data_ptr = std::shared_ptr; - using animation_data_ptr = std::shared_ptr; - public: - spine() = default; - ~spine() noexcept = default; - - spine(spine&& other) noexcept; - spine& operator=(spine&& other) noexcept; - - spine(const spine& other); - spine& operator=(const spine& other); - - void clear() noexcept; - void swap(spine& other) noexcept; - - spine& assign(spine&& other) noexcept; - spine& assign(const spine& other); - - spine& set_atlas(atlas_ptr atlas); - spine& set_skeleton(skeleton_data_ptr skeleton); - - spine& set_default_mix(f32 duration); - spine& set_animation_mix( - const str& from, - const str& to, - f32 duration); - - const atlas_ptr& atlas() const noexcept; - const skeleton_data_ptr& skeleton() const noexcept; - const animation_data_ptr& animation() const noexcept; - private: - atlas_ptr atlas_; - skeleton_data_ptr skeleton_; - animation_data_ptr animation_; - }; - - void swap(spine& l, spine& r) noexcept; - bool operator==(const spine& l, const spine& r) noexcept; - bool operator!=(const spine& l, const spine& r) noexcept; -} diff --git a/headers/enduro2d/high/systems/spine_system.hpp b/headers/enduro2d/high/systems/spine_system.hpp deleted file mode 100644 index 137099c4..00000000 --- a/headers/enduro2d/high/systems/spine_system.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "_systems.hpp" - -namespace e2d -{ - class spine_system final - : public ecs::system> { - public: - spine_system(); - ~spine_system() noexcept; - - void process( - ecs::registry& owner, - const ecs::after& trigger) override; - private: - class internal_state; - std::unique_ptr state_; - }; -} diff --git a/modules/spine b/modules/spine deleted file mode 160000 index 9fabc603..00000000 --- a/modules/spine +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9fabc6032363b27823110f5d8f7c14706367ccbf diff --git a/samples/bin/library/materials/spine_material_additive.json b/samples/bin/library/materials/spine_material_additive.json deleted file mode 100644 index a131c4cc..00000000 --- a/samples/bin/library/materials/spine_material_additive.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "passes" : [{ - "shader" : "../shaders/spine_shader.json", - "state_block" : { - "blending_state" : { - "src_factor" : "one", - "dst_factor" : "one" - }, - "capabilities_state" : { - "blending" : true - } - } - }] -} diff --git a/samples/bin/library/materials/spine_material_multiply.json b/samples/bin/library/materials/spine_material_multiply.json deleted file mode 100644 index 79d5b9dc..00000000 --- a/samples/bin/library/materials/spine_material_multiply.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "passes" : [{ - "shader" : "../shaders/spine_shader.json", - "state_block" : { - "blending_state" : { - "src_factor" : "dst_color", - "dst_factor" : "one_minus_src_alpha" - }, - "capabilities_state" : { - "blending" : true - } - } - }] -} diff --git a/samples/bin/library/materials/spine_material_normal.json b/samples/bin/library/materials/spine_material_normal.json deleted file mode 100644 index 6463264d..00000000 --- a/samples/bin/library/materials/spine_material_normal.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "passes" : [{ - "shader" : "../shaders/spine_shader.json", - "state_block" : { - "blending_state" : { - "src_factor" : "one", - "dst_factor" : "one_minus_src_alpha" - }, - "capabilities_state" : { - "blending" : true - } - } - }] -} diff --git a/samples/bin/library/materials/spine_material_screen.json b/samples/bin/library/materials/spine_material_screen.json deleted file mode 100644 index 7ffbe27b..00000000 --- a/samples/bin/library/materials/spine_material_screen.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "passes" : [{ - "shader" : "../shaders/spine_shader.json", - "state_block" : { - "blending_state" : { - "src_factor" : "one", - "dst_factor" : "one_minus_src_color" - }, - "capabilities_state" : { - "blending" : true - } - } - }] -} diff --git a/samples/bin/library/prefabs/coin_prefab.json b/samples/bin/library/prefabs/coin_prefab.json deleted file mode 100644 index 6ae01035..00000000 --- a/samples/bin/library/prefabs/coin_prefab.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "prefab" : "spine_prefab.json", - "components" : { - "named" : { - "name" : "coin" - }, - "spine_player" : { - "spine" : "../spines/coin_spine.json" - }, - "spine_player.commands" : { - "commands" : [{ - "type" : "set_anim_cmd", - "desc" : { - "track" : 0, - "name" : "animation", - "loop" : true - } - }] - } - } -} diff --git a/samples/bin/library/prefabs/dragon_prefab.json b/samples/bin/library/prefabs/dragon_prefab.json deleted file mode 100644 index d8d8bd5b..00000000 --- a/samples/bin/library/prefabs/dragon_prefab.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "prefab" : "spine_prefab.json", - "components" : { - "named" : { - "name" : "dragon" - }, - "spine_player" : { - "spine" : "../spines/dragon_spine.json" - }, - "spine_player.commands" : { - "commands" : [{ - "type" : "set_anim_cmd", - "desc" : { - "track" : 0, - "name" : "flying", - "loop" : true - } - }] - } - } -} diff --git a/samples/bin/library/prefabs/raptor_prefab.json b/samples/bin/library/prefabs/raptor_prefab.json deleted file mode 100644 index 964064b2..00000000 --- a/samples/bin/library/prefabs/raptor_prefab.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "prefab" : "spine_prefab.json", - "components" : { - "named" : { - "name" : "raptor" - }, - "spine_player" : { - "spine" : "../spines/raptor_spine.json" - }, - "spine_player.commands" : { - "commands" : [{ - "type" : "add_anim_cmd", - "desc" : { - "track" : 0, - "name" : "walk" - } - }, { - "type" : "add_anim_cmd", - "desc" : { - "track" : 0, - "name" : "roar" - } - }, { - "type" : "add_anim_cmd", - "desc" : { - "track" : 0, - "name" : "walk", - "loop" : true - } - }, { - "type" : "add_anim_cmd", - "desc" : { - "track" : 1, - "name" : "gun-grab", - "delay" : 2 - } - }, { - "type" : "add_anim_cmd", - "desc" : { - "track" : 1, - "name" : "gun-holster", - "delay" : 3 - } - }] - } - } -} diff --git a/samples/bin/library/prefabs/spine_prefab.json b/samples/bin/library/prefabs/spine_prefab.json deleted file mode 100644 index 2a1918a7..00000000 --- a/samples/bin/library/prefabs/spine_prefab.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "components" : { - "named" : { - "name" : "spine" - }, - "renderer" : {}, - "spine_player" : { - "materials" : { - "additive" : "../materials/spine_material_additive.json", - "multiply" : "../materials/spine_material_multiply.json", - "normal" : "../materials/spine_material_normal.json", - "screen" : "../materials/spine_material_screen.json" - } - }, - "spine_player.events" : {}, - "spine_player.commands" : {} - } -} diff --git a/samples/bin/library/scenes/sample_06.json b/samples/bin/library/scenes/sample_06.json index efca2bbf..c76bb455 100644 --- a/samples/bin/library/scenes/sample_06.json +++ b/samples/bin/library/scenes/sample_06.json @@ -2,38 +2,5 @@ "prefab" : "../prefabs/scene_prefab.json", "children" : [{ "prefab" : "../prefabs/camera_prefab.json" - },{ - "prefab" : "../prefabs/coin_prefab.json", - "components" : { - "actor" : { - "translation" : [350,250], - "scale" : 0.25 - }, - "named" : { - "name" : "coin" - } - } - }, { - "prefab" : "../prefabs/raptor_prefab.json", - "components" : { - "actor" : { - "translation" : [300,-350], - "scale" : 0.25 - }, - "named" : { - "name" : "raptor" - } - } - }, { - "prefab" : "../prefabs/dragon_prefab.json", - "components" : { - "actor" : { - "translation" : [-100,0], - "scale" : 0.9 - }, - "named" : { - "name" : "dragon" - } - } }] } diff --git a/samples/bin/library/shaders/spine_shader.frag b/samples/bin/library/shaders/spine_shader.frag deleted file mode 100644 index 7ea012bd..00000000 --- a/samples/bin/library/shaders/spine_shader.frag +++ /dev/null @@ -1,10 +0,0 @@ -uniform sampler2D u_texture; - -varying vec2 v_st0; -varying vec4 v_color0; - -void main() { - vec4 c = texture2D(u_texture, v_st0) * v_color0; - c.rgb *= c.a; - gl_FragColor = c; -} diff --git a/samples/bin/library/shaders/spine_shader.json b/samples/bin/library/shaders/spine_shader.json deleted file mode 100644 index 49e5a054..00000000 --- a/samples/bin/library/shaders/spine_shader.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "vertex" : "spine_shader.vert", - "fragment" : "spine_shader.frag" -} diff --git a/samples/bin/library/shaders/spine_shader.vert b/samples/bin/library/shaders/spine_shader.vert deleted file mode 100644 index cf3bb179..00000000 --- a/samples/bin/library/shaders/spine_shader.vert +++ /dev/null @@ -1,36 +0,0 @@ -uniform vec2 u_screen_s; -uniform mat4 u_matrix_vp; - -attribute vec3 a_vertex; -attribute vec2 a_st0; -attribute vec4 a_color0; - -varying vec2 v_st0; -varying vec4 v_color0; - -vec2 round(vec2 v) { - return vec2( - floor(v.x + 0.5), - floor(v.y + 0.5)); -} - -vec4 pixel_snap(vec4 pos) { - vec2 hpc = u_screen_s * 0.5; - vec2 pixel_pos = round((pos.xy / pos.w) * hpc); - pos.xy = pixel_pos / hpc * pos.w; - return pos; -} - -vec4 vertex_to_homo(vec3 pos) { - return vec4(pos, 1.0) * u_matrix_vp; -} - -void main() { - v_st0 = a_st0; - v_color0 = a_color0; -#ifndef VERTEX_SNAPPING_ON - gl_Position = vertex_to_homo(a_vertex); -#else - gl_Position = pixel_snap(vertex_to_homo(a_vertex)); -#endif -} diff --git a/samples/bin/library/spines/coin/coin-pro.skel b/samples/bin/library/spines/coin/coin-pro.skel deleted file mode 100644 index da1f3b2f..00000000 --- a/samples/bin/library/spines/coin/coin-pro.skel +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:772bf78b10c22079c0afb46edfff2eff789c4082cd52f4124868a04905b72bbf -size 2657 diff --git a/samples/bin/library/spines/coin/coin.atlas b/samples/bin/library/spines/coin/coin.atlas deleted file mode 100644 index 89443c48..00000000 --- a/samples/bin/library/spines/coin/coin.atlas +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:833bc92c2a02695c326080b72f8636206ec53f361010a6b02324565b470f690b -size 831 diff --git a/samples/bin/library/spines/coin/coin.png b/samples/bin/library/spines/coin/coin.png deleted file mode 100644 index d08611e0..00000000 --- a/samples/bin/library/spines/coin/coin.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:21bc65e3de306d698df5c6a6519786a430d8529bc58f01f87013c9927819f87a -size 402363 diff --git a/samples/bin/library/spines/coin_spine.json b/samples/bin/library/spines/coin_spine.json deleted file mode 100644 index 2a0a6029..00000000 --- a/samples/bin/library/spines/coin_spine.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "atlas" : "coin/coin.atlas", - "skeleton" : "coin/coin-pro.skel", - "skeleton_scale" : 1.0 -} diff --git a/samples/bin/library/spines/dragon/dragon-ess.skel b/samples/bin/library/spines/dragon/dragon-ess.skel deleted file mode 100644 index 24c19706..00000000 --- a/samples/bin/library/spines/dragon/dragon-ess.skel +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2d299087ede92db92396af117f151e8f50abecb57094f34b031d0a389a53d1ad -size 7073 diff --git a/samples/bin/library/spines/dragon/dragon.atlas b/samples/bin/library/spines/dragon/dragon.atlas deleted file mode 100644 index 6765e4b3..00000000 --- a/samples/bin/library/spines/dragon/dragon.atlas +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa3a79e67d926b1e5f017ecd2f2bc2f73fa02a766f27cc83a6547f0c90556c58 -size 4224 diff --git a/samples/bin/library/spines/dragon/dragon.png b/samples/bin/library/spines/dragon/dragon.png deleted file mode 100644 index 70dfda26..00000000 --- a/samples/bin/library/spines/dragon/dragon.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a45ac203747ffc4802c83860b20bcb380b405ea55734992defb5fb64f49bbfa0 -size 628537 diff --git a/samples/bin/library/spines/dragon/dragon2.png b/samples/bin/library/spines/dragon/dragon2.png deleted file mode 100644 index 50ed6210..00000000 --- a/samples/bin/library/spines/dragon/dragon2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:86b1a3fcd15a538e08535f0fad4b6cc1c9595060aae0d558c0f2bcc1d09a2833 -size 194829 diff --git a/samples/bin/library/spines/dragon_spine.json b/samples/bin/library/spines/dragon_spine.json deleted file mode 100644 index 4997fae6..00000000 --- a/samples/bin/library/spines/dragon_spine.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "atlas" : "dragon/dragon.atlas", - "skeleton" : "dragon/dragon-ess.skel", - "skeleton_scale" : 1.0 -} diff --git a/samples/bin/library/spines/raptor/raptor-pro.json-large b/samples/bin/library/spines/raptor/raptor-pro.json-large deleted file mode 100644 index 47afbe58..00000000 --- a/samples/bin/library/spines/raptor/raptor-pro.json-large +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c8d0e5057c92306900f39879e51642500b841825cedb47833bbfa129978b5757 -size 172896 diff --git a/samples/bin/library/spines/raptor/raptor-pro.skel b/samples/bin/library/spines/raptor/raptor-pro.skel deleted file mode 100644 index 235f7aa0..00000000 --- a/samples/bin/library/spines/raptor/raptor-pro.skel +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:83c00999f00c4ac395ba063291d02131fb2a8869cb6d8f4fd20bc15131d52d54 -size 63077 diff --git a/samples/bin/library/spines/raptor/raptor.atlas b/samples/bin/library/spines/raptor/raptor.atlas deleted file mode 100644 index 3ea64517..00000000 --- a/samples/bin/library/spines/raptor/raptor.atlas +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd001b421b535adb21c74148790d8b576d17aedaeecf0f2ac6318619b94a932b -size 4210 diff --git a/samples/bin/library/spines/raptor/raptor.png b/samples/bin/library/spines/raptor/raptor.png deleted file mode 100644 index 6e6a20d2..00000000 --- a/samples/bin/library/spines/raptor/raptor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:879d84230024a1529ea994e7cd6416c5883f4b74b0d268b5e2dea1cbe2d00777 -size 480392 diff --git a/samples/bin/library/spines/raptor_spine.json b/samples/bin/library/spines/raptor_spine.json deleted file mode 100644 index 3e86aa10..00000000 --- a/samples/bin/library/spines/raptor_spine.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "atlas": "raptor/raptor.atlas", - "skeleton": "raptor/raptor-pro.json-large", - "skeleton_scale": 1.0, - "default_animation_mix" : 0.5, - "animation_mixes": [ - { - "from": "walk", - "to": "roar", - "duration": 0.5 - }, - { - "from": "roar", - "to": "walk", - "duration": 0.5 - }, - { - "from": "walk", - "to": "jump", - "duration": 0.5 - }, - { - "from": "jump", - "to": "walk", - "duration": 0.5 - }, - { - "from": "roar", - "to": "jump", - "duration": 0.5 - }, - { - "from": "jump", - "to": "roar", - "duration": 0.5 - } - ] -} diff --git a/samples/sources/sample_06/sample_06.cpp b/samples/sources/sample_06/sample_06.cpp index 85194102..887e2259 100644 --- a/samples/sources/sample_06/sample_06.cpp +++ b/samples/sources/sample_06/sample_06.cpp @@ -29,44 +29,6 @@ namespace if ( k.is_key_pressed(keyboard_key::lsuper) && k.is_key_just_released(keyboard_key::enter) ) { the().toggle_fullscreen(!the().fullscreen()); } - - // use keys R, J, G to start animations - const bool roar = k.is_key_just_pressed(keyboard_key::r); - const bool jump = k.is_key_just_pressed(keyboard_key::j); - const bool gun_grab = k.is_key_just_pressed(keyboard_key::g); - - if ( roar || jump || gun_grab ) { - owner.for_each_component([ - roar, jump, gun_grab - ](ecs::entity e, const spine_player& p) { - if ( roar && p.has_animation("roar") ) { - e.ensure_component>() - .add(spine_player_commands::set_anim_cmd(0, "roar") - .complete_message("to_walk")); - } else if ( jump && p.has_animation("jump") ) { - e.ensure_component>() - .add(spine_player_commands::set_anim_cmd(0, "jump") - .complete_message("to_walk")); - } else if ( gun_grab && p.has_animation("gun-grab") ) { - e.ensure_component>() - .add(spine_player_commands::set_anim_cmd(1, "gun-grab")) - .add(spine_player_commands::add_anim_cmd(1, "gun-holster").delay(3.f)); - } - }); - } - - owner.for_joined_components>([ - ](ecs::entity e, const events& pe) { - for ( const auto& evt : pe.get() ) { - if ( auto complete = std::get_if(&evt); - complete && complete->message() == "to_walk" ) - { - e.ensure_component>() - .add(spine_player_commands::add_anim_cmd(0, "walk") - .loop(true)); - } - } - }); } }; diff --git a/sources/enduro2d/high/assets/spine_asset.cpp b/sources/enduro2d/high/assets/spine_asset.cpp deleted file mode 100644 index a2058bf6..00000000 --- a/sources/enduro2d/high/assets/spine_asset.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#include -#include -#include - -#include -#include - -namespace -{ - using namespace e2d; - - class spine_asset_loading_exception final : public asset_loading_exception { - const char* what() const noexcept final { - return "spine asset loading exception"; - } - }; - - const char* spine_asset_schema_source = R"json({ - "type" : "object", - "required" : [ "atlas", "skeleton" ], - "additionalProperties" : false, - "properties" : { - "atlas" : { "$ref" : "#/common_definitions/address" }, - "skeleton" : { "$ref" : "#/common_definitions/address" }, - "skeleton_scale" : { "type" : "number" }, - "default_animation_mix" : { "type" : "number" }, - "animation_mixes" : { "$ref": "#/definitions/animation_mixes" } - }, - "definitions" : { - "animation_mixes" : { - "type" : "array", - "items" : { "$ref": "#/definitions/animation_mix" } - }, - "animation_mix" : { - "type" : "object", - "required" : [ "from", "to", "duration" ], - "additionalProperties" : false, - "properties" : { - "from" : { "$ref": "#/common_definitions/name" }, - "to" : { "$ref": "#/common_definitions/name" }, - "duration" : { "type" : "number" } - } - } - } - })json"; - - const rapidjson::SchemaDocument& spine_asset_schema() { - static std::mutex mutex; - static std::unique_ptr schema; - - std::lock_guard guard(mutex); - if ( !schema ) { - rapidjson::Document doc; - if ( doc.Parse(spine_asset_schema_source).HasParseError() ) { - the().error("ASSETS: Failed to parse spine asset schema"); - throw spine_asset_loading_exception(); - } - json_utils::add_common_schema_definitions(doc); - schema = std::make_unique(doc); - } - - return *schema; - } - - struct animation_mix { - str from; - str to; - f32 duration{0.f}; - }; - - animation_mix parse_animation_mix(const rapidjson::Value& root) { - animation_mix mix; - - E2D_ASSERT(root.HasMember("from") && root["from"].IsString()); - if ( !json_utils::try_parse_value(root["from"], mix.from) ) { - the().error("SPINE: Incorrect formating of 'from' property"); - throw spine_asset_loading_exception(); - } - - E2D_ASSERT(root.HasMember("to") && root["to"].IsString()); - if ( !json_utils::try_parse_value(root["to"], mix.to) ) { - the().error("SPINE: Incorrect formating of 'to' property"); - throw spine_asset_loading_exception(); - } - - E2D_ASSERT(root.HasMember("duration") && root["duration"].IsNumber()); - if ( !json_utils::try_parse_value(root["duration"], mix.duration) ) { - the().error("SPINE: Incorrect formating of 'duration' property"); - throw spine_asset_loading_exception(); - } - - return mix; - } - - struct atlas_internal_state { - asset_group loaded; - asset_dependencies loading; - }; - - stdex::promise load_atlas( - const library& library, - const str& parent_address, - const str& atlas_address) - { - const str atlas_path = path::combine(parent_address, atlas_address); - const str atlas_folder = path::parent_path(atlas_path); - - return library.load_asset_async(atlas_path) - .then([ - &library, - atlas_path, - atlas_folder - ](const binary_asset::load_result& atlas_data){ - return the().do_in_worker_thread([](){}) - .then([ - &library, - atlas_data, - atlas_path, - atlas_folder - ](){ - auto atlas_internal = std::make_unique(); - - spine::atlas_ptr atlas( - spAtlas_create( - reinterpret_cast(atlas_data->content().data()), - math::numeric_cast(atlas_data->content().size()), - atlas_folder.c_str(), - atlas_internal.get()), - spAtlas_dispose); - - if ( !atlas ) { - the().error("SPINE: Failed to create preload atlas"); - throw spine_asset_loading_exception(); - } - - return atlas_internal->loading.load_async(library); - }) - .then([ - atlas_data, - atlas_path, - atlas_folder - ](auto&& dependencies){ - auto atlas_internal = std::make_unique(); - atlas_internal->loaded = std::forward(dependencies); - - spine::atlas_ptr atlas( - spAtlas_create( - reinterpret_cast(atlas_data->content().data()), - math::numeric_cast(atlas_data->content().size()), - atlas_folder.c_str(), - atlas_internal.get()), - spAtlas_dispose); - - if ( !atlas ) { - the().error("SPINE: Failed to create preloaded atlas"); - throw spine_asset_loading_exception(); - } - - for ( const spAtlasPage* page = atlas->pages; page; page = page->next ) { - if ( !page->rendererObject ) { - the().error("SPINE: Failed to create preloaded atlas"); - throw spine_asset_loading_exception(); - } - } - - atlas->rendererObject = nullptr; - return atlas; - }); - }); - } - - stdex::promise load_skeleton_data( - const library& library, - const str& parent_address, - const str& skeleton_address, - f32 skeleton_scale, - const spine::atlas_ptr& atlas) - { - str address = path::combine(parent_address, skeleton_address); - return library.load_asset_async(address) - .then([ - atlas, - skeleton_scale, - address = std::move(address) - ](const binary_asset::load_result& skeleton_data){ - return the().do_in_worker_thread([ - atlas, - skeleton_scale, - address = std::move(address), - skeleton_data - ](){ - if ( strings::ends_with(address, ".skel") ) { - using skeleton_bin_ptr = std::unique_ptr< - spSkeletonBinary, - decltype(&::spSkeletonBinary_dispose)>; - - skeleton_bin_ptr binary_skeleton( - spSkeletonBinary_create(atlas.get()), - spSkeletonBinary_dispose); - - if ( !binary_skeleton ) { - the().error("SPINE: Failed to create binary skeleton"); - throw spine_asset_loading_exception(); - } - - binary_skeleton->scale = skeleton_scale; - - spine::skeleton_data_ptr data_skeleton( - spSkeletonBinary_readSkeletonData( - binary_skeleton.get(), - reinterpret_cast(skeleton_data->content().data()), - math::numeric_cast(skeleton_data->content().size())), - spSkeletonData_dispose); - - if ( !data_skeleton ) { - the().error("SPINE: Failed to read binary skeleton data:\n" - "--> Error: %0", - binary_skeleton->error); - throw spine_asset_loading_exception(); - } - - return data_skeleton; - } else { - using skeleton_json_ptr = std::unique_ptr< - spSkeletonJson, - decltype(&::spSkeletonJson_dispose)>; - - skeleton_json_ptr json_skeleton( - spSkeletonJson_create(atlas.get()), - spSkeletonJson_dispose); - - if ( !json_skeleton ) { - the().error("SPINE: Failed to create json skeleton"); - throw spine_asset_loading_exception(); - } - - json_skeleton->scale = skeleton_scale; - - spine::skeleton_data_ptr data_skeleton( - spSkeletonJson_readSkeletonData( - json_skeleton.get(), - reinterpret_cast(skeleton_data->content().data())), - spSkeletonData_dispose); - - if ( !data_skeleton ) { - the().error("SPINE: Failed to read json skeleton data:\n" - "--> Error: %0", - json_skeleton->error); - throw spine_asset_loading_exception(); - } - - return data_skeleton; - } - }); - }); - } - - stdex::promise parse_spine( - const library& library, - const str& parent_address, - const rapidjson::Value& root) - { - f32 skeleton_scale{1.0f}; - if ( root.HasMember("skeleton_scale") ) { - if ( !json_utils::try_parse_value(root["skeleton_scale"], skeleton_scale) ) { - the().error("SPINE: Incorrect formating of 'skeleton_scale' property"); - } - } - - f32 default_animation_mix{0.5f}; - if ( root.HasMember("default_animation_mix") ) { - if ( !json_utils::try_parse_value(root["default_animation_mix"], default_animation_mix) ) { - the().error("SPINE: Incorrect formating of 'default_animation_mix' property"); - } - } - - vector animation_mixes; - if ( root.HasMember("animation_mixes") ) { - E2D_ASSERT(root["animation_mixes"].IsArray()); - const auto& mixes_json = root["animation_mixes"]; - animation_mixes.reserve(mixes_json.Size()); - for ( rapidjson::SizeType i = 0; i < mixes_json.Size(); ++i ) { - E2D_ASSERT(mixes_json[i].IsObject()); - animation_mixes.push_back( - parse_animation_mix(mixes_json[i])); - } - } - - E2D_ASSERT(root.HasMember("atlas") && root["atlas"].IsString()); - const str atlas_address = root["atlas"].GetString(); - - E2D_ASSERT(root.HasMember("skeleton") && root["skeleton"].IsString()); - const str skeleton_address = root["skeleton"].GetString(); - - return load_atlas( - library, - parent_address, - atlas_address) - .then([ - &library, - parent_address, - atlas_address, - skeleton_scale, - skeleton_address - ](const spine::atlas_ptr& atlas){ - return stdex::make_tuple_promise(std::make_tuple( - stdex::make_resolved_promise(atlas), - load_skeleton_data( - library, - parent_address, - skeleton_address, - skeleton_scale, - atlas))); - }) - .then([ - default_animation_mix, - animation_mixes = std::move(animation_mixes) - ](const std::tuple< - spine::atlas_ptr, - spine::skeleton_data_ptr - >& results){ - spine content; - content.set_atlas(std::get<0>(results)); - content.set_skeleton(std::get<1>(results)); - content.set_default_mix(default_animation_mix); - for ( const animation_mix& mix : animation_mixes ) { - content.set_animation_mix(mix.from, mix.to, mix.duration); - } - return content; - }); - } -} - -namespace e2d -{ - spine_asset::load_async_result spine_asset::load_async( - const library& library, str_view address) - { - return library.load_asset_async(address) - .then([ - &library, - address = str(address), - parent_address = path::parent_path(address) - ](const json_asset::load_result& spine_data){ - return the().do_in_worker_thread([address, spine_data](){ - const rapidjson::Document& doc = *spine_data->content(); - rapidjson::SchemaValidator validator(spine_asset_schema()); - - if ( doc.Accept(validator) ) { - return; - } - - rapidjson::StringBuffer sb; - if ( validator.GetInvalidDocumentPointer().StringifyUriFragment(sb) ) { - the().error("ASSET: Failed to validate asset json:\n" - "--> Address: %0\n" - "--> Invalid schema keyword: %1\n" - "--> Invalid document pointer: %2", - address, - validator.GetInvalidSchemaKeyword(), - sb.GetString()); - } else { - the().error("ASSET: Failed to validate asset json"); - } - - throw spine_asset_loading_exception(); - }) - .then([&library, parent_address, spine_data](){ - return parse_spine( - library, parent_address, *spine_data->content()); - }) - .then([](auto&& content){ - return spine_asset::create( - std::forward(content)); - }); - }); - } -} - -extern "C" void _spAtlasPage_createTexture(spAtlasPage* self, const char* path) { - try { - E2D_ASSERT(self->atlas->rendererObject); - atlas_internal_state& atlas_internal = - *static_cast(self->atlas->rendererObject); - auto texture_res = atlas_internal.loaded.find_asset(path); - if ( texture_res ) { - self->width = math::numeric_cast(texture_res->content()->size().x); - self->height = math::numeric_cast(texture_res->content()->size().y); - self->rendererObject = texture_res.release(); - } else { - atlas_internal.loading.add_dependency(path); - } - } catch(...) { - // nothing - } -} - -extern "C" void _spAtlasPage_disposeTexture(spAtlasPage* self) { - E2D_UNUSED(texture_asset::load_result( - static_cast(self->rendererObject), false)); -} - -extern "C" char* _spUtil_readFile(const char* path, int* length) { - E2D_ASSERT_MSG(false, "unimplemented by design"); - E2D_UNUSED(path, length); - return nullptr; -} diff --git a/sources/enduro2d/high/components/spine_player.cpp b/sources/enduro2d/high/components/spine_player.cpp deleted file mode 100644 index ff4ff3a5..00000000 --- a/sources/enduro2d/high/components/spine_player.cpp +++ /dev/null @@ -1,922 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#include -#include - -#include - -namespace -{ - using namespace e2d; - - std::optional parse_custom_evt(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - spine_player_events::custom_evt evt; - - if ( root.HasMember("name") ) { - str evt_name = evt.name(); - if ( !json_utils::try_parse_value(root["name"], evt_name) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'custom_evt.name' property"); - return std::nullopt; - } - evt.name(std::move(evt_name)); - } - - if ( root.HasMember("int_value") ) { - i32 evt_int_value = evt.int_value(); - if ( !json_utils::try_parse_value(root["int_value"], evt_int_value) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'custom_evt.int_value' property"); - return std::nullopt; - } - evt.int_value(evt_int_value); - } - - if ( root.HasMember("float_value") ) { - f32 evt_float_value = evt.float_value(); - if ( !json_utils::try_parse_value(root["float_value"], evt_float_value) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'custom_evt.float_value' property"); - return std::nullopt; - } - evt.float_value(evt_float_value); - } - - if ( root.HasMember("string_value") ) { - str evt_string_value = evt.string_value(); - if ( !json_utils::try_parse_value(root["string_value"], evt_string_value) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'custom_evt.string_value' property"); - return std::nullopt; - } - evt.string_value(std::move(evt_string_value)); - } - - return evt; - } - - std::optional parse_end_evt(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - spine_player_events::end_evt evt; - - if ( root.HasMember("message") ) { - str evt_message = evt.message(); - if ( !json_utils::try_parse_value(root["message"], evt_message) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'end_evt.message' property"); - return std::nullopt; - } - evt.message(std::move(evt_message)); - } - - return evt; - } - - std::optional parse_complete_evt(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - spine_player_events::complete_evt evt; - - if ( root.HasMember("message") ) { - str evt_message = evt.message(); - if ( !json_utils::try_parse_value(root["message"], evt_message) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'complete_evt.message' property"); - return std::nullopt; - } - evt.message(std::move(evt_message)); - } - - return evt; - } - - std::optional parse_event(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - str_hash command_type; - E2D_ASSERT(root.HasMember("type") && root["type"].IsString()); - if ( !json_utils::try_parse_value(root["type"], command_type) ) { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'event.type' property"); - return std::nullopt; - } - - E2D_ASSERT(root.HasMember("desc") && root["desc"].IsObject()); - const auto& event_desc = root["desc"]; - - if ( command_type == make_hash("custom_evt") ) { - auto evt = parse_custom_evt(event_desc); - return evt ? evt : std::nullopt; - } else if ( command_type == make_hash("end_evt") ) { - auto evt = parse_end_evt(event_desc); - return evt ? evt : std::nullopt; - } else if ( command_type == make_hash("complete_evt") ) { - auto evt = parse_complete_evt(event_desc); - return evt ? evt : std::nullopt; - } else { - the().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'event.type' property"); - return std::nullopt; - } - } - - std::optional> parse_events(const rapidjson::Value& root) { - E2D_ASSERT(root.IsArray()); - - vector evts; - evts.reserve(root.Size()); - - for ( rapidjson::SizeType i = 0; i < root.Size(); ++i ) { - auto evt = parse_event(root[i]); - if ( !evt ) { - return std::nullopt; - } - evts.push_back(std::move(*evt)); - } - - return evts; - } -} - -namespace -{ - using namespace e2d; - - std::optional parse_clear_track_cmd(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - u32 cmd_track{0u}; - if ( !json_utils::try_parse_value(root["track"], cmd_track) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'clear_track_cmd.track' property"); - return std::nullopt; - } - - return spine_player_commands::clear_track_cmd(cmd_track); - } - - std::optional parse_set_anim_cmd(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - u32 cmd_track{0u}; - E2D_ASSERT(root.HasMember("track")); - if ( !json_utils::try_parse_value(root["track"], cmd_track) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_anim_cmd.track' property"); - return std::nullopt; - } - - str cmd_name; - E2D_ASSERT(root.HasMember("name")); - if ( !json_utils::try_parse_value(root["name"], cmd_name) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_anim_cmd.name' property"); - return std::nullopt; - } - - spine_player_commands::set_anim_cmd cmd(cmd_track, std::move(cmd_name)); - - if ( root.HasMember("loop") ) { - bool cmd_loop = cmd.loop(); - if ( !json_utils::try_parse_value(root["loop"], cmd_loop) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_anim_cmd.loop' property"); - return std::nullopt; - } - cmd.loop(cmd_loop); - } - - if ( root.HasMember("end_message") ) { - str cmd_end_message = cmd.end_message(); - if ( !json_utils::try_parse_value(root["end_message"], cmd_end_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_anim_cmd.end_message' property"); - return std::nullopt; - } - cmd.end_message(std::move(cmd_end_message)); - } - - if ( root.HasMember("complete_message") ) { - str cmd_complete_message = cmd.complete_message(); - if ( !json_utils::try_parse_value(root["complete_message"], cmd_complete_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_anim_cmd.complete_message' property"); - return std::nullopt; - } - cmd.complete_message(std::move(cmd_complete_message)); - } - - return cmd; - } - - std::optional parse_add_anim_cmd(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - u32 cmd_track{0u}; - E2D_ASSERT(root.HasMember("track")); - if ( !json_utils::try_parse_value(root["track"], cmd_track) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.track' property"); - return std::nullopt; - } - - str cmd_name; - E2D_ASSERT(root.HasMember("name")); - if ( !json_utils::try_parse_value(root["name"], cmd_name) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.name' property"); - return std::nullopt; - } - - spine_player_commands::add_anim_cmd cmd(cmd_track, std::move(cmd_name)); - - if ( root.HasMember("loop") ) { - bool cmd_loop = cmd.loop(); - if ( !json_utils::try_parse_value(root["loop"], cmd_loop) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.loop' property"); - return std::nullopt; - } - cmd.loop(cmd_loop); - } - - if ( root.HasMember("delay") ) { - f32 cmd_delay = cmd.delay(); - if ( !json_utils::try_parse_value(root["delay"], cmd_delay) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.delay' property"); - return std::nullopt; - } - cmd.delay(cmd_delay); - } - - if ( root.HasMember("end_message") ) { - str cmd_end_message = cmd.end_message(); - if ( !json_utils::try_parse_value(root["end_message"], cmd_end_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.end_message' property"); - return std::nullopt; - } - cmd.end_message(std::move(cmd_end_message)); - } - - if ( root.HasMember("complete_message") ) { - str cmd_complete_message = cmd.complete_message(); - if ( !json_utils::try_parse_value(root["complete_message"], cmd_complete_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_anim_cmd.complete_message' property"); - return std::nullopt; - } - cmd.complete_message(std::move(cmd_complete_message)); - } - - return cmd; - } - - std::optional parse_set_empty_anim_cmd(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - u32 cmd_track{0u}; - E2D_ASSERT(root.HasMember("track")); - if ( !json_utils::try_parse_value(root["track"], cmd_track) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_empty_anim_cmd.track' property"); - return std::nullopt; - } - - spine_player_commands::set_empty_anim_cmd cmd(cmd_track); - - if ( root.HasMember("mix_duration") ) { - f32 cmd_mix_duration = cmd.mix_duration(); - if ( !json_utils::try_parse_value(root["mix_duration"], cmd_mix_duration) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_empty_anim_cmd.mix_duration' property"); - return std::nullopt; - } - cmd.mix_duration(cmd_mix_duration); - } - - if ( root.HasMember("end_message") ) { - str cmd_end_message = cmd.end_message(); - if ( !json_utils::try_parse_value(root["end_message"], cmd_end_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_empty_anim_cmd.end_message' property"); - return std::nullopt; - } - cmd.end_message(std::move(cmd_end_message)); - } - - if ( root.HasMember("complete_message") ) { - str cmd_complete_message = cmd.complete_message(); - if ( !json_utils::try_parse_value(root["complete_message"], cmd_complete_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'set_empty_anim_cmd.complete_message' property"); - return std::nullopt; - } - cmd.complete_message(std::move(cmd_complete_message)); - } - - return cmd; - } - - std::optional parse_add_empty_anim_cmd(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - u32 cmd_track{0u}; - E2D_ASSERT(root.HasMember("track")); - if ( !json_utils::try_parse_value(root["track"], cmd_track) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_empty_anim_cmd.track' property"); - return std::nullopt; - } - - spine_player_commands::add_empty_anim_cmd cmd(cmd_track); - - if ( root.HasMember("delay") ) { - f32 cmd_delay = cmd.delay(); - if ( !json_utils::try_parse_value(root["delay"], cmd_delay) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_empty_anim_cmd.delay' property"); - return std::nullopt; - } - cmd.delay(cmd_delay); - } - - if ( root.HasMember("mix_duration") ) { - f32 cmd_mix_duration = cmd.mix_duration(); - if ( !json_utils::try_parse_value(root["mix_duration"], cmd_mix_duration) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_empty_anim_cmd.mix_duration' property"); - return std::nullopt; - } - cmd.mix_duration(cmd_mix_duration); - } - - if ( root.HasMember("end_message") ) { - str cmd_end_message = cmd.end_message(); - if ( !json_utils::try_parse_value(root["end_message"], cmd_end_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_empty_anim_cmd.end_message' property"); - return std::nullopt; - } - cmd.end_message(std::move(cmd_end_message)); - } - - if ( root.HasMember("complete_message") ) { - str cmd_complete_message = cmd.complete_message(); - if ( !json_utils::try_parse_value(root["complete_message"], cmd_complete_message) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'add_empty_anim_cmd.complete_message' property"); - return std::nullopt; - } - cmd.complete_message(std::move(cmd_complete_message)); - } - - return cmd; - } - - std::optional parse_command(const rapidjson::Value& root) { - E2D_ASSERT(root.IsObject()); - - str_hash command_type; - E2D_ASSERT(root.HasMember("type") && root["type"].IsString()); - if ( !json_utils::try_parse_value(root["type"], command_type) ) { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'command.type' property"); - return std::nullopt; - } - - E2D_ASSERT(root.HasMember("desc") && root["desc"].IsObject()); - const auto& command_desc = root["desc"]; - - if ( command_type == make_hash("clear_track_cmd") ) { - auto cmd = parse_clear_track_cmd(command_desc); - return cmd ? cmd : std::nullopt; - } else if ( command_type == make_hash("set_anim_cmd") ) { - auto cmd = parse_set_anim_cmd(command_desc); - return cmd ? cmd : std::nullopt; - } else if ( command_type == make_hash("add_anim_cmd") ) { - auto cmd = parse_add_anim_cmd(command_desc); - return cmd ? cmd : std::nullopt; - } else if ( command_type == make_hash("set_empty_anim_cmd") ) { - auto cmd = parse_set_empty_anim_cmd(command_desc); - return cmd ? cmd : std::nullopt; - } else if ( command_type == make_hash("add_empty_anim_cmd") ) { - auto cmd = parse_add_empty_anim_cmd(command_desc); - return cmd ? cmd : std::nullopt; - } else { - the().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'command.type' property"); - return std::nullopt; - } - } - - std::optional> parse_commands(const rapidjson::Value& root) { - E2D_ASSERT(root.IsArray()); - - vector cmds; - cmds.reserve(root.Size()); - - for ( rapidjson::SizeType i = 0; i < root.Size(); ++i ) { - auto cmd = parse_command(root[i]); - if ( !cmd ) { - return std::nullopt; - } - cmds.push_back(std::move(*cmd)); - } - - return cmds; - } -} - -namespace e2d -{ - spine_player::spine_player(const spine_asset::ptr& spine) { - this->spine(spine); - } - - spine_player& spine_player::spine(const spine_asset::ptr& value) { - clipping_ptr new_clipping = clipping_ptr( - spSkeletonClipping_create(), - spSkeletonClipping_dispose); - if ( !new_clipping ) { - throw std::bad_alloc(); - } - - skeleton_ptr new_skeleton; - if ( value && value->content().skeleton() ) { - new_skeleton = skeleton_ptr( - spSkeleton_create(value->content().skeleton().get()), - spSkeleton_dispose); - if ( !new_skeleton ) { - throw std::bad_alloc(); - } - } - - animation_ptr new_animation; - if ( value && value->content().animation() ) { - new_animation = animation_ptr( - spAnimationState_create(value->content().animation().get()), - spAnimationState_dispose); - if ( !new_animation ) { - throw std::bad_alloc(); - } - } - - spine_ = value; - clipping_ = std::move(new_clipping); - skeleton_ = std::move(new_skeleton); - animation_ = std::move(new_animation); - return *this; - } - - bool spine_player::skin(str_view name) { - if ( !skeleton_ ) { - return false; - } - - static thread_local str skin_name; - skin_name = name; - - return !!spSkeleton_setSkinByName( - skeleton_.get(), skin_name.c_str()); - } - - bool spine_player::attachment(str_view slot, str_view name) { - if ( !skeleton_ ) { - return false; - } - - static thread_local str slot_name; - slot_name = slot; - - static thread_local str attachment_name; - attachment_name = name; - - return !!spSkeleton_setAttachment( - skeleton_.get(), slot_name.c_str(), attachment_name.c_str()); - } - - bool spine_player::has_skin(str_view name) const noexcept { - if ( !skeleton_ ) { - return false; - } - - for ( int i = 0; i < skeleton_->data->skinsCount; ++i ) { - if ( name == skeleton_->data->skins[i]->name ) { - return true; - } - } - - return false; - } - - bool spine_player::has_animation(str_view name) const noexcept { - if ( !skeleton_ ) { - return false; - } - - for ( int i = 0; i < skeleton_->data->animationsCount; ++i ) { - if ( name == skeleton_->data->animations[i]->name ) { - return true; - } - } - - return false; - } - - const spine_asset::ptr& spine_player::spine() const noexcept { - return spine_; - } - - const spine_player::clipping_ptr& spine_player::clipper() const noexcept { - return clipping_; - } - - const spine_player::skeleton_ptr& spine_player::skeleton() const noexcept { - return skeleton_; - } - - const spine_player::animation_ptr& spine_player::animation() const noexcept { - return animation_; - } - - spine_player& spine_player::materials(flat_map value) noexcept { - materials_ = std::move(value); - return *this; - } - - const flat_map& spine_player::materials() const noexcept { - return materials_; - } - - material_asset::ptr spine_player::find_material(str_hash name) const noexcept { - const auto iter = materials_.find(name); - return iter != materials_.end() - ? iter->second - : nullptr; - } -} - -namespace e2d -{ - const char* factory_loader::schema_source = R"json({ - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "spine" : { "$ref": "#/common_definitions/address" }, - "materials" : { "$ref": "#/definitions/materials" }, - "skin" : { "$ref": "#/common_definitions/name" }, - "attachments" : { "$ref": "#/definitions/attachments" } - }, - "definitions" : { - "materials" : { - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "normal" : { "$ref": "#/common_definitions/address" }, - "additive" : { "$ref": "#/common_definitions/address" }, - "multiply" : { "$ref": "#/common_definitions/address" }, - "screen" : { "$ref": "#/common_definitions/address" } - } - }, - "attachments" : { - "type" : "array", - "items" : { "$ref": "#/definitions/attachment" } - }, - "attachment" : { - "type" : "object", - "required" : [ "slot", "name" ], - "additionalProperties" : false, - "properties" : { - "slot" : { "$ref": "#/common_definitions/name" }, - "name" : { "$ref": "#/common_definitions/name" } - } - } - } - })json"; - - bool factory_loader::operator()( - spine_player& component, - const fill_context& ctx) const - { - if ( ctx.root.HasMember("spine") ) { - auto spine = ctx.dependencies.find_asset( - path::combine(ctx.parent_address, ctx.root["spine"].GetString())); - if ( !spine ) { - the().error("SPINE_PLAYER: Dependency 'spine' is not found:\n" - "--> Parent address: %0\n" - "--> Dependency address: %1", - ctx.parent_address, - ctx.root["spine"].GetString()); - return false; - } - component.spine(spine); - } - - if ( ctx.root.HasMember("materials") ) { - const rapidjson::Value& materials_root = ctx.root["materials"]; - flat_map materials; - materials.reserve(materials_root.MemberCount()); - for ( rapidjson::Value::ConstMemberIterator material_root = materials_root.MemberBegin(); - material_root != materials_root.MemberEnd(); - ++material_root ) - { - str_hash material_name; - if ( !json_utils::try_parse_value(material_root->name, material_name) ) { - the().error("SPINE_PLAYER: Incorrect formatting of 'material.name' property"); - return false; - } - - str material_address; - if ( !json_utils::try_parse_value(material_root->value, material_address) ) { - the().error("SPINE_PLAYER: Incorrect formatting of 'material.address' property"); - return false; - } - - auto material = ctx.dependencies.find_asset( - path::combine(ctx.parent_address, material_address)); - if ( !material ) { - the().error("SPINE_PLAYER: Dependency 'material' is not found:\n" - "--> Parent address: %0\n" - "--> Dependency address: %1", - ctx.parent_address, - material_address); - return false; - } - materials.emplace(material_name, material); - } - component.materials(std::move(materials)); - } - - if ( ctx.root.HasMember("skin") ) { - str skin; - if ( !json_utils::try_parse_value(ctx.root["skin"], skin) ) { - the().error("SPINE_PLAYER: Incorrect formatting of 'skin' property"); - return false; - } - component.skin(skin); - } - - if ( ctx.root.HasMember("attachments") ) { - const auto& attachments_json = ctx.root["attachments"]; - E2D_ASSERT(attachments_json.IsArray()); - - for ( rapidjson::SizeType i = 0; i < attachments_json.Size(); ++i ) { - E2D_ASSERT(attachments_json[i].IsObject()); - const auto& attachment_json = attachments_json[i]; - - str slot; - E2D_ASSERT(attachment_json.HasMember("slot")); - if ( !json_utils::try_parse_value(attachment_json["slot"], slot) ) { - the().error("SPINE_PLAYER: Incorrect formatting of 'attachment.slot' property"); - return false; - } - - str name; - E2D_ASSERT(attachment_json.HasMember("name")); - if ( !json_utils::try_parse_value(attachment_json["name"], name) ) { - the().error("SPINE_PLAYER: Incorrect formatting of 'attachment.name' property"); - return false; - } - - component.attachment(slot, name); - } - } - - return true; - } - - bool factory_loader::operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const - { - if ( ctx.root.HasMember("spine") ) { - dependencies.add_dependency( - path::combine(ctx.parent_address, ctx.root["spine"].GetString())); - } - - if ( ctx.root.HasMember("materials") ) { - const rapidjson::Value& materials_root = ctx.root["materials"]; - for ( rapidjson::Value::ConstMemberIterator material_root = materials_root.MemberBegin(); - material_root != materials_root.MemberEnd(); - ++material_root ) - { - dependencies.add_dependency( - path::combine(ctx.parent_address, material_root->value.GetString())); - } - } - - return true; - } -} - -namespace e2d -{ - const char* factory_loader>::schema_source = R"json({ - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "events" : { "$ref": "#/definitions/events" } - }, - "definitions" : { - "events" : { - "type" : "array", - "items" : { "$ref": "#/definitions/event" } - }, - "event" : { - "type" : "object", - "required" : [ "type", "desc" ], - "additionalProperties" : false, - "properties" : { - "type" : { "$ref": "#/common_definitions/name" }, - "desc" : { - "anyOf" : [{ - "$ref" : "#/definitions/custom_evt" - }, { - "$ref" : "#/definitions/end" - }, { - "$ref" : "#/definitions/complete" - }] - } - } - }, - "custom_evt" : { - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "name" : { "type" : "string" }, - "int_value" : { "type" : "integer" }, - "float_value" : { "type" : "number" }, - "string_value" : { "type" : "string" } - } - }, - "end" : { - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "message" : { "type" : "string" } - } - }, - "complete" : { - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "message" : { "type" : "string" } - } - } - } - })json"; - - bool factory_loader>::operator()( - events& component, - const fill_context& ctx) const - { - if ( ctx.root.HasMember("events") ) { - auto evts = parse_events(ctx.root["events"]); - - if ( !evts ) { - return false; - } - - for ( auto& evt : *evts ) { - if ( evt.valueless_by_exception() ) { - return false; - } - } - - component.set(std::move(*evts)); - } - - return true; - } - - bool factory_loader>::operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const - { - E2D_UNUSED(dependencies, ctx); - return true; - } -} - -namespace e2d -{ - const char* factory_loader>::schema_source = R"json({ - "type" : "object", - "required" : [], - "additionalProperties" : false, - "properties" : { - "commands" : { "$ref": "#/definitions/commands" } - }, - "definitions" : { - "commands" : { - "type" : "array", - "items" : { "$ref": "#/definitions/command" } - }, - "command" : { - "type" : "object", - "required" : [ "type", "desc" ], - "additionalProperties" : false, - "properties" : { - "type" : { "$ref": "#/common_definitions/name" }, - "desc" : { - "anyOf" : [{ - "$ref" : "#/definitions/clear_track_cmd" - }, { - "$ref" : "#/definitions/set_anim_cmd" - }, { - "$ref" : "#/definitions/add_anim_cmd" - }, { - "$ref" : "#/definitions/set_empty_anim_cmd" - }, { - "$ref" : "#/definitions/add_empty_anim_cmd" - }] - } - } - }, - "clear_track_cmd" : { - "type" : "object", - "required" : [ "track" ], - "additionalProperties" : false, - "properties" : { - "track" : { "type" : "integer", "minimum" : 0 } - } - }, - "set_anim_cmd" : { - "type" : "object", - "required" : [ "track", "name" ], - "additionalProperties" : false, - "properties" : { - "track" : { "type" : "integer", "minimum" : 0 }, - "name" : { "$ref": "#/common_definitions/name" }, - "loop" : { "type" : "boolean" }, - "end_message" : { "type" : "string" }, - "complete_message" : { "type" : "string" } - } - }, - "add_anim_cmd" : { - "type" : "object", - "required" : [ "track", "name" ], - "additionalProperties" : false, - "properties" : { - "track" : { "type" : "integer", "minimum" : 0 }, - "name" : { "$ref": "#/common_definitions/name" }, - "loop" : { "type" : "boolean" }, - "delay" : { "type" : "number" }, - "end_message" : { "type" : "string" }, - "complete_message" : { "type" : "string" } - } - }, - "set_empty_anim_cmd" : { - "type" : "object", - "required" : [ "track" ], - "additionalProperties" : false, - "properties" : { - "track" : { "type" : "integer", "minimum" : 0 }, - "mix_duration" : { "type" : "number" }, - "end_message" : { "type" : "string" }, - "complete_message" : { "type" : "string" } - } - }, - "add_empty_anim_cmd" : { - "type" : "object", - "required" : [ "track" ], - "additionalProperties" : false, - "properties" : { - "track" : { "type" : "integer", "minimum" : 0 }, - "delay" : { "type" : "number" }, - "mix_duration" : { "type" : "number" }, - "end_message" : { "type" : "string" }, - "complete_message" : { "type" : "string" } - } - } - } - })json"; - - bool factory_loader>::operator()( - commands& component, - const fill_context& ctx) const - { - if ( ctx.root.HasMember("commands") ) { - auto cmds = parse_commands(ctx.root["commands"]); - - if ( !cmds ) { - return false; - } - - for ( auto& cmd : *cmds ) { - if ( cmd.valueless_by_exception() ) { - return false; - } - } - - component.set(std::move(*cmds)); - } - - return true; - } - - bool factory_loader>::operator()( - asset_dependencies& dependencies, - const collect_context& ctx) const - { - E2D_UNUSED(dependencies, ctx); - return true; - } -} - -namespace e2d -{ - const char* component_inspector::title = ICON_FA_PARAGRAPH " spine_player"; - - void component_inspector::operator()(gcomponent& c) const { - E2D_UNUSED(c); - ///TODO(BlackMat): add 'spine' inspector - ///TODO(BlackMat): add 'materials' inspector - } -} diff --git a/sources/enduro2d/high/resources/spine.cpp b/sources/enduro2d/high/resources/spine.cpp deleted file mode 100644 index a62aa04e..00000000 --- a/sources/enduro2d/high/resources/spine.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#include - -namespace e2d -{ - spine::spine(spine&& other) noexcept { - assign(std::move(other)); - } - - spine& spine::operator=(spine&& other) noexcept { - return assign(std::move(other)); - } - - spine::spine(const spine& other) { - assign(other); - } - - spine& spine::operator=(const spine& other) { - return assign(other); - } - - void spine::clear() noexcept { - atlas_.reset(); - skeleton_.reset(); - animation_.reset(); - } - - void spine::swap(spine& other) noexcept { - using std::swap; - swap(atlas_, other.atlas_); - swap(skeleton_, other.skeleton_); - swap(animation_, other.animation_); - } - - spine& spine::assign(spine&& other) noexcept { - if ( this != &other ) { - swap(other); - other.clear(); - } - return *this; - } - - spine& spine::assign(const spine& other) { - if ( this != &other ) { - spine m; - m.atlas_ = other.atlas_; - m.skeleton_ = other.skeleton_; - m.animation_ = other.animation_; - swap(m); - } - return *this; - } - - spine& spine::set_atlas(atlas_ptr atlas) { - atlas_ = std::move(atlas); - return *this; - } - - spine& spine::set_skeleton(skeleton_data_ptr skeleton) { - animation_data_ptr animation; - if ( skeleton ) { - animation.reset( - spAnimationStateData_create(skeleton.get()), - spAnimationStateData_dispose); - if ( !animation ) { - throw std::bad_alloc(); - } - } - skeleton_ = std::move(skeleton); - animation_ = std::move(animation); - return *this; - } - - spine& spine::set_default_mix(f32 duration) { - if ( !animation_ ) { - throw bad_spine_access(); - } - animation_->defaultMix = duration; - return *this; - } - - spine& spine::set_animation_mix( - const str& from, - const str& to, - f32 duration) - { - spAnimation* from_anim = animation_ - ? spSkeletonData_findAnimation(animation_->skeletonData, from.c_str()) - : nullptr; - - spAnimation* to_anim = animation_ - ? spSkeletonData_findAnimation(animation_->skeletonData, to.c_str()) - : nullptr; - - if ( !from_anim || !to_anim ) { - throw bad_spine_access(); - } - - spAnimationStateData_setMix(animation_.get(), from_anim, to_anim, duration); - return *this; - } - - const spine::atlas_ptr& spine::atlas() const noexcept { - return atlas_; - } - - const spine::skeleton_data_ptr& spine::skeleton() const noexcept { - return skeleton_; - } - - const spine::animation_data_ptr& spine::animation() const noexcept { - return animation_; - } -} - -namespace e2d -{ - void swap(spine& l, spine& r) noexcept { - l.swap(r); - } - - bool operator==(const spine& l, const spine& r) noexcept { - return l.atlas() == r.atlas() - && l.skeleton() == r.skeleton() - && l.animation() == r.animation(); - } - - bool operator!=(const spine& l, const spine& r) noexcept { - return !(l == r); - } -} diff --git a/sources/enduro2d/high/starter.cpp b/sources/enduro2d/high/starter.cpp index ffed5a7d..860f2a5a 100644 --- a/sources/enduro2d/high/starter.cpp +++ b/sources/enduro2d/high/starter.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -74,8 +72,6 @@ namespace .add_system()) .feature(ecs::feature() .add_system()) - .feature(ecs::feature() - .add_system()) .feature(ecs::feature() .add_system()) .feature(ecs::feature() @@ -198,9 +194,6 @@ namespace e2d .register_component("named") .register_component("renderer") .register_component("scene") - .register_component("spine_player") - .register_component>("spine_player.events") - .register_component>("spine_player.commands") .register_component("sprite_renderer") .register_component("touchable") .register_component>("touchable.events") @@ -225,9 +218,6 @@ namespace e2d .register_component("named") .register_component("renderer") .register_component("scene") - .register_component("spine_player") - //.register_component>("spine_player.events") - //.register_component>("spine_player.commands") .register_component("sprite_renderer") .register_component("touchable") //.register_component>("touchable.events") diff --git a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp index c64e7290..d70e3064 100644 --- a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp +++ b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp @@ -9,11 +9,8 @@ #include #include #include -#include #include -#include - namespace { using namespace e2d; @@ -103,10 +100,6 @@ namespace e2d::render_system_impl draw(model_m, *node_r, *mdl_r); } - if ( auto spn_p = gcomponent{owner} ) { - draw(model_m, *node_r, *spn_p); - } - if ( auto spr_r = gcomponent{owner} ) { draw(model_m, *node_r, *spr_r); } @@ -155,276 +148,6 @@ namespace e2d::render_system_impl } } - void drawer::context::draw( - const m4f& model_m, - const renderer& node_r, - const spine_player& spine_r) - { - //TODO(BlackMat): replace it to frame allocator - static thread_local std::vector temp_vertices(1000u, 0.f); - static thread_local std::vector batch_vertices(1000u); - - spSkeleton* skeleton = spine_r.skeleton().get(); - spSkeletonClipping* clipper = spine_r.clipper().get(); - - if ( !skeleton || !clipper ) { - return; - } - - if ( math::is_near_zero(skeleton->color.a) ) { - return; - } - - material_asset::ptr normal_mat_a; - material_asset::ptr additive_mat_a; - material_asset::ptr multiply_mat_a; - material_asset::ptr screen_mat_a; - - unsigned short quad_indices[6] = { 0, 1, 2, 2, 3, 0 }; - - DEFER([this, clipper](){ - property_cache_.clear(); - spSkeletonClipping_clipEnd2(clipper); - }); - - for ( int i = 0; i < skeleton->slotsCount; ++i ) { - spSlot* slot = skeleton->drawOrder[i]; - - auto slot_clipping_defer = defer_hpp::make_defer([clipper, slot](){ - spSkeletonClipping_clipEnd(clipper, slot); - }); - - spAttachment* attachment = slot->attachment; - if ( !attachment || math::is_near_zero(slot->color.a) ) { - continue; - } - - float* uvs = nullptr; - unsigned short* indices = nullptr; - int index_count = 0; - int vertex_count = 0; - const spAtlasPage* atlas_page = nullptr; - const spColor* attachment_color = nullptr; - - if ( attachment->type == SP_ATTACHMENT_REGION ) { - spRegionAttachment* region = reinterpret_cast(attachment); - - attachment_color = ®ion->color; - if ( math::is_near_zero(attachment_color->a) ) { - continue; - } - - { - vertex_count = 8; - if ( temp_vertices.size() < math::numeric_cast(vertex_count) ) { - temp_vertices.resize(math::max( - temp_vertices.size() * 2u, - math::numeric_cast(vertex_count))); - } - } - - spRegionAttachment_computeWorldVertices( - region, - slot->bone, - temp_vertices.data(), - 0, 2); - - uvs = region->uvs; - indices = quad_indices; - index_count = 6; - atlas_page = static_cast(region->rendererObject)->page; - } else if ( attachment->type == SP_ATTACHMENT_MESH ) { - spMeshAttachment* mesh = reinterpret_cast(attachment); - - attachment_color = &mesh->color; - if ( math::is_near_zero(attachment_color->a) ) { - continue; - } - - { - vertex_count = mesh->super.worldVerticesLength; - if ( temp_vertices.size() < math::numeric_cast(vertex_count) ) { - temp_vertices.resize(math::max( - temp_vertices.size() * 2u, - math::numeric_cast(vertex_count))); - } - } - - spVertexAttachment_computeWorldVertices( - &mesh->super, - slot, - 0, - mesh->super.worldVerticesLength, - temp_vertices.data(), - 0, 2); - - uvs = mesh->uvs; - indices = mesh->triangles; - index_count = mesh->trianglesCount; - atlas_page = static_cast(mesh->rendererObject)->page; - } else if ( attachment->type == SP_ATTACHMENT_CLIPPING ) { - spClippingAttachment* clip = reinterpret_cast(attachment); - spSkeletonClipping_clipStart(clipper, slot, clip); - slot_clipping_defer.dismiss(); - continue; - } else { - slot_clipping_defer.dismiss(); - continue; - } - - color32 vert_color = color32( - color(skeleton->color.r, skeleton->color.g, skeleton->color.b, skeleton->color.a) * - color(slot->color.r, slot->color.g, slot->color.b, slot->color.a) * - color(attachment_color->r, attachment_color->g, attachment_color->b, attachment_color->a)); - - texture_ptr tex_p; - const texture_asset* texture_asset_ptr = atlas_page - ? static_cast(atlas_page->rendererObject) - : nullptr; - if ( texture_asset_ptr ) { - tex_p = texture_asset_ptr->content(); - } - - render::sampler_min_filter tex_min_f = render::sampler_min_filter::linear; - if ( atlas_page ) { - switch ( atlas_page->minFilter ) { - case SP_ATLAS_NEAREST: - case SP_ATLAS_MIPMAP_NEAREST_LINEAR: - case SP_ATLAS_MIPMAP_NEAREST_NEAREST: - tex_min_f = render::sampler_min_filter::nearest; - break; - default: - tex_min_f = render::sampler_min_filter::linear; - break; - } - } - - render::sampler_mag_filter tex_mag_f = render::sampler_mag_filter::linear; - if ( atlas_page ) { - switch ( atlas_page->magFilter ) { - case SP_ATLAS_NEAREST: - case SP_ATLAS_MIPMAP_NEAREST_LINEAR: - case SP_ATLAS_MIPMAP_NEAREST_NEAREST: - tex_mag_f = render::sampler_mag_filter::nearest; - break; - default: - tex_mag_f = render::sampler_mag_filter::linear; - break; - } - } - - render::sampler_wrap tex_wrap_s = render::sampler_wrap::repeat; - if ( atlas_page ) { - switch ( atlas_page->uWrap ) { - case SP_ATLAS_MIRROREDREPEAT: - tex_wrap_s = render::sampler_wrap::mirror; - break; - case SP_ATLAS_CLAMPTOEDGE: - tex_wrap_s = render::sampler_wrap::clamp; - break; - case SP_ATLAS_REPEAT: - tex_wrap_s = render::sampler_wrap::repeat; - break; - default: - E2D_ASSERT_MSG(false, "unexpected wrap mode for slot"); - break; - } - } - - render::sampler_wrap tex_wrap_t = render::sampler_wrap::repeat; - if ( atlas_page ) { - switch ( atlas_page->vWrap ) { - case SP_ATLAS_MIRROREDREPEAT: - tex_wrap_t = render::sampler_wrap::mirror; - break; - case SP_ATLAS_CLAMPTOEDGE: - tex_wrap_t = render::sampler_wrap::clamp; - break; - case SP_ATLAS_REPEAT: - tex_wrap_t = render::sampler_wrap::repeat; - break; - default: - E2D_ASSERT_MSG(false, "unexpected wrap mode for slot"); - break; - } - } - - material_asset::ptr mat_a; - switch ( slot->data->blendMode ) { - case SP_BLEND_MODE_NORMAL: - mat_a = normal_mat_a - ? normal_mat_a - : (normal_mat_a = spine_r.find_material(normal_material_hash)); - break; - case SP_BLEND_MODE_ADDITIVE: - mat_a = additive_mat_a - ? additive_mat_a - : (additive_mat_a = spine_r.find_material(additive_material_hash)); - break; - case SP_BLEND_MODE_MULTIPLY: - mat_a = multiply_mat_a - ? multiply_mat_a - : (multiply_mat_a = spine_r.find_material(multiply_material_hash)); - break; - case SP_BLEND_MODE_SCREEN: - mat_a = screen_mat_a - ? screen_mat_a - : (screen_mat_a = spine_r.find_material(screen_material_hash)); - break; - default: - E2D_ASSERT_MSG(false, "unexpected blend mode for slot"); - break; - } - - if ( math::is_near_zero(vert_color.a) || !tex_p || !mat_a ) { - continue; - } - - const float* vertices = temp_vertices.data(); - if ( spSkeletonClipping_isClipping(clipper) ) { - spSkeletonClipping_clipTriangles( - clipper, - temp_vertices.data(), vertex_count, - indices, index_count, - uvs, - 2); - vertices = clipper->clippedVertices->items; - vertex_count = clipper->clippedVertices->size; - uvs = clipper->clippedUVs->items; - indices = clipper->clippedTriangles->items; - index_count = clipper->clippedTriangles->size; - } - - { - const std::size_t batch_vertex_count = vertex_count >> 1; - - if ( batch_vertices.size() < batch_vertex_count ) { - batch_vertices.resize(math::max(batch_vertices.size() * 2u, batch_vertex_count)); - } - - for ( std::size_t j = 0; j < batch_vertex_count; ++j ) { - batcher_type::vertex_type& vert = batch_vertices[j]; - vert.v = v3f(v4f(vertices[j * 2], vertices[j * 2 + 1], 0.f, 1.f) * model_m); - vert.t = v2f(uvs[j * 2], uvs[j * 2 + 1]); - vert.c = vert_color; - } - - property_cache_ - .sampler(texture_sampler_hash, render::sampler_state() - .texture(tex_p) - .filter(tex_min_f, tex_mag_f) - .wrap(tex_wrap_s, tex_wrap_t)) - .merge(node_r.properties()); - - batcher_.batch( - mat_a, - property_cache_, - indices, math::numeric_cast(index_count), - batch_vertices.data(), batch_vertex_count); - } - } - } - void drawer::context::draw( const m4f& model_m, const renderer& node_r, diff --git a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.hpp b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.hpp index 69801c8d..240ff887 100644 --- a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.hpp +++ b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.hpp @@ -51,11 +51,6 @@ namespace e2d::render_system_impl const m4f& model_m, const renderer& node_r, const sprite_renderer& spr_r); - - void draw( - const m4f& model_m, - const renderer& node_r, - const spine_player& spine_r); private: render& render_; batcher_type& batcher_; diff --git a/sources/enduro2d/high/systems/spine_system.cpp b/sources/enduro2d/high/systems/spine_system.cpp deleted file mode 100644 index db8e739a..00000000 --- a/sources/enduro2d/high/systems/spine_system.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -#include -#include -#include - -#include - -namespace -{ - using namespace e2d; - - struct entry_internal_state { - ecs::entity target; - str end_message; - str complete_message; - - entry_internal_state(ecs::entity target, str end_msg, str complete_msg) - : target(std::move(target)) - , end_message(std::move(end_msg)) - , complete_message(std::move(complete_msg)) {} - }; - - void entry_listener( - spAnimationState*, - spEventType type, - spTrackEntry* entry, - spEvent* event) - { - if ( !entry->userData ) { - return; - } - - entry_internal_state& entry_state = - *static_cast(entry->userData); - - if ( type == SP_ANIMATION_DISPOSE || !entry_state.target.valid() ) { - std::unique_ptr entry_internal(&entry_state); - entry->userData = nullptr; - return; - } - - if ( type == SP_ANIMATION_EVENT ) { - if ( !event || !event->data ) { - return; - } - entry_state.target - .ensure_component>() - .add(spine_player_events::custom_evt(event->data->name ? event->data->name : "") - .int_value(event->intValue) - .float_value(event->floatValue) - .string_value(event->stringValue ? event->stringValue : "")); - } else if ( type == SP_ANIMATION_END ) { - if ( entry_state.end_message.empty() ) { - return; - } - entry_state.target - .ensure_component>() - .add(spine_player_events::end_evt(entry_state.end_message)); - } else if ( type == SP_ANIMATION_COMPLETE ) { - if ( entry_state.complete_message.empty() ) { - return; - } - entry_state.target - .ensure_component>() - .add(spine_player_events::complete_evt(entry_state.complete_message)); - } - } - - class command_visitor final : private noncopyable { - public: - command_visitor( - ecs::entity target, - spSkeletonData& skeleton_data, - spAnimationState& animation_state) - : target_(std::move(target)) - , skeleton_data_(skeleton_data) - , animation_state_(animation_state) {} - - void operator()(const spine_player_commands::clear_track_cmd& cmd) const noexcept { - spAnimationState_clearTrack( - &animation_state_, - math::numeric_cast(cmd.track())); - } - - void operator()(const spine_player_commands::set_anim_cmd& cmd) const noexcept { - spAnimation* animation = spSkeletonData_findAnimation(&skeleton_data_, cmd.name().c_str()); - if ( !animation ) { - the().error("SPINE_POST_SYSTEM: animation '%0' is not found", cmd.name()); - return; - } - - auto entry_state = std::make_unique( - target_, - cmd.end_message(), - cmd.complete_message()); - - spTrackEntry* entry = spAnimationState_setAnimation( - &animation_state_, - math::numeric_cast(cmd.track()), - animation, - cmd.loop() ? 1 : 0); - - entry->listener = &entry_listener; - entry->userData = entry_state.release(); - } - - void operator()(const spine_player_commands::add_anim_cmd& cmd) const noexcept { - spAnimation* animation = spSkeletonData_findAnimation(&skeleton_data_, cmd.name().c_str()); - if ( !animation ) { - the().error("SPINE_POST_SYSTEM: animation '%0' is not found", cmd.name()); - return; - } - - auto entry_state = std::make_unique( - target_, - cmd.end_message(), - cmd.complete_message()); - - spTrackEntry* entry = spAnimationState_addAnimation( - &animation_state_, - math::numeric_cast(cmd.track()), - animation, - cmd.loop() ? 1 : 0, - cmd.delay()); - - entry->listener = &entry_listener; - entry->userData = entry_state.release(); - } - - void operator()(const spine_player_commands::set_empty_anim_cmd& cmd) const noexcept { - auto entry_state = std::make_unique( - target_, - cmd.end_message(), - cmd.complete_message()); - - spTrackEntry* entry = spAnimationState_setEmptyAnimation( - &animation_state_, - math::numeric_cast(cmd.track()), - cmd.mix_duration()); - - entry->listener = &entry_listener; - entry->userData = entry_state.release(); - } - - void operator()(const spine_player_commands::add_empty_anim_cmd& cmd) const noexcept { - auto entry_state = std::make_unique( - target_, - cmd.end_message(), - cmd.complete_message()); - - spTrackEntry* entry = spAnimationState_addEmptyAnimation( - &animation_state_, - math::numeric_cast(cmd.track()), - cmd.mix_duration(), - cmd.delay()); - - entry->listener = &entry_listener; - entry->userData = entry_state.release(); - } - private: - ecs::entity target_; - spSkeletonData& skeleton_data_; - spAnimationState& animation_state_; - }; - - void clear_events(ecs::registry& owner) { - owner.for_each_component>([ - ](const ecs::const_entity&, events& es) { - es.clear(); - }); - } - - void update_animations(f32 dt, ecs::registry& owner) { - owner.for_each_component([dt]( - const ecs::const_entity&, - spine_player& p) - { - spSkeleton* skeleton = p.skeleton().get(); - spAnimationState* anim_state = p.animation().get(); - - if ( !skeleton || !anim_state ) { - return; - } - - spSkeleton_update(skeleton, dt); - spAnimationState_update(anim_state, dt); - spAnimationState_apply(anim_state, skeleton); - spSkeleton_updateWorldTransform(skeleton); - }); - } - - void process_commands(ecs::registry& owner) { - owner.for_joined_components, spine_player>([]( - ecs::entity e, - const commands& cs, - spine_player& p) - { - spSkeleton* skeleton = p.skeleton().get(); - spAnimationState* animation_state = p.animation().get(); - - if ( !skeleton || !skeleton->data || !animation_state ) { - return; - } - - command_visitor v(e, *skeleton->data, *animation_state); - for ( const auto& cmd : cs.get() ) { - std::visit(v, cmd); - } - }); - } - - void clear_commands(ecs::registry& owner) { - owner.for_each_component>([ - ](const ecs::const_entity&, commands& cs) { - cs.clear(); - }); - } -} - -namespace e2d -{ - // - // internal_state - // - - class spine_system::internal_state final { - public: - internal_state() = default; - ~internal_state() noexcept = default; - - void process_update(f32 dt, ecs::registry& owner) { - process_commands(owner); - clear_commands(owner); - clear_events(owner); - update_animations(dt, owner); - } - }; - - // - // spine_system - // - - spine_system::spine_system() - : state_(new internal_state()) {} - - spine_system::~spine_system() noexcept { - spAnimationState_disposeStatics(); - } - - void spine_system::process( - ecs::registry& owner, - const ecs::after& trigger) - { - state_->process_update(trigger.event.dt, owner); - } -}