14#include <luabridge3/LuaBridge/LuaBridge.h>
19#include <toast/events/listener.hpp>
51 using Pusher = std::function<void(lua_State*)>;
52 using Callback = std::function<bool(
const Pusher&)>;
55 std::function<bool(lua_State*,
int, std::string&)> send;
62 static void registerBinding(std::shared_ptr<LuaEventBinding> binding);
64 static auto find(std::string_view name) -> std::shared_ptr<const LuaEventBinding>;
66 static auto descriptors() -> std::vector<LuaEventDescriptor>;
67 static void installDescriptors(lua_State* state);
70template<
typename Owner,
typename Get,
typename Set>
72 using value_type = std::remove_cvref_t<std::invoke_result_t<const Get&, const Owner&>>;
74 std::string_view name;
75 std::string_view type;
80template<
typename Owner,
typename Get,
typename Set>
82 return {name, type, std::move(get), std::move(set)};
85template<
typename Owner,
typename Member>
86constexpr auto luaEventField(std::string_view name, Member Owner::* member) {
87 return luaEventField<Owner>(
90 [member](
const Owner& owner) ->
const Member& {
return owner.*member; },
91 [member](Owner& owner, Member value) { owner.*member = std::move(value); }
96TOAST_API
auto readEventPrimitive(lua_State* state,
int index,
bool& out) -> bool;
97TOAST_API
auto readEventPrimitive(lua_State* state,
int index, int64_t& out) -> bool;
98TOAST_API
auto readEventPrimitive(lua_State* state,
int index,
double& out) -> bool;
99TOAST_API
auto readEventPrimitive(lua_State* state,
int index, std::string& out) -> bool;
100TOAST_API
auto readEventPrimitive(lua_State* state,
int index, toast::UID& out) -> bool;
101TOAST_API
auto readEventPrimitive(lua_State* state,
int index, toast::Box<toast::Node>& out) -> bool;
102TOAST_API
auto readEventPrimitive(lua_State* state,
int index, toast::Node*& out) -> bool;
103TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::vec2& out) -> bool;
104TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::vec3& out) -> bool;
105TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::vec4& out) -> bool;
106TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::ivec2& out) -> bool;
107TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::ivec3& out) -> bool;
108TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::ivec4& out) -> bool;
109TOAST_API
auto readEventPrimitive(lua_State* state,
int index, glm::quat& out) -> bool;
110TOAST_API
auto readEventHandle(lua_State* state,
int index, std::string_view type, assets::HandleBase& out) -> bool;
112TOAST_API
void pushEventPrimitive(lua_State* state,
bool value);
113TOAST_API
void pushEventPrimitive(lua_State* state, int64_t value);
114TOAST_API
void pushEventPrimitive(lua_State* state,
double value);
115TOAST_API
void pushEventPrimitive(lua_State* state, std::string_view value);
116TOAST_API
void pushEventPrimitive(lua_State* state, toast::UID value);
117TOAST_API
void pushEventPrimitive(lua_State* state,
const toast::Box<toast::Node>& value);
118TOAST_API
void pushEventPrimitive(lua_State* state,
const toast::Node* value);
119TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::vec2& value);
120TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::vec3& value);
121TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::vec4& value);
122TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::ivec2& value);
123TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::ivec3& value);
124TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::ivec4& value);
125TOAST_API
void pushEventPrimitive(lua_State* state,
const glm::quat& value);
126TOAST_API
void pushEventPrimitive(lua_State* state,
const assets::HandleBase& value);
127TOAST_API
void pushEventPrimitive(lua_State* state,
const input::Action& value);
128TOAST_API
void pushEventPrimitive(lua_State* state,
const physics::BroadPhasePair& value);
129TOAST_API
void pushEventPrimitive(lua_State* state,
const event::ContactEventData& value);
130TOAST_API
void pushEventTable(lua_State* state,
int field_count);
131TOAST_API
void setEventTableField(lua_State* state, std::string_view field);
133TOAST_API
auto pushEventField(lua_State* state,
int table, std::string_view field) -> int;
134TOAST_API
auto pushEventElement(lua_State* state,
int table, int64_t i) -> int;
135TOAST_API
void popEventValue(lua_State* state);
136TOAST_API
auto eventArrayLength(lua_State* state,
int index) -> int64_t;
137TOAST_API
void pushEventArray(lua_State* state,
size_t size);
138TOAST_API
void setEventArrayElement(lua_State* state, int64_t i);
141inline constexpr bool is_vector_v =
false;
142template<
typename T,
typename Alloc>
143inline constexpr bool is_vector_v<std::vector<T, Alloc>> =
true;
146inline constexpr bool is_handle_v =
false;
148inline constexpr bool is_handle_v<assets::Handle<T>> =
true;
151auto readEventIndex(lua_State* state,
int index, std::string_view type, T& out) ->
bool {
152 if constexpr (!std::same_as<T, bool> && (std::is_enum_v<T> || std::integral<T>)) {
154 if (!readEventPrimitive(state, index, value)) {
157 out =
static_cast<T
>(value);
159 }
else if constexpr (std::floating_point<T>) {
161 if (!readEventPrimitive(state, index, value)) {
164 out =
static_cast<T
>(value);
166 }
else if constexpr (is_vector_v<T>) {
167 const int64_t count = eventArrayLength(state, index);
172 out.reserve(
static_cast<size_t>(count));
173 for (int64_t i = 1; i <= count; ++i) {
174 typename T::value_type element {};
175 const bool ok = readEventIndex(state, pushEventElement(state, index, i), type, element);
176 popEventValue(state);
180 out.push_back(std::move(element));
183 }
else if constexpr (is_handle_v<T>) {
184 assets::HandleBase handle;
185 if (!readEventHandle(state, index, type, handle)) {
188 out = T(handle.hasValue() ? handle.operator->() :
nullptr, handle.uid(), handle.path());
191 return readEventPrimitive(state, index, out);
196auto readEventValue(lua_State* state,
int table, std::string_view field, std::string_view type, T& out, std::string& error)
198 const bool ok = readEventIndex(state, pushEventField(state, table, field), type, out);
199 popEventValue(state);
201 error =
"invalid or missing field '" + std::string(field) +
"'";
207void pushEventValue(lua_State* state,
const T& value) {
208 if constexpr (!std::same_as<T, bool> && (std::is_enum_v<T> || std::integral<T>)) {
209 pushEventPrimitive(state,
static_cast<int64_t
>(value));
210 }
else if constexpr (std::floating_point<T>) {
211 pushEventPrimitive(state,
static_cast<double>(value));
212 }
else if constexpr (std::same_as<T, std::string>) {
213 pushEventPrimitive(state, std::string_view(value));
214 }
else if constexpr (is_vector_v<T>) {
215 pushEventArray(state, value.size());
217 for (
const auto& element : value) {
218 pushEventValue<typename T::value_type>(state, element);
219 setEventArrayElement(state, ++i);
221 }
else if constexpr (is_handle_v<T>) {
222 pushEventPrimitive(state,
static_cast<const assets::HandleBase&
>(value));
224 pushEventPrimitive(state, value);
228template<
typename Event,
typename... Fields,
size_t... I>
229auto sendEvent(lua_State* state,
int payload, std::string& error,
const std::tuple<Fields...>& fields, std::index_sequence<I...>)
231 std::tuple<
typename Fields::value_type...> values;
233 (readEventValue(state, payload, std::get<I>(fields).name, std::get<I>(fields).type, std::get<I>(values), error) && ...);
237 if constexpr (std::is_constructible_v<Event, decltype(std::move(std::get<I>(values)))...>) {
238 std::apply([](
auto&&... args) { event::send<Event>(std::move(args)...); }, values);
241 (std::get<I>(fields).set(built, std::move(std::get<I>(values))), ...);
242 event::send<Event>(std::move(built));
247template<
typename Event,
typename... Fields,
size_t... I>
248void pushEvent(lua_State* state,
const Event& value,
const std::tuple<Fields...>& fields, std::index_sequence<I...>) {
249 pushEventTable(state,
static_cast<int>(
sizeof...(Fields)));
250 ((pushEventValue(state, std::get<I>(fields).get(value)), setEventTableField(state, std::get<I>(fields).name)), ...);
258template<
typename Event,
bool Sendable =
true,
typename... Fields>
260 if constexpr (Sendable) {
262 std::is_default_constructible_v<Event> || std::is_constructible_v<Event,
typename Fields::value_type...>,
263 "Lua events need a constructor taking the public fields in order, or a default constructor"
266 auto metadata = std::make_shared<std::tuple<Fields...>>(fields...);
267 auto binding = std::make_shared<LuaEventBinding>();
268 binding->name = name;
269 if constexpr (Sendable) {
270 binding->send = [metadata](lua_State* state,
int payload, std::string& error) {
271 return _detail::sendEvent<Event>(state, payload, error, *metadata, std::index_sequence_for<Fields...> {});
274 binding->subscribe = [metadata](
event::Listener& listener, std::string subscription_name, LuaEventBinding::Callback callback) {
275 listener.
subscribe<Event>(std::move(subscription_name), [metadata, callback = std::move(callback)](Event& value) {
276 return callback([metadata, &value](lua_State* state) {
277 _detail::pushEvent(state, value, *metadata, std::index_sequence_for<Fields...> {});
281 binding->unsubscribe = [](
event::Listener& listener, std::string_view subscription_name) {
284 LuaEventRegistry::registerBinding(std::move(binding));
289 ListenerProxy() =
default;
293 void subscribe(
const LuaEventDescriptor& descriptor,
const luabridge::LuaRef& callback, lua_State* state);
301void clearLuaEventSubscriptions(
void* runtime)
noexcept;
302void clearAllLuaEventSubscriptions() noexcept;
pseudo shared pointer for Nodes
manages the lifetime, subscription, and unsubscription of callbacks
Definition listener.hpp:39
void unsubscribe(std::string_view name) noexcept
unsubscribes every event in type TEvent with that name
Definition listener.inl:10
void subscribe(std::string name, F &&callback, char priority=0) noexcept
subscribes a callback to an TEvent
Definition listener.inl:24
Definition lua_event.hpp:60
Intrusive reference-counted handle to a Node.
Definition box.hpp:35
Base types for the asset system.
void registerLuaEvent(std::string_view name, Fields... fields)
Definition lua_event.hpp:259
Definition collision.hpp:24
Definition lua_event.hpp:50
Definition lua_event.hpp:46
Definition lua_event.hpp:71
Unique identifier for everything that exists in our engine.