Added event.c/h and lua binding

* Changed mouse.c to mimic keyboard.c
* Changed boot.lua to use event.poll() instead of mouse/keyboard.poll()
* Removed love.keyboard.poll()
This commit is contained in:
rxi
2016-10-15 17:40:23 +01:00
parent d8210bfc35
commit a5c66d6154
9 changed files with 302 additions and 149 deletions

View File

@@ -13,6 +13,23 @@ function love.boot()
end
end)
-- Init event handlers table
local t = {
"mousepressed",
"mousereleased",
"mousemoved",
"keypressed",
"keyreleased",
"textinput",
}
love.handlers = {}
for i, name in ipairs(t) do
love.handlers[name] = function(...)
local fn = love[name]
if fn then fn(...) end
end
end
-- Try to mount .exe file, then the first argument
for i, v in ipairs { love.argv[1], love.argv[2] } do
local mounted = love.filesystem.mount(v)
@@ -48,25 +65,13 @@ function love.run()
love.timer.step()
while true do
-- Handle mouse events
for _, e in ipairs(love.mouse.poll()) do
if e.type == "motion" then
if love.mousemoved then love.mousemoved(e.x, e.y, e.dx, e.dy) end
elseif e.type == "pressed" then
if love.mousepressed then love.mousepressed(e.x, e.y, e.button) end
elseif e.type == "released" then
if love.mousereleased then love.mousereleased(e.x, e.y, e.button) end
end
end
-- Handle keyboard events
for _, e in ipairs(love.keyboard.poll()) do
if e.type == "down" then
if love.keypressed then love.keypressed(e.key, e.code, e.isrepeat) end
elseif e.type == "up" then
if love.keyreleased then love.keyreleased(e.key, e.code) end
elseif e.type == "text" then
if love.textinput then love.textinput(e.text) end
-- Handle events
while 1 do
local name, a,b,c,d = love.event.poll()
if not name then
break
end
love.handlers[name](a, b, c, d)
end
-- Update
love.timer.step()

76
src/event.c Normal file
View File

@@ -0,0 +1,76 @@
/**
* Copyright (c) 2016 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <stdio.h>
#include <string.h>
#include "keyboard.h"
#include "mouse.h"
#include "event.h"
const char* event_typestr(int type) {
switch (type) {
case EVENT_KEYBOARD_PRESSED : return "keypressed";
case EVENT_KEYBOARD_RELEASED : return "keyreleased";
case EVENT_KEYBOARD_TEXTINPUT : return "textinput";
case EVENT_MOUSE_MOVED : return "mousemoved";
case EVENT_MOUSE_PRESSED : return "mousepressed";
case EVENT_MOUSE_RELEASED : return "mousereleased";
}
return "?";
}
int event_poll(event_t *e) {
/* Poll keyboard */
keyboard_Event ke;
if (keyboard_poll(&ke)) {
if (ke.type == KEYBOARD_PRESSED || ke.type == KEYBOARD_RELEASED) {
if (ke.type == KEYBOARD_PRESSED) {
e->type = EVENT_KEYBOARD_PRESSED;
} else {
e->type = EVENT_KEYBOARD_RELEASED;
}
e->keyboard.key = ke.key;
e->keyboard.isrepeat = ke.isrepeat;
} else if (ke.type == KEYBOARD_TEXTINPUT) {
e->type = EVENT_KEYBOARD_TEXTINPUT;
strcpy(e->keyboard.text, ke.text);
}
return 1;
}
/* Poll mouse */
mouse_Event me;
if (mouse_poll(&me)) {
if (me.type == MOUSE_PRESSED || me.type == MOUSE_RELEASED) {
if (me.type == MOUSE_PRESSED) {
e->type = EVENT_MOUSE_PRESSED;
} else {
e->type = EVENT_MOUSE_RELEASED;
}
e->mouse.button = me.button;
e->mouse.x = me.x;
e->mouse.y = me.y;
e->mouse.dx = me.dx;
e->mouse.dy = me.dy;
} else if (me.type == MOUSE_MOVED) {
e->type = EVENT_MOUSE_MOVED;
e->mouse.x = me.x;
e->mouse.y = me.y;
}
return 1;
}
/* No events */
return 0;
}

44
src/event.h Normal file
View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2016 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#ifndef EVENT_H
#define EVENT_H
enum {
EVENT_NULL,
EVENT_KEYBOARD_PRESSED,
EVENT_KEYBOARD_RELEASED,
EVENT_KEYBOARD_TEXTINPUT,
EVENT_MOUSE_MOVED,
EVENT_MOUSE_PRESSED,
EVENT_MOUSE_RELEASED
};
typedef union {
int type;
struct {
int type;
int x, y;
int dx, dy;
int button;
} mouse;
struct {
int type;
const char *key;
char text[64];
int isrepeat;
} keyboard;
} event_t;
const char* event_typestr(int type);
int event_poll(event_t *e);
#endif

56
src/modules/l_event.c Normal file
View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2016 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include "luaobj.h"
#include "event.h"
int l_event_poll(lua_State *L) {
event_t e;
if (event_poll(&e)) {
lua_pushstring(L, event_typestr(e.type));
switch(e.type) {
case EVENT_KEYBOARD_PRESSED:
case EVENT_KEYBOARD_RELEASED:
lua_pushstring(L, e.keyboard.key);
lua_pushstring(L, e.keyboard.key);
lua_pushboolean(L, e.keyboard.isrepeat);
return 4;
case EVENT_KEYBOARD_TEXTINPUT:
lua_pushstring(L, e.keyboard.text);
return 2;
case EVENT_MOUSE_MOVED:
lua_pushnumber(L, e.mouse.x);
lua_pushnumber(L, e.mouse.y);
lua_pushnumber(L, e.mouse.dx);
lua_pushnumber(L, e.mouse.dy);
return 5;
case EVENT_MOUSE_PRESSED:
case EVENT_MOUSE_RELEASED:
lua_pushnumber(L, e.mouse.x);
lua_pushnumber(L, e.mouse.y);
lua_pushnumber(L, e.mouse.button);
return 4;
}
}
return 0;
}
int luaopen_event(lua_State *L) {
luaL_Reg reg[] = {
{ "poll", l_event_poll },
{ 0, 0 },
};
luaL_newlib(L, reg);
return 1;
}

View File

@@ -29,44 +29,8 @@ int l_keyboard_isDown(lua_State *L) {
}
int l_keyboard_poll(lua_State *L) {
lua_newtable(L);
keyboard_Event e;
int idx = 1;
while (keyboard_poll(&e)) {
if (e.type == KEYBOARD_PRESSED || e.type == KEYBOARD_RELEASED) {
lua_newtable(L);
lua_pushstring(L, e.type == KEYBOARD_PRESSED ? "down" : "up");
lua_setfield(L, -2, "type");
lua_pushnumber(L, e.code);
lua_setfield(L, -2, "code");
lua_pushstring(L, e.key);
lua_setfield(L, -2, "key");
if (e.type == KEYBOARD_PRESSED) {
lua_pushboolean(L, e.isrepeat);
lua_setfield(L, -2, "isrepeat");
}
lua_rawseti(L, -2, idx++);
} else if (e.type == KEYBOARD_TEXTINPUT) {
lua_newtable(L);
lua_pushstring(L, "text");
lua_setfield(L, -2, "type");
lua_pushstring(L, e.text);
lua_setfield(L, -2, "text");
lua_rawseti(L, -2, idx++);
}
}
return 1;
}
int luaopen_keyboard(lua_State *L) {
luaL_Reg reg[] = {
{ "poll", l_keyboard_poll },
{ "setKeyRepeat", l_keyboard_setKeyRepeat },
{ "isDown", l_keyboard_isDown },
{ 0, 0 },

View File

@@ -20,6 +20,7 @@ int luaopen_image(lua_State *L);
int luaopen_quad(lua_State *L);
int luaopen_font(lua_State *L);
int luaopen_system(lua_State *L);
int luaopen_event(lua_State *L);
int luaopen_filesystem(lua_State *L);
int luaopen_graphics(lua_State *L);
int luaopen_timer(lua_State *L);
@@ -52,6 +53,7 @@ int luaopen_love(lua_State *L) {
/* Init submodules */
struct { char *name; int (*fn)(lua_State *L); } mods[] = {
{ "system", luaopen_system },
{ "event", luaopen_event },
{ "filesystem", luaopen_filesystem },
{ "graphics", luaopen_graphics },
{ "timer", luaopen_timer },

View File

@@ -10,23 +10,20 @@
int l_mouse_getPosition(lua_State *L) {
mouse_State *state = mouse_getState();
lua_pushinteger(L, state->x);
lua_pushinteger(L, state->y);
lua_pushinteger(L, mouse_getX());
lua_pushinteger(L, mouse_getY());
return 2;
}
int l_mouse_getX(lua_State *L) {
mouse_State *state = mouse_getState();
lua_pushinteger(L, state->x);
lua_pushinteger(L, mouse_getX());
return 1;
}
int l_mouse_getY(lua_State *L) {
mouse_State *state = mouse_getState();
lua_pushinteger(L, state->y);
lua_pushinteger(L, mouse_getY());
return 1;
}
@@ -35,11 +32,10 @@ int l_mouse_isDown(lua_State *L) {
int n = lua_gettop(L);
int res = 0;
int i;
mouse_State *state = mouse_getState();
for (i = 1; i <= n; i++) {
int idx = luaL_checknumber(L, i) - 1;
if (idx >= 0 && idx < MOUSE_BUTTON_MAX) {
res |= state->buttonsDown[idx];
res |= mouse_isDown(idx);
}
}
lua_pushboolean(L, res);
@@ -47,53 +43,9 @@ int l_mouse_isDown(lua_State *L) {
}
int l_mouse_poll(lua_State *L) {
mouse_update();
mouse_State *state = mouse_getState();
int i;
int n = 1;
lua_newtable(L);
/* Add motion event if mouse moved */
if ( state->x != state->lastX || state->y != state->lastY ) {
lua_newtable(L);
lua_pushstring(L, "motion");
lua_setfield(L, -2, "type");
lua_pushinteger(L, state->x);
lua_setfield(L, -2, "x");
lua_pushinteger(L, state->y);
lua_setfield(L, -2, "y");
lua_pushinteger(L, state->x - state->lastX);
lua_setfield(L, -2, "dx");
lua_pushinteger(L, state->y - state->lastY);
lua_setfield(L, -2, "dy");
lua_rawseti(L, -2, n++);
}
/* Add `pressed` and `released` events */
for (i = 0; i < MOUSE_BUTTON_MAX; i++) {
if ( state->buttonsPressed[i] || state->buttonsReleased[i] ) {
lua_newtable(L);
lua_pushstring(L, state->buttonsPressed[i] ? "pressed" : "released");
lua_setfield(L, -2, "type");
lua_pushinteger(L, i + 1);
lua_setfield(L, -2, "button");
lua_pushinteger(L, state->x);
lua_setfield(L, -2, "x");
lua_pushinteger(L, state->y);
lua_setfield(L, -2, "y");
lua_rawseti(L, -2, n++);
}
}
return 1;
}
int luaopen_mouse(lua_State *L) {
luaL_Reg reg[] = {
{ "poll", l_mouse_poll },
{ "getPosition", l_mouse_getPosition },
{ "getX", l_mouse_getX },
{ "getY", l_mouse_getY },

View File

@@ -11,60 +11,107 @@
#include "luaobj.h"
#include "mouse.h"
mouse_State mouse_state;
#define BUFFER_SIZE 32
#define BUFFER_MASK (BUFFER_SIZE - 1)
int mouse_inited;
int mouse_x, mouse_y;
int mouse_lastX, mouse_lastY;
int mouse_buttonStates[MOUSE_BUTTON_MAX];
struct {
mouse_Event data[BUFFER_SIZE];
int writei, readi;
} mouse_events;
void mouse_init(void) {
union REGS regs = {};
int86(0x33, &regs, &regs);
mouse_state.inited = regs.x.ax ? 1 : 0;
mouse_inited = regs.x.ax ? 1 : 0;
}
void mouse_update(void) {
if (!mouse_state.inited) {
if (!mouse_inited) {
return;
}
/* Update last mouse position */
mouse_state.lastX = mouse_state.x;
mouse_state.lastY = mouse_state.y;
/* Update mouse position */
union REGS regs = {};
regs.x.ax = 3;
int86(0x33, &regs, &regs);
mouse_state.x = regs.x.cx >> 1;
mouse_state.y = regs.x.dx;
mouse_x = regs.x.cx >> 1;
mouse_y = regs.x.dx;
/* Update button states */
int i;
/* Do moved event if mouse moved */
if (mouse_x != mouse_lastX || mouse_y != mouse_lastY) {
mouse_Event e;
e.type = MOUSE_MOVED;
e.x = mouse_x;
e.y = mouse_y;
e.dx = mouse_x - mouse_lastX;
e.dy = mouse_y - mouse_lastY;
mouse_events.data[mouse_events.writei++ & BUFFER_MASK] = e;
}
/* Update last position */
mouse_lastX = mouse_x;
mouse_lastY = mouse_y;
/* Update button states and push pressed/released events */
int i, t;
for (i = 0; i < MOUSE_BUTTON_MAX; i++) {
/* Reset pressed/released */
mouse_state.buttonsPressed[i] = 0;
mouse_state.buttonsReleased[i] = 0;
/* Handle mouse pressed */
memset(&regs, 0, sizeof(regs));
regs.x.ax = 5;
regs.x.bx = i;
int86(0x33, &regs, &regs);
if (regs.x.bx) {
mouse_state.buttonsPressed[i] = 1;
mouse_state.buttonsDown[i] = 1;
}
/* Handle mouse released */
memset(&regs, 0, sizeof(regs));
regs.x.ax = 6;
regs.x.bx = i;
int86(0x33, &regs, &regs);
if (regs.x.bx) {
mouse_state.buttonsReleased[i] = 1;
mouse_state.buttonsDown[i] = 0;
for (t = 0; t < 2; t++) {
memset(&regs, 0, sizeof(regs));
regs.x.ax = 5 + t;
regs.x.bx = i;
int86(0x33, &regs, &regs);
if (regs.x.bx) {
/* Push event */
mouse_Event e;
e.type = t == 0 ? MOUSE_PRESSED : MOUSE_RELEASED;
e.button = i;
e.x = mouse_x;
e.y = mouse_y;
mouse_events.data[mouse_events.writei++ & BUFFER_MASK] = e;
/* Set state */
mouse_buttonStates[i] = t == 0 ? 1 : 0;
}
}
}
}
mouse_State* mouse_getState(void) {
return &mouse_state;
int mouse_poll(mouse_Event *e) {
retry:
/* Event in event buffer? Store and return */
if (mouse_events.readi != mouse_events.writei) {
*e = mouse_events.data[mouse_events.readi++ & BUFFER_MASK];
return 1;
}
/* No events in buffer -- update; return `0` if no new events were pushed by
* the update */
mouse_update();
if (mouse_events.readi != mouse_events.writei) {
goto retry;
}
return 0;
}
int mouse_isDown(int button) {
return mouse_buttonStates[button];
}
int mouse_getX(void) {
return mouse_x;
}
int mouse_getY(void) {
return mouse_y;
}

View File

@@ -5,20 +5,27 @@ enum {
MOUSE_BUTTON_LEFT,
MOUSE_BUTTON_RIGHT,
MOUSE_BUTTON_MIDDLE,
MOUSE_BUTTON_MAX,
MOUSE_BUTTON_MAX
};
enum {
MOUSE_PRESSED,
MOUSE_RELEASED,
MOUSE_MOVED
};
typedef struct {
int inited;
int type;
int x, y;
int lastX, lastY;
int buttonsPressed[MOUSE_BUTTON_MAX];
int buttonsReleased[MOUSE_BUTTON_MAX];
int buttonsDown[MOUSE_BUTTON_MAX];
} mouse_State;
int dx, dy;
int button;
} mouse_Event;
void mouse_init(void);
void mouse_update(void);
mouse_State* mouse_getState(void);
int mouse_poll(mouse_Event *e);
int mouse_isDown(int button);
int mouse_getX(void);
int mouse_getY(void);
#endif