mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
Added love.event.addListener and removeListener.
addListener takes a function, and names of events that will trigger the function when they're processed inside love.event.poll or love.event.wait. When the given listener function is called, the name of the event as well as all of the event's arguments are passed to the function. If addListener is called multiple times with the same function and events, it will not add the function more than once. removeListener takes a function and removes it from all events it was previously added to.
This commit is contained in:
@@ -25,6 +25,11 @@
|
||||
|
||||
#include "sdl/Event.h"
|
||||
|
||||
// Put the Lua code directly into a raw string literal.
|
||||
static const char event_lua[] =
|
||||
#include "wrap_Event.lua"
|
||||
;
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace event
|
||||
@@ -32,55 +37,82 @@ namespace event
|
||||
|
||||
#define instance() (Module::getInstance<Event>(Module::M_EVENT))
|
||||
|
||||
static int poll_i(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
static const char *listenersKey = "_listeners";
|
||||
|
||||
while (instance()->poll(m))
|
||||
static int processMessage(lua_State *L, Message *m)
|
||||
{
|
||||
if (m == nullptr)
|
||||
return 0;
|
||||
|
||||
int args = m->toLua(L);
|
||||
|
||||
// Push the love.event[listenersKey][eventname] table onto the stack.
|
||||
lua_getfield(L, lua_upvalueindex(1), listenersKey);
|
||||
lua_getfield(L, -1, m->getName().c_str());
|
||||
|
||||
if (lua_istable(L, -1))
|
||||
{
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
return args;
|
||||
int len = (int) luax_objlen(L, -1);
|
||||
|
||||
// Each array entry in the table is a listener function we should call.
|
||||
for (int i = 1; i <= len; i++)
|
||||
{
|
||||
lua_rawgeti(L, -1, i);
|
||||
|
||||
// Push all message args (including the event name), in order.
|
||||
for (int j = 1; j <= args; j++)
|
||||
lua_pushvalue(L, -(args + 3));
|
||||
|
||||
lua_call(L, args, 0);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(L, 2);
|
||||
|
||||
m->release();
|
||||
|
||||
// Leave the message's args on the stack.
|
||||
return args;
|
||||
}
|
||||
|
||||
static int w_poll_i(lua_State *L)
|
||||
{
|
||||
Message *m = nullptr;
|
||||
|
||||
if (instance()->poll(m))
|
||||
return processMessage(L, m);
|
||||
|
||||
// No pending events.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_poll(lua_State *L)
|
||||
{
|
||||
// w_poll_i needs access to the love.event table via an upvalue.
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_pushcclosure(L, w_poll_i, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_pump(lua_State *)
|
||||
{
|
||||
instance()->pump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_poll(lua_State *L)
|
||||
{
|
||||
lua_pushcclosure(L, &poll_i, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_wait(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
|
||||
if ((m = instance()->wait()))
|
||||
{
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
return args;
|
||||
}
|
||||
|
||||
return 0;
|
||||
Message *m = instance()->wait();
|
||||
return processMessage(L, m);
|
||||
}
|
||||
|
||||
int w_push(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
Message *m = Message::fromLua(L, 1);
|
||||
|
||||
bool success = (m = Message::fromLua(L, 1)) != NULL;
|
||||
luax_pushboolean(L, success);
|
||||
luax_pushboolean(L, m != nullptr);
|
||||
|
||||
if (!success)
|
||||
if (m == nullptr)
|
||||
return 1;
|
||||
|
||||
instance()->push(m);
|
||||
@@ -117,6 +149,7 @@ int w_quit(lua_State *L)
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
// addListener and removeListener are defined in wrap_Event.lua
|
||||
{ "pump", w_pump },
|
||||
{ "poll", w_poll },
|
||||
{ "wait", w_wait },
|
||||
@@ -143,7 +176,19 @@ extern "C" int luaopen_love_event(lua_State *L)
|
||||
w.functions = functions;
|
||||
w.types = nullptr;
|
||||
|
||||
return luax_register_module(L, w);
|
||||
int ret = luax_register_module(L, w);
|
||||
|
||||
// love.event[listenersKey] = {}
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, listenersKey);
|
||||
|
||||
// Execute wrap_Event.lua, sending the event and listeners tables as args.
|
||||
luaL_loadbuffer(L, event_lua, sizeof(event_lua), "wrap_Event.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_getfield(L, -1, listenersKey);
|
||||
lua_call(L, 2, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // event
|
||||
|
||||
Reference in New Issue
Block a user