add loading behaviour script asset

This commit is contained in:
2019-10-08 03:58:19 +07:00
parent ad37e6fe84
commit b9423484dc
10 changed files with 251 additions and 91 deletions

View File

@@ -9,6 +9,8 @@
#include "../core/_all.hpp"
#include <ecs.hpp/ecs.hpp>
#define SOL_ALL_SAFETIES_ON 1
#include <3rdparty/sol/sol.hpp>
namespace e2d

View File

@@ -9,12 +9,19 @@
#include "../_high.hpp"
#include "../factory.hpp"
#include "../assets/script_asset.hpp"
namespace e2d
{
class behaviour final {
public:
behaviour() = default;
behaviour(const script_asset::ptr& script);
behaviour& script(const script_asset::ptr& value) noexcept;
[[nodiscard]] const script_asset::ptr& script() const noexcept;
private:
script_asset::ptr script_;
};
template <>
@@ -31,3 +38,18 @@ namespace e2d
const collect_context& ctx) const;
};
}
namespace e2d
{
inline behaviour::behaviour(const script_asset::ptr& value)
: script_(value) {}
inline behaviour& behaviour::script(const script_asset::ptr& value) noexcept {
script_ = value;
return *this;
}
inline const script_asset::ptr& behaviour::script() const noexcept {
return script_;
}
}

View File

@@ -8,16 +8,38 @@
#include "_high.hpp"
#include "script.hpp"
namespace e2d
{
class luasol final : public module<luasol> {
public:
luasol();
~luasol() noexcept final;
~luasol() noexcept final = default;
sol::state& lua() noexcept;
const sol::state& lua() const noexcept;
template < typename F >
decltype(auto) with_state(F&& f);
template < typename F >
decltype(auto) with_state(F&& f) const;
std::optional<script> load_script(buffer_view src);
std::optional<script> load_script(const input_stream_uptr& src);
private:
sol::state lua_;
sol::state state_;
};
}
namespace e2d
{
template < typename F >
decltype(auto) luasol::with_state(F&& f) {
E2D_ASSERT(is_in_main_thread());
return std::invoke(std::forward<F>(f), state_);
}
template < typename F >
decltype(auto) luasol::with_state(F&& f) const {
E2D_ASSERT(is_in_main_thread());
return std::invoke(std::forward<F>(f), state_);
}
}

View File

@@ -10,6 +10,13 @@
namespace e2d
{
class bad_script_access final : public exception {
public:
const char* what() const noexcept final {
return "bad script access";
}
};
class script final {
public:
script() = default;
@@ -21,14 +28,35 @@ namespace e2d
script(const script& other);
script& operator=(const script& other);
void clear() noexcept;
void swap(script& other) noexcept;
script(sol::protected_function&& func) noexcept;
script(const sol::protected_function& func);
script& assign(script&& other) noexcept;
script& assign(const script& other);
script& assign(sol::protected_function&& func) noexcept;
script& assign(const sol::protected_function& func);
void clear() noexcept;
void swap(script& other) noexcept;
bool empty() const noexcept;
template < typename... Ret, typename... Args >
decltype(auto) call(Args&&... args) const;
private:
std::optional<sol::protected_function> func_;
};
void swap(script& l, script& r) noexcept;
bool operator==(const script& l, const script& r) noexcept;
bool operator!=(const script& l, const script& r) noexcept;
}
namespace e2d
{
template < typename... Ret, typename... Args >
decltype(auto) script::call(Args&&... args) const {
if ( !func_ ) {
throw bad_script_access();
}
return func_->call<Ret...>(std::forward<Args>(args)...);
}
}

View File

@@ -5,6 +5,8 @@
******************************************************************************/
#include <enduro2d/high/assets/script_asset.hpp>
#include <enduro2d/high/luasol.hpp>
#include <enduro2d/high/assets/binary_asset.hpp>
namespace
@@ -25,8 +27,14 @@ namespace e2d
{
return library.load_asset_async<binary_asset>(address)
.then([](const binary_asset::load_result& script_data){
script content;
return script_asset::create(std::move(content));
return the<deferrer>().do_in_main_thread([script_data](){
std::optional<script> script_opt = the<luasol>().load_script(
script_data->content());
if ( !script_opt ) {
throw script_asset_loading_exception();
}
return script_asset::create(std::move(*script_opt));
});
});
}
}

View File

@@ -12,14 +12,29 @@ namespace e2d
"type" : "object",
"required" : [],
"additionalProperties" : false,
"properties" : {}
"properties" : {
"script" : { "$ref": "#/common_definitions/address" }
}
})json";
bool factory_loader<behaviour>::operator()(
behaviour& component,
const fill_context& ctx) const
{
E2D_UNUSED(component, ctx);
if ( ctx.root.HasMember("script") ) {
auto script = ctx.dependencies.find_asset<script_asset>(
path::combine(ctx.parent_address, ctx.root["script"].GetString()));
if ( !script ) {
the<debug>().error("BEHAVIOUR: Dependency 'script' is not found:\n"
"--> Parent address: %0\n"
"--> Dependency address: %1",
ctx.parent_address,
ctx.root["script"].GetString());
return false;
}
component.script(script);
}
return true;
}
@@ -27,7 +42,11 @@ namespace e2d
asset_dependencies& dependencies,
const collect_context& ctx) const
{
E2D_UNUSED(dependencies, ctx);
if ( ctx.root.HasMember("script") ) {
dependencies.add_dependency<script_asset>(
path::combine(ctx.parent_address, ctx.root["script"].GetString()));
}
return true;
}
}

View File

@@ -11,7 +11,7 @@
namespace e2d
{
luasol::luasol() {
lua_.open_libraries(
state_.open_libraries(
sol::lib::base,
sol::lib::package,
sol::lib::coroutine,
@@ -19,20 +19,38 @@ namespace e2d
sol::lib::math,
sol::lib::table,
sol::lib::utf8);
bindings::bind_math(lua_);
bindings::bind_utils(lua_);
bindings::bind_core(lua_);
bindings::bind_high(lua_);
bindings::bind_math(state_);
bindings::bind_utils(state_);
bindings::bind_core(state_);
bindings::bind_high(state_);
}
luasol::~luasol() noexcept {
std::optional<script> luasol::load_script(buffer_view src) {
E2D_ASSERT(is_in_main_thread());
sol::load_result result = state_.load_buffer(
reinterpret_cast<const char*>(src.data()),
src.size());
if ( !result.valid() ) {
the<debug>().error("LUASOL: Failed to load script buffer:\n"
"--> Info: %0",
sol::error(result).what());
return std::nullopt;
}
sol::state& luasol::lua() noexcept {
return lua_;
return script(sol::protected_function(result));
}
const sol::state& luasol::lua() const noexcept {
return lua_;
std::optional<script> luasol::load_script(const input_stream_uptr& src) {
E2D_ASSERT(is_in_main_thread());
buffer file_data;
if ( !streams::try_read_tail(file_data, src) ) {
the<debug>().error("LUASOL: Failed to read script stream");
return std::nullopt;
}
return load_script(file_data);
}
}

View File

@@ -24,11 +24,12 @@ namespace e2d
return assign(other);
}
void script::clear() noexcept {
script::script(sol::protected_function&& func) noexcept {
assign(std::move(func));
}
void script::swap(script& other) noexcept {
using std::swap;
script::script(const sol::protected_function& func) {
assign(func);
}
script& script::assign(script&& other) noexcept {
@@ -41,11 +42,33 @@ namespace e2d
script& script::assign(const script& other) {
if ( this != &other ) {
script s;
swap(s);
func_ = other.func_;
}
return *this;
}
script& script::assign(sol::protected_function&& func) noexcept {
func_ = std::move(func);
return *this;
}
script& script::assign(const sol::protected_function& func) {
func_ = func;
return *this;
}
void script::clear() noexcept {
func_.reset();
}
void script::swap(script& other) noexcept {
using std::swap;
swap(func_, other.func_);
}
bool script::empty() const noexcept {
return !func_;
}
}
namespace e2d
@@ -53,12 +76,4 @@ namespace e2d
void swap(script& l, script& r) noexcept {
l.swap(r);
}
bool operator==(const script& l, const script& r) noexcept {
return true;
}
bool operator!=(const script& l, const script& r) noexcept {
return !(l == r);
}
}

View File

@@ -135,6 +135,7 @@ namespace e2d
starter::starter(int argc, char *argv[], const parameters& params) {
safe_module_initialize<engine>(argc, argv, params.engine_params());
safe_module_initialize<luasol>();
safe_module_initialize<factory>()
.register_component<actor>("actor")
.register_component<behaviour>("behaviour")
@@ -150,15 +151,14 @@ namespace e2d
.register_component<spine_player_evt>("spine_player_evt")
.register_component<sprite_renderer>("sprite_renderer");
safe_module_initialize<library>(params.library_root(), the<deferrer>());
safe_module_initialize<luasol>();
safe_module_initialize<world>();
}
starter::~starter() noexcept {
modules::shutdown<world>();
modules::shutdown<luasol>();
modules::shutdown<library>();
modules::shutdown<factory>();
modules::shutdown<luasol>();
modules::shutdown<engine>();
}

View File

@@ -29,46 +29,60 @@ TEST_CASE("luasol") {
luasol& l = the<luasol>();
SECTION("vec2/vec3/vec4") {
v2f r0 = l.lua().script(R"lua(
v2f r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local v = v2f.new(1,2)
return v2f.new((v + v + 2).y)
)lua");
v3f r1 = l.lua().script(R"lua(
});
v3f r1 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local v = v3f.new(1,2,3)
return v3f.new((v + v + 2).y)
)lua");
v4f r2 = l.lua().script(R"lua(
});
v4f r2 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local v = v4f.new(1,2,3,4)
return v4f.new((v + v + 2).y)
)lua");
});
REQUIRE(r0 == v2f(6));
REQUIRE(r1 == v3f(6));
REQUIRE(r2 == v4f(6));
}
SECTION("quat") {
v3f r0 = l.lua().script(R"lua(
v3f r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
return v3f.new(1,2,3) * q4f.make_quat_from_axis_angle(radf.new(10), v3f.new(1,2,3))
)lua");
});
REQUIRE(r0 == v3f(1,2,3) * math::make_quat_from_axis_angle(radf(10.f), v3f(1,2,3)));
}
SECTION("mat2/mat2/mat3") {
std::pair<m2f, bool> r0 = l.lua().script(R"lua(
std::pair<m2f, bool> r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local m = m2f.make_scale_matrix2(2,3)
local rm, s = m2f.inversed(m)
return rm * m2f.identity(), s
)lua");
std::pair<m3f, bool> r1 = l.lua().script(R"lua(
});
std::pair<m3f, bool> r1 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local m = m3f.make_rotation_matrix3(degf.new(45),2,3,4)
local rm, s = m3f.inversed(m)
return rm * m3f.identity(), s
)lua");
std::pair<m4f, bool> r2 = l.lua().script(R"lua(
});
std::pair<m4f, bool> r2 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local m = m4f.make_translation_matrix4(2,3,4)
local rm, s = m4f.inversed(m)
return rm * m4f.identity(), s
)lua");
});
REQUIRE(r0.second);
REQUIRE(r0.first == math::inversed(math::make_scale_matrix2(2.f,3.f)).first);
REQUIRE(r1.second);
@@ -78,39 +92,51 @@ TEST_CASE("luasol") {
}
SECTION("rect/aabb") {
bool r0 = l.lua().script(R"lua(
bool r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local b = b2f.unit() * 2
return b:inside(v2f.new(1.5,1.5))
)lua");
});
REQUIRE(r0);
bool r1 = l.lua().script(R"lua(
bool r1 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local b = b3f.unit() * 2
return b:overlaps(b3f.new(1.5,1.5,1.5,2,2,2))
)lua");
});
REQUIRE(r1);
}
SECTION("trs2/trs3") {
radf r0 = l.lua().script(R"lua(
radf r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local t = t2f.make_rotation_trs2(degf.new(45))
return t.rotation
)lua");
});
REQUIRE(r0 == math::to_rad(degf(45.f)));
v3f r1 = l.lua().script(R"lua(
v3f r1 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
local t = t3f.make_translation_trs3(v3f.new(1,2,3))
return t.translation
)lua");
});
REQUIRE(r1 == v3f(1,2,3));
}
SECTION("color/color32") {
color r0 = l.lua().script(R"lua(
color r0 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
return color.white() * 0.5
)lua");
});
REQUIRE(r0 == color(0.5f,0.5f,0.5f,0.5f));
color32 r1 = l.lua().script(R"lua(
color32 r1 = l.with_state([](sol::state& lua){
return lua.script(R"lua(
return color32.white() - 1
)lua");
});
REQUIRE(r1 == color32(254,254,254,254));
}
}