This commit is contained in:
Federico Cecchetto 2022-04-25 22:41:02 +02:00
parent b117d4b787
commit 29b95f3625
11 changed files with 16 additions and 312 deletions

View File

@ -1,6 +1,5 @@
#pragma once
#include "game/ui_scripting/lua/value_conversion.hpp"
#include "game/ui_scripting/event.hpp"
namespace ui_scripting
{

View File

@ -1206,11 +1206,11 @@ namespace game
enum HksError
{
HKS_NO_ERROR = 0x0,
LUA_ERRSYNTAX = 0xFFFFFFFC,
LUA_ERRFILE = 0xFFFFFFFB,
LUA_ERRRUN = 0xFFFFFF9C,
LUA_ERRMEM = 0xFFFFFF38,
LUA_ERRERR = 0xFFFFFED4,
HKS_ERRSYNTAX = 0xFFFFFFFC,
HKS_ERRFILE = 0xFFFFFFFB,
HKS_ERRRUN = 0xFFFFFF9C,
HKS_ERRMEM = 0xFFFFFF38,
HKS_ERRERR = 0xFFFFFED4,
HKS_THROWING_ERROR = 0xFFFFFE0C,
HKS_GC_YIELD = 0x1,
};

View File

@ -1,11 +0,0 @@
#pragma once
#include "script_value.hpp"
namespace ui_scripting
{
struct event
{
std::string name;
arguments arguments;
};
}

View File

@ -40,7 +40,7 @@ namespace ui_scripting
bool notify(const std::string& name, const event_arguments& arguments)
{
const auto state = *game::hks::lua_state;
if (!state)
if (state == nullptr)
{
return false;
}

View File

@ -1,7 +1,5 @@
#pragma once
#include "../event.hpp"
#pragma warning(push)
#pragma warning(disable: 4702)
@ -10,7 +8,6 @@
#include <sol/sol.hpp>
#include "scheduler.hpp"
#include "event_handler.hpp"
namespace ui_scripting::lua
{
@ -33,7 +30,6 @@ namespace ui_scripting::lua
context& operator=(const context&) = delete;
void run_frame();
void notify(const event& e);
private:
sol::state state_{};

View File

@ -1,7 +1,5 @@
#pragma once
#include "../event.hpp"
namespace ui_scripting::lua::engine
{
void start();

View File

@ -1,175 +0,0 @@
#include "std_include.hpp"
#include "context.hpp"
#include "error.hpp"
#include "event_handler.hpp"
#include "value_conversion.hpp"
namespace ui_scripting::lua
{
event_handler::event_handler(sol::state& state)
: state_(state)
{
auto event_listener_handle_type = state.new_usertype<event_listener_handle>("event_listener_handle");
event_listener_handle_type["clear"] = [this](const event_listener_handle& handle)
{
this->remove(handle);
};
event_listener_handle_type["endon"] = [this](const event_listener_handle& handle, const std::string& event)
{
this->add_endon_condition(handle, event);
};
}
void event_handler::dispatch(const event& event)
{
bool has_built_arguments = false;
event_arguments arguments{};
callbacks_.access([&](task_list& tasks)
{
this->merge_callbacks();
this->handle_endon_conditions(event);
for (auto i = tasks.begin(); i != tasks.end();)
{
if (i->event != event.name)
{
++i;
continue;
}
if (!i->is_deleted)
{
if (!has_built_arguments)
{
has_built_arguments = true;
arguments = this->build_arguments(event);
}
handle_error(i->callback(sol::as_args(arguments)));
}
if (i->is_volatile || i->is_deleted)
{
i = tasks.erase(i);
}
else
{
++i;
}
}
});
}
event_listener_handle event_handler::add_event_listener(event_listener&& listener)
{
const uint64_t id = ++this->current_listener_id_;
listener.id = id;
listener.is_deleted = false;
new_callbacks_.access([&listener](task_list& tasks)
{
tasks.emplace_back(std::move(listener));
});
return {id};
}
void event_handler::add_endon_condition(const event_listener_handle& handle, const std::string& event)
{
auto merger = [&](task_list& tasks)
{
for (auto& task : tasks)
{
if (task.id == handle.id)
{
task.endon_conditions.emplace_back(event);
}
}
};
callbacks_.access([&](task_list& tasks)
{
merger(tasks);
new_callbacks_.access(merger);
});
}
void event_handler::clear()
{
callbacks_.access([&](task_list& tasks)
{
new_callbacks_.access([&](task_list& new_tasks)
{
new_tasks.clear();
tasks.clear();
});
});
}
void event_handler::remove(const event_listener_handle& handle)
{
auto mask_as_deleted = [&](task_list& tasks)
{
for (auto& task : tasks)
{
if (task.id == handle.id)
{
task.is_deleted = true;
break;
}
}
};
callbacks_.access(mask_as_deleted);
new_callbacks_.access(mask_as_deleted);
}
void event_handler::merge_callbacks()
{
callbacks_.access([&](task_list& tasks)
{
new_callbacks_.access([&](task_list& new_tasks)
{
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()),
std::move_iterator<task_list::iterator>(new_tasks.end()));
new_tasks = {};
});
});
}
void event_handler::handle_endon_conditions(const event& event)
{
auto deleter = [&](task_list& tasks)
{
for (auto& task : tasks)
{
for (auto& condition : task.endon_conditions)
{
if (condition == event.name)
{
task.is_deleted = true;
break;
}
}
}
};
callbacks_.access(deleter);
}
event_arguments event_handler::build_arguments(const event& event) const
{
event_arguments arguments;
for (const auto& argument : event.arguments)
{
arguments.emplace_back(convert(this->state_, argument));
}
return arguments;
}
}

View File

@ -1,58 +0,0 @@
#pragma once
#include <utils/concurrency.hpp>
namespace ui_scripting::lua
{
using event_arguments = std::vector<sol::lua_value>;
using event_callback = sol::protected_function;
class event_listener_handle
{
public:
uint64_t id = 0;
};
class event_listener final : public event_listener_handle
{
public:
std::string event = {};
event_callback callback = {};
bool is_volatile = false;
bool is_deleted = false;
std::vector<std::string> endon_conditions{};
};
class event_handler final
{
public:
event_handler(sol::state& state);
event_handler(event_handler&&) noexcept = delete;
event_handler& operator=(event_handler&&) noexcept = delete;
event_handler(const scheduler&) = delete;
event_handler& operator=(const event_handler&) = delete;
void dispatch(const event& event);
event_listener_handle add_event_listener(event_listener&& listener);
void clear();
private:
sol::state& state_;
std::atomic_int64_t current_listener_id_ = 0;
using task_list = std::vector<event_listener>;
utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
void remove(const event_listener_handle& handle);
void merge_callbacks();
void handle_endon_conditions(const event& event);
void add_endon_condition(const event_listener_handle& handle, const std::string& event);
event_arguments build_arguments(const event& event) const;
};
}

View File

@ -12,35 +12,6 @@ namespace ui_scripting::lua
{
this->remove(handle);
};
task_handle_type["endon"] = [this](const task_handle& handle, const std::string& event)
{
this->add_endon_condition(handle, event);
};
}
void scheduler::dispatch(const event& event)
{
auto deleter = [&](task_list& tasks)
{
for (auto& task : tasks)
{
for (auto& condition : task.endon_conditions)
{
if (condition == event.name)
{
task.is_deleted = true;
break;
}
}
}
};
callbacks_.access([&](task_list& tasks)
{
deleter(tasks);
new_callbacks_.access(deleter);
});
}
void scheduler::run_frame()
@ -118,26 +89,6 @@ namespace ui_scripting::lua
return {id};
}
void scheduler::add_endon_condition(const task_handle& handle, const std::string& event)
{
auto merger = [&](task_list& tasks)
{
for (auto& task : tasks)
{
if (task.id == handle.id)
{
task.endon_conditions.emplace_back(event);
}
}
};
callbacks_.access([&](task_list& tasks)
{
merger(tasks);
new_callbacks_.access(merger);
});
}
void scheduler::remove(const task_handle& handle)
{
auto mask_as_deleted = [&](task_list& tasks)

View File

@ -19,7 +19,6 @@ namespace ui_scripting::lua
std::chrono::milliseconds delay{};
bool is_volatile = false;
bool is_deleted = false;
std::vector<std::string> endon_conditions{};
};
class scheduler final
@ -33,7 +32,6 @@ namespace ui_scripting::lua
scheduler(const scheduler&) = delete;
scheduler& operator=(const scheduler&) = delete;
void dispatch(const event& event);
void run_frame();
void clear();
@ -46,8 +44,6 @@ namespace ui_scripting::lua
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
std::atomic_int64_t current_task_id_ = 0;
void add_endon_condition(const task_handle& handle, const std::string& event);
void remove(const task_handle& handle);
void merge_callbacks();
};

View File

@ -60,8 +60,12 @@ namespace ui_scripting
game::hks::HksObject obj{};
const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
if (state == nullptr)
{
return;
}
state->m_apistack.top = state->m_apistack.base;
game::hks::hksi_lua_pushlstring(state, value, static_cast<unsigned int>(strlen(value)));
obj = state->m_apistack.top[-1];
@ -73,8 +77,12 @@ namespace ui_scripting
game::hks::HksObject obj{};
const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
if (state == nullptr)
{
return;
}
state->m_apistack.top = state->m_apistack.base;
game::hks::hksi_lua_pushlstring(state, value, len);
obj = state->m_apistack.top[-1];