diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 107ae51d..6715c073 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -36,3 +36,4 @@ add_e2d_sample(02)
add_e2d_sample(03)
add_e2d_sample(04)
add_e2d_sample(05)
+add_e2d_sample(07)
diff --git a/samples/bin/library/raptor/export/raptor-pro.json b/samples/bin/library/raptor/export/raptor-pro.json
new file mode 100644
index 00000000..47afbe58
--- /dev/null
+++ b/samples/bin/library/raptor/export/raptor-pro.json
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c8d0e5057c92306900f39879e51642500b841825cedb47833bbfa129978b5757
+size 172896
diff --git a/samples/bin/library/raptor/export/raptor-pro.skel b/samples/bin/library/raptor/export/raptor-pro.skel
new file mode 100644
index 00000000..235f7aa0
--- /dev/null
+++ b/samples/bin/library/raptor/export/raptor-pro.skel
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83c00999f00c4ac395ba063291d02131fb2a8869cb6d8f4fd20bc15131d52d54
+size 63077
diff --git a/samples/bin/library/raptor/export/raptor.atlas b/samples/bin/library/raptor/export/raptor.atlas
new file mode 100644
index 00000000..09e4ce87
--- /dev/null
+++ b/samples/bin/library/raptor/export/raptor.atlas
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:19b38bacd3e0cb4b41df20d88d2097e9886745b535bf821004736f7ae7582736
+size 4224
diff --git a/samples/bin/library/raptor/export/raptor.png b/samples/bin/library/raptor/export/raptor.png
new file mode 100644
index 00000000..6e6a20d2
--- /dev/null
+++ b/samples/bin/library/raptor/export/raptor.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:879d84230024a1529ea994e7cd6416c5883f4b74b0d268b5e2dea1cbe2d00777
+size 480392
diff --git a/samples/bin/library/spine_material.json b/samples/bin/library/spine_material.json
new file mode 100644
index 00000000..ecaf4333
--- /dev/null
+++ b/samples/bin/library/spine_material.json
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b20bd767ea8ad744e3af8c4bd353f010e9f4d65f17c34b70a974baf117ff7ecb
+size 349
diff --git a/samples/bin/library/spine_raptor.json b/samples/bin/library/spine_raptor.json
new file mode 100644
index 00000000..fcd252a0
--- /dev/null
+++ b/samples/bin/library/spine_raptor.json
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5b2d2131b3fe0d761de597e316a9001f3fefc7c03c503ec9b2bac538543893e1
+size 131
diff --git a/samples/bin/library/spine_shader.frag b/samples/bin/library/spine_shader.frag
new file mode 100644
index 00000000..e0fff40b
--- /dev/null
+++ b/samples/bin/library/spine_shader.frag
@@ -0,0 +1,11 @@
+#version 120
+
+uniform sampler2D u_texture;
+
+varying vec4 v_tint;
+varying vec2 v_st;
+
+void main() {
+ vec2 st = vec2(v_st.s, v_st.t);
+ gl_FragColor = texture2D(u_texture, st) * v_tint;
+}
diff --git a/samples/bin/library/spine_shader.json b/samples/bin/library/spine_shader.json
new file mode 100644
index 00000000..b13c1dcf
--- /dev/null
+++ b/samples/bin/library/spine_shader.json
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aa42a9a09042744abe4f9ef1d50b190baef49e43ccd979ac99e491743d17dfec
+size 81
diff --git a/samples/bin/library/spine_shader.vert b/samples/bin/library/spine_shader.vert
new file mode 100644
index 00000000..edfe96a4
--- /dev/null
+++ b/samples/bin/library/spine_shader.vert
@@ -0,0 +1,16 @@
+#version 120
+
+uniform mat4 u_matrix_mvp;
+
+attribute vec3 a_vertex;
+attribute vec4 a_tint;
+attribute vec2 a_st;
+
+varying vec4 v_tint;
+varying vec2 v_st;
+
+void main() {
+ v_st = a_st;
+ v_tint = a_tint;
+ gl_Position = vec4(a_vertex, 1.0) * u_matrix_mvp;
+}
diff --git a/samples/sources/sample_07/sample_07.cpp b/samples/sources/sample_07/sample_07.cpp
new file mode 100644
index 00000000..b0a750e3
--- /dev/null
+++ b/samples/sources/sample_07/sample_07.cpp
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * This file is part of the "Enduro2D"
+ * For conditions of distribution and use, see copyright notice in LICENSE.md
+ * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
+ ******************************************************************************/
+
+#include "../common.hpp"
+using namespace e2d;
+
+namespace
+{
+ class game_system final : public ecs::system {
+ public:
+ void process(ecs::registry& owner) override {
+ E2D_UNUSED(owner);
+ const keyboard& k = the().keyboard();
+
+ if ( k.is_key_just_released(keyboard_key::f12) ) {
+ the().toggle_visible(!the().visible());
+ }
+
+ if ( k.is_key_just_released(keyboard_key::escape) ) {
+ the().set_should_close(true);
+ }
+
+ if ( k.is_key_pressed(keyboard_key::lsuper) && k.is_key_just_released(keyboard_key::enter) ) {
+ the().toggle_fullscreen(!the().fullscreen());
+ }
+ }
+ };
+
+ class camera_system final : public ecs::system {
+ public:
+ void process(ecs::registry& owner) override {
+ owner.for_joined_components(
+ [](const ecs::const_entity&, camera& cam){
+ if ( !cam.target() ) {
+ cam.viewport(
+ the().real_size());
+ cam.projection(math::make_orthogonal_lh_matrix4(
+ the().real_size().cast_to(), 0.f, 1000.f));
+ }
+ });
+ }
+ };
+
+ class game final : public starter::application {
+ public:
+ bool initialize() final {
+ return create_scene()
+ && create_camera()
+ && create_systems();
+ }
+ private:
+ bool create_scene() {
+ auto spine_res = the().load_asset("spine_raptor.json");
+ auto spine_mat = the().load_asset("spine_material.json");
+
+ if ( !spine_res || !spine_mat ) {
+ return false;
+ }
+
+ auto scene_i = the().instantiate();
+
+ scene_i->entity_filler()
+ .component()
+ .component(node::create(scene_i));
+
+ node_iptr scene_r = scene_i->get_component().get().node();
+
+ auto spine_i = the().instantiate();
+ spine_i->entity_filler()
+ .component(node::create(spine_i, scene_r))
+ .component(renderer()
+ .materials({spine_mat}))
+ .component(spine_renderer(spine_res))
+ .component(spine_player(spine_res)
+ .set_animation(0, "walk", true)
+ .add_animation(1, "gun-grab", false, secf(2.0f)));
+
+ node_iptr spine_n = spine_i->get_component().get().node();
+ spine_n->scale(v3f(0.25f));
+ spine_n->translation(v3f{-40.f, -100.f, 0.0f});
+ return true;
+ }
+
+ bool create_camera() {
+ auto camera_i = the().instantiate();
+ camera_i->entity_filler()
+ .component(camera()
+ .background({1.f, 0.4f, 0.f, 1.f}))
+ .component(node::create(camera_i));
+ return true;
+ }
+
+ bool create_systems() {
+ ecs::registry_filler(the().registry())
+ .system(world::priority_update)
+ .system(world::priority_pre_render);
+ return true;
+ }
+ };
+}
+
+int e2d_main(int argc, char *argv[]) {
+ const auto starter_params = starter::parameters(
+ engine::parameters("sample_07", "enduro2d")
+ .timer_params(engine::timer_parameters()
+ .maximal_framerate(100)));
+ modules::initialize(argc, argv, starter_params).start();
+ modules::shutdown();
+ return 0;
+}
diff --git a/sources/enduro2d/high/assets/spine_model_asset.cpp b/sources/enduro2d/high/assets/spine_model_asset.cpp
index 473ab5d3..9d141386 100644
--- a/sources/enduro2d/high/assets/spine_model_asset.cpp
+++ b/sources/enduro2d/high/assets/spine_model_asset.cpp
@@ -29,6 +29,7 @@ namespace
"additionalProperties" : false,
"properties" : {
"skeleton" : { "$ref" : "#/common_definitions/address" },
+ "scale" : { "type" : "number" },
"atlas" : { "$ref" : "#/common_definitions/address" },
"premultiplied_alpha" : { "type" : "boolean" },
"mix_animations" : {
@@ -127,15 +128,22 @@ namespace
nullptr),
spAtlas_dispose);
+ float skeleton_scale = 1.0f;
+ if ( root.HasMember("scale") ) {
+ if ( !json_utils::try_parse_value(root["scale"], skeleton_scale) ) {
+ the().error("SPINE: Incorrect formating of 'scale' property");
+ }
+ }
+
+ skeleton_json_ptr skeleton_json(spSkeletonJson_create(atlas.get()), spSkeletonJson_dispose);
+ skeleton_json->scale = skeleton_scale;
+
E2D_ASSERT(root.HasMember("skeleton") && root["skeleton"].IsString());
binary_asset::load_result skeleton_data = library.load_asset(
path::combine(parent_address, root["skeleton"].GetString()));
- skeleton_json_ptr json(
- spSkeletonJson_create(atlas.get()),
- spSkeletonJson_dispose);
spine_model::skeleton_data_ptr skeleton(
spSkeletonJson_readSkeletonData(
- json.get(),
+ skeleton_json.get(),
reinterpret_cast(skeleton_data->content().data())),
spSkeletonData_dispose);
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 37bf923d..2c8459eb 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
@@ -26,6 +26,7 @@ namespace
const str_hash matrix_v_property_hash = "u_matrix_v";
const str_hash matrix_p_property_hash = "u_matrix_p";
const str_hash matrix_vp_property_hash = "u_matrix_vp";
+ const str_hash matrix_mvp_property_hash = "u_matrix_mvp";
const str_hash game_time_property_hash = "u_game_time";
const str_hash sprite_texture_sampler_hash = "u_texture";
}
@@ -52,15 +53,15 @@ namespace e2d::render_system_impl
: m4f::identity();
const std::pair cam_w_inv = math::inversed(cam_w);
- const m4f& m_v = cam_w_inv.second
+ view_mat_ = cam_w_inv.second
? cam_w_inv.first
: m4f::identity();
- const m4f& m_p = cam.projection();
+ proj_mat_ = cam.projection();
batcher_.flush()
- .property(matrix_v_property_hash, m_v)
- .property(matrix_p_property_hash, m_p)
- .property(matrix_vp_property_hash, m_v * m_p)
+ .property(matrix_v_property_hash, view_mat_)
+ .property(matrix_p_property_hash, proj_mat_)
+ .property(matrix_vp_property_hash, view_mat_ * proj_mat_)
.property(game_time_property_hash, engine.time());
render.execute(render::command_block<3>()
@@ -249,6 +250,7 @@ namespace e2d::render_system_impl
spSkeletonClipping* clipper = spine_r.clipper().operator->();
spVertexEffect* effect = spine_r.effect().operator->();
const material_asset::ptr& mat_a = node_r.materials().front();
+ const m4f& mvp = node->world_matrix() * view_mat_ * proj_mat_;
float dt = 0.01f;
if ( !skeleton || !clipper || !mat_a ) {
@@ -271,6 +273,7 @@ namespace e2d::render_system_impl
if ( effect ) {
effect->begin(effect, skeleton);
}
+
for ( int i = 0; i < skeleton->slotsCount; ++i ) {
spSlot* slot = skeleton->drawOrder[i];
@@ -381,6 +384,7 @@ namespace e2d::render_system_impl
.texture(texture)
.min_filter(render::sampler_min_filter::linear)
.mag_filter(render::sampler_mag_filter::linear))
+ .property(matrix_mvp_property_hash, mvp)
.merge(node_r.properties());
batcher_.batch(
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 05c82cff..6f584a4b 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
@@ -65,6 +65,8 @@ namespace e2d::render_system_impl
batcher_type& batcher_;
std::vector& spine_vertices_;
render::property_block property_cache_;
+ m4f view_mat_;
+ m4f proj_mat_;
};
public:
drawer(engine& e, debug& d, render& r);