return spine events and commands parsing

This commit is contained in:
2019-11-17 11:14:52 +07:00
parent a78cdaf72a
commit eed478f288
17 changed files with 857 additions and 121 deletions

View File

@@ -15,23 +15,14 @@ namespace e2d
public:
commands() = default;
[[nodiscard]]
typename vector<C>::const_iterator
begin() const noexcept;
[[nodiscard]]
typename vector<C>::const_iterator
cbegin() const noexcept;
[[nodiscard]]
typename vector<C>::const_iterator
end() const noexcept;
[[nodiscard]]
typename vector<C>::const_iterator
cend() const noexcept;
commands& add(C command);
commands& set(vector<C>&& commands) noexcept;
commands& set(const vector<C>& commands);
[[nodiscard]] vector<C>& get() noexcept;
[[nodiscard]] const vector<C>& get() const noexcept;
commands& clear() noexcept;
[[nodiscard]] bool empty() const noexcept;
[[nodiscard]] std::size_t size() const noexcept;
@@ -42,32 +33,34 @@ namespace e2d
namespace e2d
{
template < typename C >
typename vector<C>::const_iterator commands<C>::begin() const noexcept {
return commands_.begin();
}
template < typename C >
typename vector<C>::const_iterator commands<C>::cbegin() const noexcept {
return commands_.cbegin();
}
template < typename C >
typename vector<C>::const_iterator commands<C>::end() const noexcept {
return commands_.end();
}
template < typename C >
typename vector<C>::const_iterator commands<C>::cend() const noexcept {
return commands_.cend();
}
template < typename C >
commands<C>& commands<C>::add(C command) {
commands_.push_back(std::move(command));
return *this;
}
template < typename C >
commands<C>& commands<C>::set(vector<C>&& commands) noexcept {
commands_ = std::move(commands);
return *this;
}
template < typename C >
commands<C>& commands<C>::set(const vector<C>& commands) {
commands_ = commands;
return *this;
}
template < typename C >
vector<C>& commands<C>::get() noexcept {
return commands_;
}
template < typename C >
const vector<C>& commands<C>::get() const noexcept {
return commands_;
}
template < typename C >
commands<C>& commands<C>::clear() noexcept {
commands_.clear();

View File

@@ -15,23 +15,14 @@ namespace e2d
public:
events() = default;
[[nodiscard]]
typename vector<E>::const_iterator
begin() const noexcept;
[[nodiscard]]
typename vector<E>::const_iterator
cbegin() const noexcept;
[[nodiscard]]
typename vector<E>::const_iterator
end() const noexcept;
[[nodiscard]]
typename vector<E>::const_iterator
cend() const noexcept;
events& add(E event);
events& set(vector<E>&& events) noexcept;
events& set(const vector<E>& events);
[[nodiscard]] vector<E>& get() noexcept;
[[nodiscard]] const vector<E>& get() const noexcept;
events& clear() noexcept;
[[nodiscard]] bool empty() const noexcept;
[[nodiscard]] std::size_t size() const noexcept;
@@ -42,32 +33,34 @@ namespace e2d
namespace e2d
{
template < typename E >
typename vector<E>::const_iterator events<E>::begin() const noexcept {
return events_.begin();
}
template < typename E >
typename vector<E>::const_iterator events<E>::cbegin() const noexcept {
return events_.cbegin();
}
template < typename E >
typename vector<E>::const_iterator events<E>::end() const noexcept {
return events_.end();
}
template < typename E >
typename vector<E>::const_iterator events<E>::cend() const noexcept {
return events_.cend();
}
template < typename E >
events<E>& events<E>::add(E event) {
events_.push_back(std::move(event));
return *this;
}
template < typename E >
events<E>& events<E>::set(vector<E>&& events) noexcept {
events_ = std::move(events);
return *this;
}
template < typename E >
events<E>& events<E>::set(const vector<E>& events) {
events_ = events;
return *this;
}
template < typename E >
vector<E>& events<E>::get() noexcept {
return events_;
}
template < typename E >
const vector<E>& events<E>::get() const noexcept {
return events_;
}
template < typename E >
events<E>& events<E>::clear() noexcept {
events_.clear();

View File

@@ -16,6 +16,34 @@ 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 {
@@ -72,24 +100,50 @@ namespace e2d
asset_dependencies& dependencies,
const collect_context& ctx) const;
};
template <>
class factory_loader<events<spine_player_events::event>> final : factory_loader<> {
public:
static const char* schema_source;
bool operator()(
events<spine_player_events::event>& component,
const fill_context& ctx) const;
bool operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const;
};
template <>
class factory_loader<commands<spine_player_commands::command>> final : factory_loader<> {
public:
static const char* schema_source;
bool operator()(
commands<spine_player_commands::command>& component,
const fill_context& ctx) const;
bool operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const;
};
}
namespace e2d::spine_player_events
{
class custom_evt;
class end_evt;
class complete_evt;
using event = std::variant<
custom_evt,
end_evt,
complete_evt>;
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;
@@ -118,9 +172,16 @@ namespace e2d::spine_player_events
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_;
@@ -128,9 +189,16 @@ namespace e2d::spine_player_events
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_;
@@ -139,19 +207,6 @@ namespace e2d::spine_player_events
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>;
class clear_track_cmd final {
public:
clear_track_cmd(u32 track)

View File

@@ -3,6 +3,16 @@
"components" : {
"spine_player" : {
"spine" : "../spines/coin_spine.json"
},
"spine_player_commands" : {
"commands" : [{
"type" : "set_anim_cmd",
"desc" : {
"track" : 0,
"name" : "animation",
"loop" : true
}
}]
}
}
}

View File

@@ -3,6 +3,16 @@
"components" : {
"spine_player" : {
"spine" : "../spines/dragon_spine.json"
},
"spine_player_commands" : {
"commands" : [{
"type" : "set_anim_cmd",
"desc" : {
"track" : 0,
"name" : "flying",
"loop" : true
}
}]
}
}
}

View File

@@ -3,6 +3,42 @@
"components" : {
"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
}
}]
}
}
}

View File

@@ -8,6 +8,8 @@
"normal" : "../materials/spine_material_normal.json",
"screen" : "../materials/spine_material_screen.json"
}
}
},
"spine_player_events" : {},
"spine_player_commands" : {}
}
}

View File

@@ -56,9 +56,10 @@ spine_player.custom_evt = {
string_value = ""
}
---@param name string
---@overload fun(): spine_player_custom_evt
---@overload fun(name: string): spine_player_custom_evt
---@return spine_player_custom_evt
function spine_player.custom_evt.new(name) end
function spine_player.custom_evt.new(...) end
--
-- end_evt
@@ -70,12 +71,13 @@ spine_player.end_evt = {
message = ""
}
---@param message string
---@overload fun(): spine_player_end_evt
---@overload fun(message: string): spine_player_end_evt
---@return spine_player_end_evt
function spine_player.end_evt.new(message) end
function spine_player.end_evt.new(...) end
--
-- complete_evt
-- complete
--
---@class spine_player_complete_evt
@@ -84,9 +86,10 @@ spine_player.complete_evt = {
message = ""
}
---@param message string
---@overload fun(): spine_player_complete_evt
---@overload fun(message: string): spine_player_complete_evt
---@return spine_player_complete_evt
function spine_player.complete_evt.new(message) end
function spine_player.complete_evt.new(...) end
-- -----------------------------------------------------------------------------
--

View File

@@ -57,9 +57,9 @@ namespace
owner.for_joined_components<events<spine_player_events::event>>([
](ecs::entity e, const events<spine_player_events::event>& pe) {
for ( const auto& evt : pe ) {
if ( auto complete_evt = std::get_if<spine_player_events::complete_evt>(&evt);
complete_evt && complete_evt->message() == "to_walk" )
for ( const auto& evt : pe.get() ) {
if ( auto complete = std::get_if<spine_player_events::complete_evt>(&evt);
complete && complete->message() == "to_walk" )
{
e.ensure_component<commands<spine_player_commands::command>>()
.add(spine_player_commands::add_anim_cmd(0, "walk")

View File

@@ -3,5 +3,7 @@ SCRIPT_DIR=`dirname "$BASH_SOURCE"`
cloc \
$SCRIPT_DIR/../headers/enduro2d \
$SCRIPT_DIR/../sources/enduro2d \
$SCRIPT_DIR/../samples/bin \
$SCRIPT_DIR/../samples/sources \
$SCRIPT_DIR/../untests/bin \
$SCRIPT_DIR/../untests/sources

View File

@@ -1,3 +1,5 @@
#!/bin/bash
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
cloc $SCRIPT_DIR/../samples/sources
cloc \
$SCRIPT_DIR/../samples/bin \
$SCRIPT_DIR/../samples/sources

View File

@@ -1,3 +1,5 @@
#!/bin/bash
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
cloc $SCRIPT_DIR/../untests/sources
cloc \
$SCRIPT_DIR/../untests/bin \
$SCRIPT_DIR/../untests/sources

View File

@@ -58,12 +58,15 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_events::custom_evt>("custom_evt",
sol::constructors<
spine_player_events::custom_evt(),
spine_player_events::custom_evt(str)>(),
"name", sol::property(
[](const spine_player_events::custom_evt& c) -> str {
return c.name();
}),
},
sol::resolve<spine_player_events::custom_evt&(str)>(
&spine_player_events::custom_evt::name)),
"int_value", sol::property(
[](const spine_player_events::custom_evt& c) -> i32 {
@@ -90,23 +93,29 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_events::end_evt>("end_evt",
sol::constructors<
spine_player_events::end_evt(),
spine_player_events::end_evt(str)>(),
"message", sol::property(
[](const spine_player_events::end_evt& c) -> str {
return c.message();
})
},
sol::resolve<spine_player_events::end_evt&(str)>(
&spine_player_events::end_evt::message))
);
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_events::complete_evt>("complete_evt",
sol::constructors<
spine_player_events::complete_evt(),
spine_player_events::complete_evt(str)>(),
"message", sol::property(
[](const spine_player_events::complete_evt& c) -> str {
return c.message();
})
},
sol::resolve<spine_player_events::complete_evt&(str)>(
&spine_player_events::complete_evt::message))
);
//
@@ -115,8 +124,7 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_commands::clear_track_cmd>("clear_track_cmd",
sol::constructors<
spine_player_commands::clear_track_cmd(u32)>(),
sol::constructors<spine_player_commands::clear_track_cmd(u32)>(),
"track", sol::property(
[](const spine_player_commands::clear_track_cmd& c) -> u32 {
@@ -126,8 +134,7 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_commands::set_anim_cmd>("set_anim_cmd",
sol::constructors<
spine_player_commands::set_anim_cmd(u32,str)>(),
sol::constructors<spine_player_commands::set_anim_cmd(u32,str)>(),
"track", sol::property(
[](const spine_player_commands::set_anim_cmd& c) -> u32 {
@@ -163,8 +170,7 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_commands::add_anim_cmd>("add_anim_cmd",
sol::constructors<
spine_player_commands::add_anim_cmd(u32,str)>(),
sol::constructors<spine_player_commands::add_anim_cmd(u32,str)>(),
"track", sol::property(
[](const spine_player_commands::add_anim_cmd& c) -> u32 {
@@ -207,8 +213,7 @@ namespace e2d::bindings::high
l["spine_player"].get_or_create<sol::table>()
.new_usertype<spine_player_commands::set_empty_anim_cmd>("set_empty_anim_cmd",
sol::constructors<
spine_player_commands::set_empty_anim_cmd(u32)>(),
sol::constructors<spine_player_commands::set_empty_anim_cmd(u32)>(),
"track", sol::property(
[](const spine_player_commands::set_empty_anim_cmd& c) -> u32 {

View File

@@ -6,8 +6,407 @@
#include <enduro2d/high/components/spine_player.hpp>
#include <enduro2d/high/components/commands.hpp>
#include <enduro2d/high/components/events.hpp>
#include <spine/spine.h>
namespace
{
using namespace e2d;
std::optional<spine_player_events::custom_evt> 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<debug>().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<debug>().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<debug>().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<debug>().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<spine_player_events::end_evt> 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<debug>().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'end_evt.message' property");
return std::nullopt;
}
evt.message(std::move(evt_message));
}
return evt;
}
std::optional<spine_player_events::complete_evt> 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<debug>().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'complete_evt.message' property");
return std::nullopt;
}
evt.message(std::move(evt_message));
}
return evt;
}
std::optional<spine_player_events::event> 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<debug>().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<debug>().error("SPINE_PLAYER_EVENTS: Incorrect formatting of 'event.type' property");
return std::nullopt;
}
}
std::optional<vector<spine_player_events::event>> parse_events(const rapidjson::Value& root) {
E2D_ASSERT(root.IsArray());
vector<spine_player_events::event> 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<spine_player_commands::clear_track_cmd> 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<debug>().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<spine_player_commands::set_anim_cmd> 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<debug>().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<debug>().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<debug>().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<debug>().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<debug>().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<spine_player_commands::add_anim_cmd> 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<debug>().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<debug>().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<debug>().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<debug>().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<debug>().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<debug>().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<spine_player_commands::set_empty_anim_cmd> 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<debug>().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<debug>().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<debug>().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<debug>().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<spine_player_commands::add_empty_anim_cmd> 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<debug>().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<debug>().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<debug>().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<debug>().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<debug>().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<spine_player_commands::command> 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<debug>().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<debug>().error("SPINE_PLAYER_COMMANDS: Incorrect formatting of 'command.type' property");
return std::nullopt;
}
}
std::optional<vector<spine_player_commands::command>> parse_commands(const rapidjson::Value& root) {
E2D_ASSERT(root.IsArray());
vector<spine_player_commands::command> 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) {
@@ -107,7 +506,7 @@ namespace e2d
const spine_asset::ptr& spine_player::spine() const noexcept {
return spine_;
}
const spine_player::clipping_ptr& spine_player::clipper() const noexcept {
return clipping_;
}
@@ -291,3 +690,222 @@ namespace e2d
return true;
}
}
namespace e2d
{
const char* factory_loader<events<spine_player_events::event>>::schema_source = R"json({
"type" : "object",
"required" : [],
"additionalProperties" : false,
"properties" : {
"commands" : { "$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<events<spine_player_events::event>>::operator()(
events<spine_player_events::event>& 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<events<spine_player_events::event>>::operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const
{
E2D_UNUSED(dependencies, ctx);
return true;
}
}
namespace e2d
{
const char* factory_loader<commands<spine_player_commands::command>>::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<commands<spine_player_commands::command>>::operator()(
commands<spine_player_commands::command>& 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<commands<spine_player_commands::command>>::operator()(
asset_dependencies& dependencies,
const collect_context& ctx) const
{
E2D_UNUSED(dependencies, ctx);
return true;
}
}

View File

@@ -14,6 +14,9 @@
#include <enduro2d/high/components/actor.hpp>
#include <enduro2d/high/components/behaviour.hpp>
#include <enduro2d/high/components/camera.hpp>
#include <enduro2d/high/components/commands.hpp>
#include <enduro2d/high/components/disabled.hpp>
#include <enduro2d/high/components/events.hpp>
#include <enduro2d/high/components/flipbook_player.hpp>
#include <enduro2d/high/components/label.hpp>
#include <enduro2d/high/components/model_renderer.hpp>
@@ -186,6 +189,8 @@ namespace e2d
.register_component<renderer>("renderer")
.register_component<scene>("scene")
.register_component<spine_player>("spine_player")
.register_component<events<spine_player_events::event>>("spine_player_events")
.register_component<commands<spine_player_commands::command>>("spine_player_commands")
.register_component<sprite_renderer>("sprite_renderer");
safe_module_initialize<luasol>();

View File

@@ -51,7 +51,7 @@ namespace
if ( !a.node() || !a.node()->owner() ) {
return;
}
for ( const spine_player_events::event& evt : es ) {
for ( const spine_player_events::event& evt : es.get() ) {
behaviours::call_result r = behaviours::call_result::success;
std::visit(utils::overloaded {
[&b,&a,&r](const spine_player_events::custom_evt& e){

View File

@@ -210,7 +210,7 @@ namespace
}
command_visitor v(e, *skeleton->data, *animation_state);
for ( const auto& cmd : cs ) {
for ( const auto& cmd : cs.get() ) {
std::visit(v, cmd);
}
});