Skip to content

Commit

Permalink
cleaning-up mouse events and exposing mouse input and new window meth…
Browse files Browse the repository at this point in the history
…ods to the Lua API
  • Loading branch information
aschuhardt committed Nov 29, 2021
1 parent e8476ee commit 795b1a9
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 58 deletions.
2 changes: 1 addition & 1 deletion include/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <stdbool.h>

#define COLOR_TO_INT(r, g, b) (b | g << 8 | r << 16)
#define COLOR_TO_INT(r, g, b) ((b) | (g) << 8 | (r) << 16)

typedef struct procy_color_t {
int value;
Expand Down
9 changes: 0 additions & 9 deletions include/mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ typedef enum procy_mouse_button_t {
MOUSE_BUTTON_MIDDLE = MOUSE_BUTTON_3
} procy_mouse_button_t;

typedef enum procy_mouse_mod_t {
MOUSE_MOD_NONE = 0,
MOUSE_MOD_SHIFT = 1,
MOUSE_MOD_CTRL = 1 << 1,
MOUSE_MOD_ALT = 1 << 2
} procy_mouse_mod_t;

procy_mouse_button_t procy_map_glfw_mouse_button(int button);

procy_mouse_mod_t procy_map_glfw_mouse_modifier(int mod);

#endif
1 change: 1 addition & 0 deletions include/procyon.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "color.h"
#include "drawing.h"
#include "keys.h"
#include "mouse.h"
#include "state.h"
#include "window.h"

Expand Down
5 changes: 2 additions & 3 deletions include/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

struct procy_state_t;
struct procy_key_info_t;
enum procy_mouse_mod_t;
enum procy_mouse_button_t;

typedef void (*procy_on_load_callback_t)(struct procy_state_t *);
Expand All @@ -24,10 +23,10 @@ typedef void (*procy_on_mouse_moved_callback_t)(struct procy_state_t *, double,
double);
typedef void (*procy_on_mouse_pressed_callback_t)(struct procy_state_t *,
enum procy_mouse_button_t,
enum procy_mouse_mod_t);
bool, bool, bool);
typedef void (*procy_on_mouse_released_callback_t)(struct procy_state_t *,
enum procy_mouse_button_t,
enum procy_mouse_mod_t);
bool, bool, bool);

typedef struct procy_state_t {
void *data;
Expand Down
5 changes: 5 additions & 0 deletions lua/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,8 @@ add_custom_target(script_test
COMMAND procyon-lua --debug -e "${CMAKE_CURRENT_SOURCE_DIR}/sample/test.lua"
DEPENDS procyon-lua copy_spritesheet_for_script_test
USES_TERMINAL)

add_custom_target(mouse_test
COMMAND procyon-lua --debug -e "${CMAKE_CURRENT_SOURCE_DIR}/sample/mouse.lua"
DEPENDS procyon-lua
USES_TERMINAL)
15 changes: 10 additions & 5 deletions lua/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ High-level objects are grouped into global tables that I refer to as "modules".
- `window.reload()` - Returns nothing. Causes the window and script environment to be disposed-of and reloaded (functionally "restarts" the app).
- `window.set_color(color)` - Returns nothing. Sets the "clear" color used for the window background.
- `window.set_high_fps(enabled)` - Returns nothing. Enables or enables "high-fps mode", in which the window will attempt to update with a frequency that matches the display refresh rate. Otherwise, when high-fps mode is disabled, the window only updates every full second or when input events are triggered.
- `window.set_fullscreen()` - Returns nothing. Switches from windowed mode to fullscreen.
- `window.set_windowed()` - Returns nothing. Switches from fullscreen mode to windowed.

#### Fields
- `window.on_draw` - If assigned, `on_draw` is called before each new frame is drawn. Perform any drawing routines here.
Expand Down Expand Up @@ -77,12 +79,11 @@ High-level objects are grouped into global tables that I refer to as "modules".
#### Fields
- `input.on_key_pressed` - If assigned, `on_key_pressed` is called when a key is pressed. It is passed a single argument, a table with the following fields:
- `value` - An integer indicating the scancode of the key that was entered. Comparable to the `KEY_...` global values.
- `name` - A string indicating the name of the key that was pressed. The same name is used as the names of the `KEY_...` global values.
- `ctrl`, `alt`, `shift` - Boolean flags indicating whether one of these modifier was pressed at the time the event was raised.
- `ctrl`, `alt`, `shift` - Boolean flags indicating whether one of these modifiers was pressed at the time the event was raised.
```lua
input.on_key_pressed = function(key)
if key.value == KEY_ESCAPE then
log.info(string.format('%s was pressed!', key.name))
log.info(string.format('Goodbye!'))
window.close()
end
end
Expand All @@ -91,7 +92,11 @@ end
- `input.on_key_released` - Same as `on_key_pressed` above, but called when a key is released.
- `input.on_char_entered` - If assigned, `on_char_entered` is called when the user enters text via the keyboard.
- `KEY_A ...` - Named key objects. See `script/keys.h` for a complete list.
- `keys[k].name`, `keys[k].value` - In addition to named objects, data pertaining to each key is stored in the `keys` table indexed by the key values themselves.
- `input.on_mouse_pressed` - If assigned, `on_mouse_pressed is called when a mouse button is pressed. It is passed a single argument, a table with the following fields:
- `value` - An integer representing the button that was pressed. One of `MOUSE_LEFT`, `MOUSE_RIGHT`, `MOUSE_MIDDLE`, or `MOUSE_[0,8]`.
- `ctrl`, `alt`, `shift` - Boolean flags indicating whether one of these modifiers was pressed at the time the event was raised.
- `input.on_mouse_released` - Same as `on_mouse_pressed` above, but called when the button is released.
- `input.on_mouse_moved` - If assigned, `on_mouse_moved` is called when the mouse has moved. It is passed two floating-point arguments, `x` and `y`, which represent the new position in screen coordinates of the mouse cursor.

---

Expand All @@ -109,7 +114,7 @@ Continuous noise is useful for all kinds of things.

### Plane

A plane is a 2D bitmap data structure. Elements in the plane consist of 8-bit integers, and are accessed by an (X, Y) index. Planes have a fixed width and height which are exposed to the developer.
A plane is a 2D bitmap data structure. Elements in the plane consist of byte values, and are accessed by an (X, Y) index. Planes have a fixed width and height which are exposed to the developer.

#### Functions
- `plane.from(w, h, value)` - Returns a new plane object with dimensions `w` and `h`, having each of its elements initialized to `value`. The dimensions are made accessible via the `width` and `height` fields in the resulting table.
Expand Down
23 changes: 23 additions & 0 deletions lua/sample/mouse.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
position = { x = 0, y = 0 }

window.on_draw = function()
draw.string(100, 100, string.format("Position: (%d, %d)", position.x, position.y))
draw.string(100, 200, "Click to change colors")
end

input.on_mouse_moved = function(x, y)
position.x = math.floor(x)
position.y = math.floor(y)
end

input.on_mouse_released = function(button)
if button.value == MOUSE_LEFT then
window.set_color(color.from_rgb(0.8, 0.3, 0.3))
else
window.set_color(color.from_rgb(0.1, 0.4, 0.8))
end
end

input.on_mouse_pressed = function(button)
window.set_color(color.from_rgb(0.4, 0.6, 0.5))
end
142 changes: 127 additions & 15 deletions lua/src/script/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@
#define FUNC_EVENTS_KEYPRESS "on_key_pressed"
#define FUNC_EVENTS_KEYRELEASE "on_key_released"
#define FUNC_EVENTS_CHAR "on_char_entered"
#define FUNC_EVENTS_MOUSE_MOVED "on_mouse_moved"
#define FUNC_EVENTS_MOUSE_PRESS "on_mouse_pressed"
#define FUNC_EVENTS_MOUSE_RELEASE "on_mouse_released"

#define FIELD_KEY_VALUE "value"
#define FIELD_KEY_NAME "name"
#define FIELD_KEY_CTRL "ctrl"
#define FIELD_KEY_SHIFT "shift"
#define FIELD_KEY_ALT "alt"

#define FIELD_MOUSE_VALUE "value"
#define FIELD_MOUSE_CTRL "ctrl"
#define FIELD_MOUSE_SHIFT "shift"
#define FIELD_MOUSE_ALT "alt"

#define CHAR_MAX_CODEPOINT 255

static void push_key_arg(lua_State *L, procy_key_info_t *key, bool shift,
Expand All @@ -26,9 +33,6 @@ static void push_key_arg(lua_State *L, procy_key_info_t *key, bool shift,
lua_pushinteger(L, key->value);
lua_setfield(L, -2, FIELD_KEY_VALUE);

lua_pushstring(L, key->name);
lua_setfield(L, -2, FIELD_KEY_NAME);

lua_pushboolean(L, shift);
lua_setfield(L, -2, FIELD_KEY_SHIFT);

Expand All @@ -39,8 +43,25 @@ static void push_key_arg(lua_State *L, procy_key_info_t *key, bool shift,
lua_setfield(L, -2, FIELD_KEY_ALT);
}

static void handle_key_pressed(procy_state_t *const state, procy_key_info_t key,
bool shift, bool ctrl, bool alt) {
static void push_mouse_button_arg(lua_State *L, procy_mouse_button_t button,
bool shift, bool ctrl, bool alt) {
lua_newtable(L);

lua_pushinteger(L, button);
lua_setfield(L, -2, FIELD_MOUSE_VALUE);

lua_pushboolean(L, shift);
lua_setfield(L, -2, FIELD_MOUSE_SHIFT);

lua_pushboolean(L, ctrl);
lua_setfield(L, -2, FIELD_MOUSE_CTRL);

lua_pushboolean(L, alt);
lua_setfield(L, -2, FIELD_MOUSE_ALT);
}

static void key_pressed(procy_state_t *state, procy_key_info_t key, bool shift,
bool ctrl, bool alt) {
lua_State *L = ((script_env_t *)state->data)->L;

lua_getglobal(L, TBL_INPUT);
Expand All @@ -56,9 +77,8 @@ static void handle_key_pressed(procy_state_t *const state, procy_key_info_t key,
lua_pop(L, lua_gettop(L));
}

static void handle_key_released(procy_state_t *const state,
procy_key_info_t key, bool shift, bool ctrl,
bool alt) {
static void key_released(procy_state_t *state, procy_key_info_t key, bool shift,
bool ctrl, bool alt) {
lua_State *L = ((script_env_t *)state->data)->L;

lua_getglobal(L, TBL_INPUT);
Expand All @@ -67,15 +87,14 @@ static void handle_key_released(procy_state_t *const state,
push_key_arg(L, &key, shift, ctrl, alt);
if (lua_pcall(L, 1, 0, 0) == LUA_ERRRUN) {
LOG_SCRIPT_ERROR(L, "Error calling %s.%s: %s", TBL_INPUT,
FUNC_EVENTS_KEYPRESS, lua_tostring(L, -1));
FUNC_EVENTS_KEYRELEASE, lua_tostring(L, -1));
}
}

lua_pop(L, lua_gettop(L));
}

static void handle_char_entered(procy_state_t *const state,
unsigned int codepoint) {
static void char_entered(procy_state_t *state, unsigned int codepoint) {
// for the time being we're using a font that only supports so-called
// "extended ASCII", up to value 255
if (codepoint > CHAR_MAX_CODEPOINT) {
Expand All @@ -100,6 +119,57 @@ static void handle_char_entered(procy_state_t *const state,
lua_pop(L, lua_gettop(L));
}

static void mouse_moved(procy_state_t *state, double x, double y) {
lua_State *L = ((script_env_t *)state->data)->L;

lua_getglobal(L, TBL_INPUT);
lua_getfield(L, -1, FUNC_EVENTS_MOUSE_MOVED);
if (lua_isfunction(L, -1)) {
lua_pushnumber(L, x);
lua_pushnumber(L, y);
if (lua_pcall(L, 2, 0, 0) == LUA_ERRRUN) {
LOG_SCRIPT_ERROR(L, "Error calling %s.%s: %s", TBL_INPUT,
FUNC_EVENTS_MOUSE_MOVED, lua_tostring(L, -1));
}
}

lua_pop(L, lua_gettop(L));
}

static void mouse_released(procy_state_t *state, procy_mouse_button_t button,
bool shift, bool ctrl, bool alt) {
lua_State *L = ((script_env_t *)state->data)->L;

lua_getglobal(L, TBL_INPUT);
lua_getfield(L, -1, FUNC_EVENTS_MOUSE_RELEASE);
if (lua_isfunction(L, -1)) {
push_mouse_button_arg(L, button, shift, ctrl, alt);
if (lua_pcall(L, 1, 0, 0) == LUA_ERRRUN) {
LOG_SCRIPT_ERROR(L, "Error calling %s.%s: %s", TBL_INPUT,
FUNC_EVENTS_MOUSE_RELEASE, lua_tostring(L, -1));
}
}

lua_pop(L, lua_gettop(L));
}

static void mouse_pressed(procy_state_t *state, procy_mouse_button_t button,
bool shift, bool ctrl, bool alt) {
lua_State *L = ((script_env_t *)state->data)->L;

lua_getglobal(L, TBL_INPUT);
lua_getfield(L, -1, FUNC_EVENTS_MOUSE_PRESS);
if (lua_isfunction(L, -1)) {
push_mouse_button_arg(L, button, shift, ctrl, alt);
if (lua_pcall(L, 1, 0, 0) == LUA_ERRRUN) {
LOG_SCRIPT_ERROR(L, "Error calling %s.%s: %s", TBL_INPUT,
FUNC_EVENTS_MOUSE_PRESS, lua_tostring(L, -1));
}
}

lua_pop(L, lua_gettop(L));
}

static void add_event_handler_table(lua_State *L) {
lua_newtable(L);
lua_setglobal(L, TBL_INPUT);
Expand All @@ -121,10 +191,52 @@ static void add_keys(lua_State *L) {
free(keys);
}

static void add_mouse_values(lua_State *L) {
lua_pushinteger(L, MOUSE_BUTTON_0);
lua_setglobal(L, "MOUSE_0");

lua_pushinteger(L, MOUSE_BUTTON_1);
lua_setglobal(L, "MOUSE_1");

lua_pushinteger(L, MOUSE_BUTTON_2);
lua_setglobal(L, "MOUSE_2");

lua_pushinteger(L, MOUSE_BUTTON_3);
lua_setglobal(L, "MOUSE_3");

lua_pushinteger(L, MOUSE_BUTTON_4);
lua_setglobal(L, "MOUSE_4");

lua_pushinteger(L, MOUSE_BUTTON_5);
lua_setglobal(L, "MOUSE_5");

lua_pushinteger(L, MOUSE_BUTTON_6);
lua_setglobal(L, "MOUSE_6");

lua_pushinteger(L, MOUSE_BUTTON_7);
lua_setglobal(L, "MOUSE_7");

lua_pushinteger(L, MOUSE_BUTTON_8);
lua_setglobal(L, "MOUSE_8");

lua_pushinteger(L, MOUSE_BUTTON_LEFT);
lua_setglobal(L, "MOUSE_LEFT");

lua_pushinteger(L, MOUSE_BUTTON_RIGHT);
lua_setglobal(L, "MOUSE_RIGHT");

lua_pushinteger(L, MOUSE_BUTTON_MIDDLE);
lua_setglobal(L, "MOUSE_MIDDLE");
}

void add_input(lua_State *L, script_env_t *env) {
add_event_handler_table(L);
add_keys(L);
env->state->on_key_pressed = handle_key_pressed;
env->state->on_key_released = handle_key_released;
env->state->on_char_entered = handle_char_entered;
add_mouse_values(L);
env->state->on_key_pressed = key_pressed;
env->state->on_key_released = key_released;
env->state->on_char_entered = char_entered;
env->state->on_mouse_moved = mouse_moved;
env->state->on_mouse_pressed = mouse_pressed;
env->state->on_mouse_released = mouse_released;
}
24 changes: 24 additions & 0 deletions lua/src/script/window.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "window.h"

#include <lauxlib.h>
#include <log.h>
#include <lua.h>
Expand All @@ -22,6 +24,8 @@
#define FUNC_SET_SCALE "set_scale"
#define FUNC_GET_SCALE "get_scale"
#define FUNC_RESET_SCALE "reset_scale"
#define FUNC_SET_FULLSCREEN "set_fullscreen"
#define FUNC_SET_WINDOWED "set_windowed"

static int close_window(lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, GLOBAL_WINDOW_PTR);
Expand Down Expand Up @@ -216,6 +220,24 @@ static int reset_window_scale(lua_State *L) {
return 0;
}

static int set_window_fullscreen(lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, GLOBAL_WINDOW_PTR);
procy_window_t *window = (procy_window_t *)lua_touserdata(L, -1);

procy_set_fullscreen(window);

return 0;
}

static int set_window_windowed(lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, GLOBAL_WINDOW_PTR);
procy_window_t *window = (procy_window_t *)lua_touserdata(L, -1);

procy_set_windowed(window);

return 0;
}

void add_window(lua_State *L, script_env_t *env) {
env->state->on_draw = perform_draw;
env->state->on_resize = handle_window_resized;
Expand All @@ -233,6 +255,8 @@ void add_window(lua_State *L, script_env_t *env) {
{FUNC_GET_SCALE, get_window_scale},
{FUNC_RESET_SCALE, reset_window_scale},
{FUNC_SET_TITLE, set_window_title},
{FUNC_SET_FULLSCREEN, set_window_fullscreen},
{FUNC_SET_WINDOWED, set_window_windowed},
{NULL, NULL}};
luaL_newlib(L, methods);
lua_setglobal(L, TBL_WINDOW);
Expand Down
4 changes: 0 additions & 4 deletions src/keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,6 @@ const key_info_t KEYS[] = {{"KEY_SPACE", KEY_SPACE},
{"KEY_RIGHT_SUPER", KEY_RIGHT_SUPER},
{"KEY_MENU", KEY_MENU}};

/* --------------------------- */
/* Public interface definition */
/* --------------------------- */

void procy_get_keys(key_info_t **buffer, size_t *len) {
*len = sizeof(KEYS) / sizeof(key_info_t);
*buffer = malloc(*len * sizeof(key_info_t));
Expand Down
Loading

0 comments on commit 795b1a9

Please sign in to comment.