love.event can now handle any number of event arguments.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2015-02-15 21:31:22 -04:00
parent 7d2f1d74a4
commit c106d9ff53
6 changed files with 155 additions and 157 deletions
+27 -26
View File
@@ -28,56 +28,57 @@ namespace love
namespace event
{
Message::Message(const std::string &name, Variant *a, Variant *b, Variant *c, Variant *d)
Message::Message(const std::string &name, const std::vector<StrongRef<Variant>> &vargs)
: name(name)
, nargs(0)
, args(vargs)
{
args[0] = a;
args[1] = b;
args[2] = c;
args[3] = d;
for (int i = 0; i < 4; i++)
{
if (!args[i])
break;
args[i]->retain();
nargs++;
}
}
Message::~Message()
{
for (int i = 0; i < nargs; i++)
args[i]->release();
}
int Message::toLua(lua_State *L)
{
luax_pushstring(L, name);
for (int i = 0; i < nargs; i++)
args[i]->toLua(L);
return nargs+1;
for (const StrongRef<Variant> &v : args)
{
if (v.get() != nullptr)
v->toLua(L);
else
lua_pushnil(L);
}
return (int) args.size() + 1;
}
Message *Message::fromLua(lua_State *L, int n)
{
std::string name = luax_checkstring(L, n);
std::vector<StrongRef<Variant>> vargs;
int count = lua_gettop(L) - n;
n++;
Message *m = new Message(name);
for (int i = 0; i < 4; i++)
for (int i = 0; i < count; i++)
{
if (lua_isnoneornil(L, n+i))
break;
m->args[i] = Variant::fromLua(L, n+i);
if (!m->args[i])
vargs.push_back(Variant::fromLua(L, n+i));
if (!vargs.back().get())
{
delete m;
vargs.clear();
luaL_error(L, "Argument %d can't be stored safely\nExpected boolean, number, string or userdata.", n+i);
return NULL;
return nullptr;
}
m->nargs++;
vargs.back()->release(); // fromLua gave a +1 ref.
}
return m;
return new Message(name, vargs);
}
Event::Event()
+12 -8
View File
@@ -30,27 +30,31 @@
#include "joystick/Joystick.h"
#include "thread/threads.h"
// STL
// C++
#include <queue>
#include <vector>
namespace love
{
namespace event
{
class Message : public Object
{
private:
std::string name;
Variant *args[4];
int nargs;
public:
Message(const std::string &name, Variant *a = NULL, Variant *b = NULL, Variant *c = NULL, Variant *d = NULL);
Message(const std::string &name, const std::vector<StrongRef<Variant>> &vargs = {});
~Message();
int toLua(lua_State *L);
static Message *fromLua(lua_State *L, int n);
};
private:
std::string name;
std::vector<StrongRef<Variant>> args;
}; // Message
class Event : public Module
{
+98 -109
View File
@@ -108,14 +108,16 @@ void Event::clear()
Message *Event::convert(const SDL_Event &e) const
{
Message *msg = NULL;
Message *msg = nullptr;
std::vector<StrongRef<Variant>> vargs;
vargs.reserve(4);
love::keyboard::Keyboard *kb = nullptr;
love::filesystem::Filesystem *filesystem = nullptr;
love::keyboard::Keyboard::Key key;
love::mouse::Mouse::Button button;
Variant *arg1, *arg2, *arg3, *arg4;
const char *txt;
std::map<SDL_Keycode, love::keyboard::Keyboard::Key>::const_iterator keyit;
@@ -137,11 +139,9 @@ Message *Event::convert(const SDL_Event &e) const
if (!love::keyboard::Keyboard::getConstant(key, txt))
txt = "unknown";
arg1 = new Variant(txt, strlen(txt));
arg2 = new Variant(e.key.repeat != 0);
msg = new Message("keypressed", arg1, arg2);
arg1->release();
arg2->release();
vargs.push_back(new Variant(txt, strlen(txt)));
vargs.push_back(new Variant(e.key.repeat != 0));
msg = new Message("keypressed", vargs);
break;
case SDL_KEYUP:
keyit = keys.find(e.key.keysym.sym);
@@ -152,25 +152,20 @@ Message *Event::convert(const SDL_Event &e) const
if (!love::keyboard::Keyboard::getConstant(key, txt))
txt = "unknown";
arg1 = new Variant(txt, strlen(txt));
msg = new Message("keyreleased", arg1);
arg1->release();
vargs.push_back(new Variant(txt, strlen(txt)));
msg = new Message("keyreleased", vargs);
break;
case SDL_TEXTINPUT:
txt = e.text.text;
arg1 = new Variant(txt, strlen(txt));
msg = new Message("textinput", arg1);
arg1->release();
vargs.push_back(new Variant(txt, strlen(txt)));
msg = new Message("textinput", vargs);
break;
case SDL_TEXTEDITING:
txt = e.edit.text;
arg1 = new Variant(txt, strlen(txt));
arg2 = new Variant((double) e.edit.start);
arg3 = new Variant((double) e.edit.length);
msg = new Message("textedit", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
vargs.push_back(new Variant(txt, strlen(txt)));
vargs.push_back(new Variant((double) e.edit.start));
vargs.push_back(new Variant((double) e.edit.length));
msg = new Message("textedit", vargs);
break;
case SDL_MOUSEMOTION:
{
@@ -180,15 +175,11 @@ Message *Event::convert(const SDL_Event &e) const
double yrel = (double) e.motion.yrel;
windowToPixelCoords(&x, &y);
windowToPixelCoords(&xrel, &yrel);
arg1 = new Variant(x);
arg2 = new Variant(y);
arg3 = new Variant(xrel);
arg4 = new Variant(yrel);
msg = new Message("mousemoved", arg1, arg2, arg3, arg4);
arg1->release();
arg2->release();
arg3->release();
arg4->release();
vargs.push_back(new Variant(x));
vargs.push_back(new Variant(y));
vargs.push_back(new Variant(xrel));
vargs.push_back(new Variant(yrel));
msg = new Message("mousemoved", vargs);
}
break;
case SDL_MOUSEBUTTONDOWN:
@@ -198,23 +189,18 @@ Message *Event::convert(const SDL_Event &e) const
double x = (double) e.button.x;
double y = (double) e.button.y;
windowToPixelCoords(&x, &y);
arg1 = new Variant(x);
arg2 = new Variant(y);
arg3 = new Variant(txt, strlen(txt));
vargs.push_back(new Variant(x));
vargs.push_back(new Variant(y));
vargs.push_back(new Variant(txt, strlen(txt)));
msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
"mousepressed" : "mousereleased",
arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
vargs);
}
break;
case SDL_MOUSEWHEEL:
arg1 = new Variant((double) e.wheel.x);
arg2 = new Variant((double) e.wheel.y);
msg = new Message("wheelmoved", arg1, arg2);
arg1->release();
arg2->release();
vargs.push_back(new Variant((double) e.wheel.x));
vargs.push_back(new Variant((double) e.wheel.y));
msg = new Message("wheelmoved", vargs);
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
@@ -240,18 +226,16 @@ Message *Event::convert(const SDL_Event &e) const
if (filesystem->isRealDirectory(e.drop.file))
{
arg1 = new Variant(e.drop.file, strlen(e.drop.file));
msg = new Message("directorydropped", arg1);
arg1->release();
vargs.push_back(new Variant(e.drop.file, strlen(e.drop.file)));
msg = new Message("directorydropped", vargs);
}
else
{
Proxy proxy;
proxy.data = new love::filesystem::DroppedFile(e.drop.file);
proxy.flags = FILESYSTEM_DROPPED_FILE_T;
arg1 = new Variant(FILESYSTEM_DROPPED_FILE_ID, &proxy);
msg = new Message("filedropped", arg1);
arg1->release();
vargs.push_back(new Variant(FILESYSTEM_DROPPED_FILE_ID, &proxy));
msg = new Message("filedropped", vargs);
((Object *) proxy.data)->release();
}
}
@@ -264,6 +248,13 @@ Message *Event::convert(const SDL_Event &e) const
break;
}
// We gave +1 refs to the StrongRef list, so we should release them.
for (const StrongRef<Variant> &v : vargs)
{
if (v.get() != nullptr)
v->release();
}
return msg;
}
@@ -271,14 +262,17 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
{
joystick::JoystickModule *joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
if (!joymodule)
return 0;
return nullptr;
Message *msg = nullptr;
std::vector<StrongRef<Variant>> vargs;
vargs.reserve(4);
Message *msg = 0;
Proxy proxy;
love::joystick::Joystick::Hat hat;
love::joystick::Joystick::GamepadButton padbutton;
love::joystick::Joystick::GamepadAxis padaxis;
Variant *arg1, *arg2, *arg3;
const char *txt;
switch (e.type)
@@ -290,13 +284,11 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jbutton.button+1));
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
vargs.push_back(new Variant((double)(e.jbutton.button+1)));
msg = new Message((e.type == SDL_JOYBUTTONDOWN) ?
"joystickpressed" : "joystickreleased",
arg1, arg2);
arg1->release();
arg2->release();
vargs);
break;
case SDL_JOYAXISMOTION:
{
@@ -305,14 +297,11 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jaxis.axis+1));
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
vargs.push_back(new Variant((double)(e.jaxis.axis+1)));
float value = joystick::Joystick::clampval(e.jaxis.value / 32768.0f);
arg3 = new Variant((double) value);
msg = new Message("joystickaxis", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
vargs.push_back(new Variant((double) value));
msg = new Message("joystickaxis", vargs);
}
break;
case SDL_JOYHATMOTION:
@@ -324,13 +313,10 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jhat.hat+1));
arg3 = new Variant(txt, strlen(txt));
msg = new Message("joystickhat", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
vargs.push_back(new Variant((double)(e.jhat.hat+1)));
vargs.push_back(new Variant(txt, strlen(txt)));
msg = new Message("joystickhat", vargs);
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
@@ -345,12 +331,10 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant(txt, strlen(txt));
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
vargs.push_back(new Variant(txt, strlen(txt)));
msg = new Message(e.type == SDL_CONTROLLERBUTTONDOWN ?
"gamepadpressed" : "gamepadreleased", arg1, arg2);
arg1->release();
arg2->release();
"gamepadpressed" : "gamepadreleased", vargs);
break;
case SDL_CONTROLLERAXISMOTION:
if (joystick::sdl::Joystick::getConstant((SDL_GameControllerAxis) e.caxis.axis, padaxis))
@@ -363,15 +347,12 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
arg2 = new Variant(txt, strlen(txt));
vargs.push_back(new Variant(txt, strlen(txt)));
float value = joystick::Joystick::clampval(e.caxis.value / 32768.0f);
arg3 = new Variant((double) value);
msg = new Message("gamepadaxis", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
vargs.push_back(new Variant((double) value));
msg = new Message("gamepadaxis", vargs);
}
break;
case SDL_JOYDEVICEADDED:
@@ -380,9 +361,8 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
proxy.flags = JOYSTICK_JOYSTICK_T;
if (proxy.data)
{
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
msg = new Message("joystickadded", arg1);
arg1->release();
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
msg = new Message("joystickadded", vargs);
}
break;
case SDL_JOYDEVICEREMOVED:
@@ -392,26 +372,35 @@ Message *Event::convertJoystickEvent(const SDL_Event &e) const
if (proxy.data)
{
joymodule->removeJoystick((joystick::Joystick *) proxy.data);
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
msg = new Message("joystickremoved", arg1);
arg1->release();
vargs.push_back(new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy));
msg = new Message("joystickremoved", vargs);
}
break;
default:
break;
}
// We gave +1 refs to the StrongRef list, so we should release them.
for (const StrongRef<Variant> &v : vargs)
{
if (v.get() != nullptr)
v->release();
}
return msg;
}
Message *Event::convertWindowEvent(const SDL_Event &e) const
{
Message *msg = 0;
Variant *arg1, *arg2, *arg3, *arg4;
window::Window *win = 0;
Message *msg = nullptr;
std::vector<StrongRef<Variant>> vargs;
vargs.reserve(4);
window::Window *win = nullptr;
if (e.type != SDL_WINDOWEVENT)
return 0;
return nullptr;
switch (e.window.event)
{
@@ -423,21 +412,18 @@ Message *Event::convertWindowEvent(const SDL_Event &e) const
SDL_DisableScreenSaver();
else
SDL_EnableScreenSaver();
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
msg = new Message("focus", arg1);
arg1->release();
vargs.push_back(new Variant(e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED));
msg = new Message("focus", vargs);
break;
case SDL_WINDOWEVENT_ENTER:
case SDL_WINDOWEVENT_LEAVE:
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_ENTER);
msg = new Message("mousefocus", arg1);
arg1->release();
vargs.push_back(new Variant(e.window.event == SDL_WINDOWEVENT_ENTER));
msg = new Message("mousefocus", vargs);
break;
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_HIDDEN:
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_SHOWN);
msg = new Message("visible", arg1);
arg1->release();
vargs.push_back(new Variant(e.window.event == SDL_WINDOWEVENT_SHOWN));
msg = new Message("visible", vargs);
break;
case SDL_WINDOWEVENT_RESIZED:
win = Module::getInstance<window::Window>(Module::M_WINDOW);
@@ -459,19 +445,22 @@ Message *Event::convertWindowEvent(const SDL_Event &e) const
if (gfx)
gfx->setViewportSize(px_w, px_h);
arg1 = new Variant((double) px_w);
arg2 = new Variant((double) px_h);
arg3 = new Variant((double) e.window.data1);
arg4 = new Variant((double) e.window.data2);
msg = new Message("resize", arg1, arg2, arg3, arg4);
arg1->release();
arg2->release();
arg3->release();
arg4->release();
vargs.push_back(new Variant((double) px_w));
vargs.push_back(new Variant((double) px_h));
vargs.push_back(new Variant((double) e.window.data1));
vargs.push_back(new Variant((double) e.window.data2));
msg = new Message("resize", vargs);
}
break;
}
// We gave +1 refs to the StrongRef list, so we should release them.
for (const StrongRef<Variant> &v : vargs)
{
if (v.get() != nullptr)
v->release();
}
return msg;
}
+9 -5
View File
@@ -112,11 +112,15 @@ void LuaThread::onError()
p.flags = THREAD_THREAD_T;
p.data = this;
Variant *arg1 = new Variant(THREAD_THREAD_ID, &p);
Variant *arg2 = new Variant(error.c_str(), error.length());
event::Message *msg = new event::Message("threaderror", arg1, arg2);
arg1->release();
arg2->release();
std::vector<StrongRef<Variant>> vargs = {
new Variant(THREAD_THREAD_ID, &p),
new Variant(error.c_str(), error.length())
};
event::Message *msg = new event::Message("threaderror", vargs);
for (const StrongRef<Variant> &v : vargs)
v->release();
event->push(msg);
msg->release();