plartfgh
kjhjk
This commit is contained in:
parent
878fbdd934
commit
3767bfc036
168
source/io/ctrl.c
168
source/io/ctrl.c
|
@ -13,44 +13,60 @@
|
||||||
#define IO_BUF_SIZE 16
|
#define IO_BUF_SIZE 16
|
||||||
|
|
||||||
enum InputType {
|
enum InputType {
|
||||||
KEY,
|
BUTTON,
|
||||||
AXIS,
|
AXIS,
|
||||||
JOYSTICK,
|
JOYSTICK,
|
||||||
ESCAPE
|
ESCAPE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Input {
|
struct Button {
|
||||||
|
u64 value;
|
||||||
|
};
|
||||||
|
struct Axis {
|
||||||
|
i64 value;
|
||||||
|
};
|
||||||
|
struct Joystick {
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
};
|
||||||
|
union InputData {
|
||||||
|
struct Button input_but;
|
||||||
|
struct Axis input_axis;
|
||||||
|
struct Joystick input_js;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputRecord {
|
||||||
|
u16f bind;
|
||||||
|
struct timespec timestamp;
|
||||||
|
|
||||||
u8 type;
|
u8 type;
|
||||||
u8 is_down;
|
u8 is_down;
|
||||||
u8 is_held;
|
u8 is_held;
|
||||||
u8 is_up;
|
u8 is_up;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct Button {
|
struct Button but;
|
||||||
u64 value;
|
struct Axis axis;
|
||||||
} but;
|
struct Joystick js;
|
||||||
struct Axis {
|
union InputData data;
|
||||||
i64 value;
|
|
||||||
} axis;
|
|
||||||
struct Joystick {
|
|
||||||
i32 x;
|
|
||||||
i32 y;
|
|
||||||
} js;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputRecord {
|
|
||||||
u16f bind;
|
|
||||||
struct Input dat;
|
|
||||||
|
|
||||||
struct timespec timestamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InputAxis {
|
struct InputAxis {
|
||||||
struct Input dat;
|
|
||||||
|
|
||||||
struct timespec last_pressed;
|
struct timespec last_pressed;
|
||||||
struct timespec last_released;
|
struct timespec last_released;
|
||||||
|
|
||||||
|
u8 type;
|
||||||
|
u8 is_down;
|
||||||
|
u8 is_held;
|
||||||
|
u8 is_up;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct Button but;
|
||||||
|
struct Axis axis;
|
||||||
|
struct Joystick js;
|
||||||
|
union InputData data;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ctrl_dict {
|
struct ctrl_dict {
|
||||||
|
@ -66,20 +82,21 @@ struct ctrl_dict {
|
||||||
} *bkts;
|
} *bkts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InputBuffer {
|
||||||
|
size_t len;
|
||||||
|
struct InputRecord records[IO_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
struct ctrl_dict codes;
|
struct ctrl_dict codes;
|
||||||
struct ctrl_dict binds;
|
struct ctrl_dict binds;
|
||||||
struct InputAxis *axes;
|
struct InputAxis *axes;
|
||||||
|
|
||||||
struct InputBuffer {
|
struct InputBuffer input_buf;
|
||||||
struct InputRecord records[IO_BUF_SIZE];
|
|
||||||
size_t len;
|
|
||||||
size_t start;
|
|
||||||
} input_buf;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t indexes[IO_BUF_SIZE];
|
|
||||||
size_t len;
|
size_t len;
|
||||||
|
struct InputAxis *axes[IO_BUF_SIZE];
|
||||||
} pending_buf;
|
} pending_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,13 +126,8 @@ bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap)
|
||||||
},
|
},
|
||||||
.axes = axes,
|
.axes = axes,
|
||||||
|
|
||||||
.input_buf = {
|
.input_buf.len = 0,
|
||||||
.len = 0,
|
.pending_buf.len = 0,
|
||||||
.start = 0,
|
|
||||||
},
|
|
||||||
.pending_buf = {
|
|
||||||
.len = 0,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -238,73 +250,67 @@ struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type)
|
||||||
return code_bkt->axis;
|
return code_bkt->axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_key(struct InputAxis *axis, struct InputRecord *rec)
|
void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
|
||||||
{
|
{
|
||||||
if (rec->but.is_down) {
|
if (rec->is_down and !axis->is_held) {
|
||||||
|
axis->is_down = true;
|
||||||
|
axis->is_held = true;
|
||||||
axis->last_pressed = rec->timestamp;
|
axis->last_pressed = rec->timestamp;
|
||||||
axis->but.is_held = true;
|
} else if (rec->is_up) {
|
||||||
} else {
|
axis->is_up = true;
|
||||||
|
axis->is_held = false;
|
||||||
axis->last_released = rec->timestamp;
|
axis->last_released = rec->timestamp;
|
||||||
axis->but.is_held = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
axis->but.is_down |= rec->but.is_down;
|
axis->data = rec->data;
|
||||||
axis->but.is_up |= rec->but.is_up;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_axis(struct InputAxis *axis, struct InputRecord *rec)
|
|
||||||
{
|
|
||||||
axis->axis.value = rec->axis.value;
|
|
||||||
|
|
||||||
axis->last_pressed = rec->timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_joystick(struct InputAxis *axis, struct InputRecord *rec)
|
|
||||||
{
|
|
||||||
axis->js.x = rec->js.x;
|
|
||||||
axis->js.y = rec->js.y;
|
|
||||||
|
|
||||||
axis->last_pressed = rec->timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
|
|
||||||
{
|
|
||||||
switch (rec->type) {
|
|
||||||
case KEY:
|
|
||||||
update_key(axis, rec);
|
|
||||||
printf("axis:%hu\n", axis->but.is_down);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case AXIS:
|
|
||||||
update_axis(axis, rec);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case JOYSTICK:
|
|
||||||
update_joystick(axis, rec);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CtrlPoll(struct Controller *ctrl)
|
bool CtrlPoll(struct Controller *ctrl)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ctrl->pending_buf.len; i++) {
|
for (size_t i = 0; i < ctrl->pending_buf.len; i++) {
|
||||||
|
struct InputAxis *axis = ctrl->pending_buf.axes[i];
|
||||||
|
|
||||||
|
axis->is_up = false;
|
||||||
|
axis->is_down = false;
|
||||||
}
|
}
|
||||||
|
ctrl->pending_buf.len = ctrl->input_buf.len;
|
||||||
|
|
||||||
for (size_t i = 0; i < ctrl->input_buf.len; i++) {
|
for (size_t i = 0; i < ctrl->input_buf.len; i++) {
|
||||||
struct InputRecord *rec = &ctrl->input_buf.records[i];
|
struct InputRecord *rec = &ctrl->input_buf.records[i];
|
||||||
printf("i:%hu\n", rec->bind);
|
|
||||||
|
|
||||||
struct InputAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type);
|
struct InputAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type);
|
||||||
|
|
||||||
if (axis == nullptr)
|
if (axis == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!dispatch_update(axis, rec))
|
dispatch_update(axis, rec);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ctrl->pending_buf.axes[i] = axis;
|
||||||
|
}
|
||||||
ctrl->input_buf.len = 0;
|
ctrl->input_buf.len = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct Controller ctrl;
|
||||||
|
if (!NewCtrl(&ctrl, 3, 3))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
CtrlMap(&ctrl, 123, 111, BUTTON);
|
||||||
|
|
||||||
|
ctrl.input_buf.records[ctrl.input_buf.len++] = (struct InputRecord) {
|
||||||
|
.bind = 111,
|
||||||
|
.type = BUTTON,
|
||||||
|
.is_down = true,
|
||||||
|
.but.value = 69
|
||||||
|
};
|
||||||
|
|
||||||
|
CtrlPoll(&ctrl);
|
||||||
|
|
||||||
|
struct InputAxis *a = CtrlGet(&ctrl, 123, BUTTON);
|
||||||
|
printf("%u\n", a->but.value);
|
||||||
|
|
||||||
|
printf("success");
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -9,54 +9,65 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "fumotris.h"
|
#include "fumotris.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
#define IO_BUF_SIZE 16
|
#define IO_BUF_SIZE 16
|
||||||
|
|
||||||
enum InputType {
|
enum InputType {
|
||||||
KEY,
|
BUTTON,
|
||||||
AXIS,
|
AXIS,
|
||||||
JOYSTICK,
|
JOYSTICK,
|
||||||
ESCAPE
|
ESCAPE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Button {
|
struct Button {
|
||||||
u32 value;
|
u64 value;
|
||||||
bool is_down;
|
|
||||||
bool is_held;
|
|
||||||
bool is_up;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Axis {
|
struct Axis {
|
||||||
i64 value;
|
i64 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Joystick {
|
struct Joystick {
|
||||||
i32 x;
|
i32 x;
|
||||||
i32 y;
|
i32 y;
|
||||||
};
|
};
|
||||||
|
union InputData {
|
||||||
|
struct Button input_but;
|
||||||
|
struct Axis input_axis;
|
||||||
|
struct Joystick input_js;
|
||||||
|
};
|
||||||
|
|
||||||
struct InputRecord {
|
struct InputRecord {
|
||||||
u16 bind;
|
u16f bind;
|
||||||
|
struct timespec timestamp;
|
||||||
|
|
||||||
u8 type;
|
u8 type;
|
||||||
|
u8 is_down;
|
||||||
|
u8 is_held;
|
||||||
|
u8 is_up;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct Button but;
|
struct Button but;
|
||||||
struct Axis axis;
|
struct Axis axis;
|
||||||
struct Joystick js;
|
struct Joystick js;
|
||||||
|
union InputData data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct timespec timestamp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputAxis {
|
struct InputAxis {
|
||||||
|
struct timespec last_pressed;
|
||||||
|
struct timespec last_released;
|
||||||
|
|
||||||
|
u8 type;
|
||||||
|
u8 is_down;
|
||||||
|
u8 is_held;
|
||||||
|
u8 is_up;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct Button but;
|
struct Button but;
|
||||||
struct Axis axis;
|
struct Axis axis;
|
||||||
struct Joystick js;
|
struct Joystick js;
|
||||||
|
union InputData data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct timespec last_pressed;
|
|
||||||
struct timespec last_released;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CtrlCode {
|
enum CtrlCode {
|
||||||
|
@ -74,8 +85,6 @@ enum CtrlCode {
|
||||||
MOUSE
|
MOUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef u32 hashtype;
|
|
||||||
|
|
||||||
struct ctrl_dict {
|
struct ctrl_dict {
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t filled;
|
size_t filled;
|
||||||
|
@ -89,20 +98,21 @@ struct ctrl_dict {
|
||||||
} *bkts;
|
} *bkts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InputBuffer {
|
||||||
|
size_t len;
|
||||||
|
struct InputRecord records[IO_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
struct ctrl_dict codes;
|
struct ctrl_dict codes;
|
||||||
struct ctrl_dict binds;
|
struct ctrl_dict binds;
|
||||||
struct InputAxis *axes;
|
struct InputAxis *axes;
|
||||||
|
|
||||||
struct InputBuffer {
|
struct InputBuffer input_buf;
|
||||||
struct InputRecord records[IO_BUF_SIZE];
|
|
||||||
size_t len;
|
|
||||||
size_t start;
|
|
||||||
} input_buf;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t indexes[IO_BUF_SIZE];
|
|
||||||
size_t len;
|
size_t len;
|
||||||
|
struct InputAxis *axes[IO_BUF_SIZE];
|
||||||
} pending_buf;
|
} pending_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,6 @@ struct Input {
|
||||||
pthread_mutex_t access_mutex;
|
pthread_mutex_t access_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputRecord *get_at(struct InputBuffer *buf, size_t i)
|
|
||||||
{
|
|
||||||
return &buf->records[(buf->start + i) % IO_BUF_SIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
void *block_input(void *args_ptr)
|
void *block_input(void *args_ptr)
|
||||||
{
|
{
|
||||||
struct Input *in = args_ptr;
|
struct Input *in = args_ptr;
|
||||||
|
|
|
@ -3,19 +3,72 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <windows.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "input.h"
|
#include "fumotris.h"
|
||||||
#include "winhandler.h"
|
#include "ctrl.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
|
||||||
bool WindowsInit(struct Terminal *term)
|
struct Windows {
|
||||||
|
HANDLE in_handle;
|
||||||
|
HANDLE timer;
|
||||||
|
DWORD in_len;
|
||||||
|
INPUT_RECORD in_buf[IO_BUF_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Windows *platform;
|
||||||
|
|
||||||
|
bool WinInitHandles(struct Windows *win)
|
||||||
{
|
{
|
||||||
if (!WinInitHandles())
|
win->in_handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
if (win->in_handle == INVALID_HANDLE_VALUE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!WinInitConsole())
|
win->timer = CreateWaitableTimer(
|
||||||
|
NULL, // Timer attributes
|
||||||
|
TRUE, // Manual reset
|
||||||
|
NULL // Name
|
||||||
|
);
|
||||||
|
if (win->timer == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinInitConsole(struct Windows *win)
|
||||||
|
{
|
||||||
|
DWORD mode = ENABLE_EXTENDED_FLAGS
|
||||||
|
| ENABLE_PROCESSED_INPUT
|
||||||
|
| ENABLE_PROCESSED_OUTPUT
|
||||||
|
| ENABLE_MOUSE_INPUT
|
||||||
|
| ENABLE_WINDOW_INPUT;
|
||||||
|
return SetConsoleMode(win->in_handle, mode) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinGetRefreshRate(u16f *out)
|
||||||
|
{
|
||||||
|
DEVMODE mode;
|
||||||
|
mode.dmSize = sizeof(DEVMODE);
|
||||||
|
mode.dmDriverExtra = 0;
|
||||||
|
|
||||||
|
if(!EnumDisplaySettingsA(
|
||||||
|
NULL, // Device name (null for current)
|
||||||
|
ENUM_CURRENT_SETTINGS, // Mode
|
||||||
|
&mode // Out
|
||||||
|
))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*out = mode.dmDisplayFrequency;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowsInit(platform win, struct Terminal *term)
|
||||||
|
{
|
||||||
|
if (!WinInitHandles(win))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!WinInitConsole(win))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!WinGetRefreshRate(&term->refresh_rate))
|
if (!WinGetRefreshRate(&term->refresh_rate))
|
||||||
|
@ -24,17 +77,103 @@ bool WindowsInit(struct Terminal *term)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowsBlockInput(struct RecordBuffer *buf)
|
void read_key_rec(struct InputRecord *rec, KEY_EVENT_RECORD win_key)
|
||||||
{
|
{
|
||||||
return WinBlockInput(buf);
|
rec->type = BUTTON;
|
||||||
|
rec->bind = win_key.wVirtualKeyCode;
|
||||||
|
|
||||||
|
rec->is_down = win_key.bKeyDown;
|
||||||
|
rec->is_up = !win_key.bKeyDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowsWait(double seconds)
|
bool read_mouse_rec(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse)
|
||||||
{
|
{
|
||||||
struct timespec duration = {
|
if (win_mouse.dwEventFlags == MOUSE_MOVED) {
|
||||||
.tv_sec = seconds,
|
rec->type = JOYSTICK;
|
||||||
.tv_nsec = fmod(seconds, 1) * 1e9
|
rec->bind = 0;
|
||||||
};
|
rec->js.x = win_mouse.dwMousePosition.X;
|
||||||
|
rec->js.y = win_mouse.dwMousePosition.Y;
|
||||||
|
|
||||||
return WinWait(duration);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (win_mouse.dwEventFlags == MOUSE_WHEELED) {
|
||||||
|
rec->bind = 0;
|
||||||
|
} else if (win_mouse.dwEventFlags == MOUSE_HWHEELED) {
|
||||||
|
rec->bind = 1;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->type = AXIS;
|
||||||
|
rec->axis.value = win_mouse.dwButtonState;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_rec(struct InputRecord *rec, INPUT_RECORD win_rec)
|
||||||
|
{
|
||||||
|
switch (win_rec.EventType) {
|
||||||
|
case KEY_EVENT:
|
||||||
|
read_key_rec(rec, win_rec.Event.KeyEvent);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MOUSE_EVENT:
|
||||||
|
return read_mouse_rec(rec, win_rec.Event.MouseEvent);
|
||||||
|
|
||||||
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
|
return false;
|
||||||
|
// TODO: Handle window resizing
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->type = ESCAPE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinBlockInput(platform win, struct InputBuffer *buf)
|
||||||
|
{
|
||||||
|
if (!ReadConsoleInput(
|
||||||
|
win->in_handle, // Input handle
|
||||||
|
win->in_buf + buf->len, // Record buffer
|
||||||
|
IO_BUF_SIZE - buf->len, // Record buffer length
|
||||||
|
&win->in_len // Out number of records
|
||||||
|
))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
timespec_get(&now, TIME_UTC);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < win->in_len; i++) {
|
||||||
|
struct InputRecord *rec = &buf->records[buf->len];
|
||||||
|
|
||||||
|
if (!read_rec(rec, win->in_buf[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rec->timestamp = now;
|
||||||
|
buf->len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WinWait(platform win, struct timespec relative)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER duration;
|
||||||
|
duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100;
|
||||||
|
|
||||||
|
if (!SetWaitableTimer(
|
||||||
|
win->timer, // Timer
|
||||||
|
&duration, // Duration
|
||||||
|
0, // Period
|
||||||
|
NULL, // Completion coroutine
|
||||||
|
NULL, // Completion coroutine arg
|
||||||
|
FALSE // Resume
|
||||||
|
))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DWORD result = WaitForSingleObject(win->timer, INFINITE);
|
||||||
|
if (result != WAIT_OBJECT_0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -1,16 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <pthread.h>
|
|
||||||
#include <iso646.h>
|
#include <iso646.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "input.h"
|
#include "fumotris.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
|
||||||
bool WindowsInit(struct Terminal *term);
|
typedef struct Windows *platform;
|
||||||
|
|
||||||
bool WindowsBlockInput(struct RecordBuffer *buf);
|
bool WindowsInit(platform win, struct Terminal *term);
|
||||||
|
|
||||||
bool WindowsWait(double seconds);
|
bool WinBlockInput(platform win, struct InputBuffer *buf);
|
||||||
|
|
||||||
|
bool WinWait(platform win, struct timespec relative);
|
|
@ -1,173 +0,0 @@
|
||||||
#include <iso646.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "fumotris.h"
|
|
||||||
#include "gametime.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "term.h"
|
|
||||||
|
|
||||||
struct Windows {
|
|
||||||
HANDLE input_handle;
|
|
||||||
HANDLE timer;
|
|
||||||
};
|
|
||||||
static struct Windows win;
|
|
||||||
|
|
||||||
bool WinInitHandles()
|
|
||||||
{
|
|
||||||
win.input_handle = GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
if (win.input_handle == INVALID_HANDLE_VALUE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
win.timer = CreateWaitableTimer(
|
|
||||||
NULL, // Timer attributes
|
|
||||||
TRUE, // Manual reset
|
|
||||||
NULL // Name
|
|
||||||
);
|
|
||||||
if (!win.timer)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WinInitConsole()
|
|
||||||
{
|
|
||||||
DWORD mode = ENABLE_EXTENDED_FLAGS
|
|
||||||
| ENABLE_PROCESSED_INPUT
|
|
||||||
| ENABLE_PROCESSED_OUTPUT
|
|
||||||
| ENABLE_MOUSE_INPUT
|
|
||||||
| ENABLE_WINDOW_INPUT;
|
|
||||||
return SetConsoleMode(win.input_handle, mode) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WinGetRefreshRate(u16f *out)
|
|
||||||
{
|
|
||||||
DEVMODE mode;
|
|
||||||
mode.dmSize = sizeof(DEVMODE);
|
|
||||||
mode.dmDriverExtra = 0;
|
|
||||||
|
|
||||||
if(!EnumDisplaySettingsA(
|
|
||||||
NULL, // Device name (null for current)
|
|
||||||
ENUM_CURRENT_SETTINGS, // Mode
|
|
||||||
&mode // Out
|
|
||||||
))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*out = mode.dmDisplayFrequency;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_key_record(struct InputRecord *rec, KEY_EVENT_RECORD win_key)
|
|
||||||
{
|
|
||||||
rec->type = KEY;
|
|
||||||
rec->bind = win_key.wVirtualKeyCode;
|
|
||||||
|
|
||||||
rec->but.is_down = win_key.bKeyDown;
|
|
||||||
rec->but.is_up = !win_key.bKeyDown;
|
|
||||||
|
|
||||||
if (win_key.wVirtualKeyCode == VK_ESCAPE)
|
|
||||||
rec->type = ESCAPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set_mouse_record(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse)
|
|
||||||
{
|
|
||||||
switch (win_mouse.dwEventFlags) {
|
|
||||||
case MOUSE_WHEELED:
|
|
||||||
rec->type = AXIS;
|
|
||||||
rec->bind = 0;
|
|
||||||
rec->axis.value = win_mouse.dwButtonState;
|
|
||||||
break;
|
|
||||||
case MOUSE_HWHEELED:
|
|
||||||
rec->type = AXIS;
|
|
||||||
rec->bind = 1;
|
|
||||||
rec->axis.value = win_mouse.dwButtonState;
|
|
||||||
break;
|
|
||||||
case MOUSE_MOVED:
|
|
||||||
rec->type = JOYSTICK;
|
|
||||||
rec->bind = 0;
|
|
||||||
rec->js.x = win_mouse.dwMousePosition.X;
|
|
||||||
rec->js.y = win_mouse.dwMousePosition.Y;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dispatch_record(struct InputRecord *rec, INPUT_RECORD win_rec)
|
|
||||||
{
|
|
||||||
switch (win_rec.EventType) {
|
|
||||||
case KEY_EVENT:
|
|
||||||
set_key_record(rec, win_rec.Event.KeyEvent);
|
|
||||||
break;
|
|
||||||
case MOUSE_EVENT:
|
|
||||||
return set_mouse_record(rec, win_rec.Event.MouseEvent);
|
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
|
||||||
// TODO: Handle window resizing
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
rec->type = ESCAPE;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WinBlockInput(struct Controller *ctrl)
|
|
||||||
{
|
|
||||||
size_t win_size = IO_BUF_SIZE - ctrl->input_buf.len;
|
|
||||||
INPUT_RECORD win_buf[win_size];
|
|
||||||
DWORD count;
|
|
||||||
|
|
||||||
if (!ReadConsoleInput(
|
|
||||||
win.input_handle, // Input handle
|
|
||||||
win_buf, // Record buffer
|
|
||||||
win_size, // Record buffer length
|
|
||||||
&count // Out number of records
|
|
||||||
))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct timespec now;
|
|
||||||
timespec_get(&now, TIME_UTC);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&buf->mutex);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
struct InputRecord rec;
|
|
||||||
rec.timestamp = now;
|
|
||||||
|
|
||||||
bool include = dispatch_record(&rec, win_buf[i]);
|
|
||||||
if (!include)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
buf->records[buf->count++] = rec;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&buf->mutex);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WinWait(struct timespec relative)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER duration;
|
|
||||||
duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100;
|
|
||||||
|
|
||||||
if (!SetWaitableTimer(
|
|
||||||
win.timer, // Timer
|
|
||||||
&duration, // Duration
|
|
||||||
0, // Period
|
|
||||||
NULL, // Completion coroutine
|
|
||||||
NULL, // Completion coroutine arg
|
|
||||||
FALSE // Resume
|
|
||||||
))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DWORD result = WaitForSingleObject(win.timer, INFINITE);
|
|
||||||
if (result != WAIT_OBJECT_0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <iso646.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "fumotris.h"
|
|
||||||
|
|
||||||
bool WinInitHandles();
|
|
||||||
|
|
||||||
bool WinInitConsole();
|
|
||||||
|
|
||||||
bool WinGetRefreshRate(u16f *out);
|
|
||||||
|
|
||||||
bool WinBlockInput(struct RecordBuffer *buf);
|
|
||||||
|
|
||||||
bool WinWait(struct timespec relative);
|
|
|
@ -75,15 +75,15 @@ struct CtrlBind {
|
||||||
|
|
||||||
const size_t code_count = 12;
|
const size_t code_count = 12;
|
||||||
const struct CtrlBind ctrl_binds[12] = {
|
const struct CtrlBind ctrl_binds[12] = {
|
||||||
{ LEFT, 0x25, KEY },
|
{ LEFT, 0x25, BUTTON },
|
||||||
{ RIGHT, 0x27, KEY },
|
{ RIGHT, 0x27, BUTTON },
|
||||||
{ SOFT_DROP, 0x28, KEY },
|
{ SOFT_DROP, 0x28, BUTTON },
|
||||||
{ HARD_DROP, 0x20, KEY },
|
{ HARD_DROP, 0x20, BUTTON },
|
||||||
{ ROTATE_CCW, 'Z', KEY },
|
{ ROTATE_CCW, 'Z', BUTTON },
|
||||||
{ ROTATE_CW, 'X', KEY },
|
{ ROTATE_CW, 'X', BUTTON },
|
||||||
{ ROTATE_180, 'A', KEY },
|
{ ROTATE_180, 'A', BUTTON },
|
||||||
{ SWAP, 'C', KEY },
|
{ SWAP, 'C', BUTTON },
|
||||||
{ ESC, 0x1B, KEY },
|
{ ESC, 0x1B, BUTTON },
|
||||||
{ VSCROLL, 0, AXIS },
|
{ VSCROLL, 0, AXIS },
|
||||||
{ HSCROLL, 1, AXIS },
|
{ HSCROLL, 1, AXIS },
|
||||||
{ MOUSE, 0, JOYSTICK }
|
{ MOUSE, 0, JOYSTICK }
|
||||||
|
@ -96,7 +96,7 @@ void *Update(void *args)
|
||||||
while (true) {
|
while (true) {
|
||||||
// Input
|
// Input
|
||||||
CtrlPoll(&game->ctrl);
|
CtrlPoll(&game->ctrl);
|
||||||
if (CtrlGet(&game->ctrl, LEFT, KEY)->button.is_down)
|
if (CtrlGet(&game->ctrl, LEFT, BUTTON)->button.is_down)
|
||||||
printf("left down this frame\n");
|
printf("left down this frame\n");
|
||||||
|
|
||||||
// Game logic
|
// Game logic
|
||||||
|
|
Loading…
Reference in a new issue