177 lines
5.3 KiB
Plaintext
177 lines
5.3 KiB
Plaintext
module ugui;
|
|
|
|
import grapheme;
|
|
import std::io;
|
|
import std::math;
|
|
|
|
|
|
bitstruct InputEvents : uint {
|
|
bool resize : 0; // window size was changed
|
|
bool change_focus : 1; // window focus changed
|
|
bool mouse_move : 2; // mouse was moved
|
|
bool mouse_btn : 3; // mouse button pressed or released
|
|
bool mouse_scroll : 4; // mouse scroll wheel. x or y
|
|
bool text_input : 5;
|
|
bool mod_key : 6;
|
|
}
|
|
|
|
bitstruct MouseButtons : uint {
|
|
bool btn_left : 0;
|
|
bool btn_middle : 1;
|
|
bool btn_right : 2;
|
|
bool btn_4 : 3;
|
|
bool btn_5 : 4;
|
|
}
|
|
|
|
// FIXME: all of these names were prefixed with key_ idk if this is better,
|
|
// if it is remove the prefix on MouseButtons as well
|
|
// Modifier Keys, same as SDL
|
|
bitstruct ModKeys : uint {
|
|
bool lshift : 0;
|
|
bool rshift : 1;
|
|
bool lctrl : 2;
|
|
bool rctrl : 3;
|
|
bool lalt : 4;
|
|
bool ralt : 5;
|
|
bool lgui : 6;
|
|
bool rgui : 7;
|
|
bool num : 8;
|
|
bool caps : 9;
|
|
bool mode : 10;
|
|
bool scroll : 11;
|
|
}
|
|
|
|
const ModKeys KMOD_CTRL = {.lctrl = true, .rctrl = true};
|
|
const ModKeys KMOD_SHIFT = {.lshift = true, .rshift = true};
|
|
const ModKeys KMOD_ALT = {.lalt = true, .ralt = true};
|
|
const ModKeys KMOD_GUI = {.lgui = true, .rgui = true};
|
|
const ModKeys KMOD_NONE = ModKeys{};
|
|
const ModKeys KMOD_ANY = (ModKeys)(ModKeys.inner.max);
|
|
|
|
const MouseButtons BTN_NONE = MouseButtons{};
|
|
const MouseButtons BTN_ANY = (MouseButtons)(MouseButtons.inner.max);
|
|
const MouseButtons BTN_LEFT = {.btn_left = true};
|
|
const MouseButtons BTN_MIDDLE = {.btn_middle = true};
|
|
const MouseButtons BTN_RIGHT = {.btn_right = true};
|
|
const MouseButtons BTN_4 = {.btn_4 = true};
|
|
const MouseButtons BTN_5 = {.btn_5 = true};
|
|
|
|
const ModKeys KEY_ANY = (ModKeys)(ModKeys.inner.max);
|
|
|
|
// Window size was changed
|
|
fn void! Ctx.input_window_size(&ctx, short width, short height)
|
|
{
|
|
if (width <= 0 || height <= 0) {
|
|
return UgError.INVALID_SIZE?;
|
|
}
|
|
ctx.input.events.resize = ctx.width != width || ctx.height != height;
|
|
ctx.width = width;
|
|
ctx.height = height;
|
|
}
|
|
|
|
// Window gained/lost focus
|
|
fn void Ctx.input_changefocus(&ctx, bool has_focus)
|
|
{
|
|
// FIXME: raylib only has an API to query the focus status so we have to
|
|
// update the input flag only if the focus changed
|
|
ctx.input.events.change_focus = ctx.has_focus != has_focus;
|
|
ctx.has_focus = has_focus;
|
|
}
|
|
|
|
macro Ctx.mouse_pressed(&ctx) => ctx.input.mouse.updated & ctx.input.mouse.down;
|
|
macro Ctx.mouse_released(&ctx) => ctx.input.mouse.updated & ~ctx.input.mouse.down;
|
|
macro Ctx.mouse_down(&ctx) => ctx.input.mouse.down;
|
|
|
|
// FIXME: hthis compairson could be done with a cast using MouseButtons.inner
|
|
// property but I could not figure out how
|
|
macro Ctx.is_mouse_pressed(&ctx, MouseButtons btn) => (ctx.mouse_pressed() & btn) != BTN_NONE;
|
|
macro Ctx.is_mouse_released(&ctx, MouseButtons btn) => (ctx.mouse_released() & btn) != BTN_NONE;
|
|
macro Ctx.is_mouse_down(&ctx, MouseButtons btn) => (ctx.mouse_down() & btn) != BTN_NONE;
|
|
|
|
// Mouse Buttons down
|
|
fn void Ctx.input_mouse_button(&ctx, MouseButtons buttons)
|
|
{
|
|
ctx.input.mouse.updated = ctx.input.mouse.down ^ buttons;
|
|
ctx.input.mouse.down = buttons;
|
|
ctx.input.events.mouse_btn = (uint)ctx.input.mouse.down != 0 || (uint)ctx.input.mouse.updated != 0;
|
|
}
|
|
|
|
// Mouse was moved, report absolute position
|
|
fn void Ctx.input_mouse_abs(&ctx, short x, short y)
|
|
{
|
|
ctx.input.mouse.pos.x = math::clamp(x, 0u16, ctx.width);
|
|
ctx.input.mouse.pos.y = math::clamp(y, 0u16, ctx.height);
|
|
|
|
short dx, dy;
|
|
dx = x - ctx.input.mouse.pos.x;
|
|
dy = y - ctx.input.mouse.pos.y;
|
|
|
|
ctx.input.mouse.delta.x = dx;
|
|
ctx.input.mouse.delta.y = dy;
|
|
|
|
ctx.input.events.mouse_move = dx != 0 || dy != 0;
|
|
}
|
|
|
|
// Mouse was moved, report relative motion
|
|
fn void Ctx.input_mouse_delta(&ctx, short dx, short dy)
|
|
{
|
|
ctx.input.mouse.delta.x = dx;
|
|
ctx.input.mouse.delta.y = dy;
|
|
|
|
short mx, my;
|
|
mx = ctx.input.mouse.pos.x + dx;
|
|
my = ctx.input.mouse.pos.y + dy;
|
|
|
|
ctx.input.mouse.pos.x = math::clamp(mx, 0u16, ctx.width);
|
|
ctx.input.mouse.pos.y = math::clamp(my, 0u16, ctx.height);
|
|
|
|
ctx.input.events.mouse_move = dx != 0 || dy != 0;
|
|
}
|
|
|
|
fn void Ctx.input_mouse_wheel(&ctx, short x, short y, float scale = 1.0)
|
|
{
|
|
ctx.input.mouse.scroll.x = (short)((float)-x*scale);
|
|
ctx.input.mouse.scroll.y = (short)((float)-y*scale);
|
|
ctx.input.events.mouse_scroll = x !=0 || y != 0;
|
|
}
|
|
|
|
// append utf-8 encoded text to the context text input
|
|
fn void Ctx.input_text_utf8(&ctx, char[] text)
|
|
{
|
|
if (text.len == 0) { return; }
|
|
|
|
usz remaining = ctx.input.keyboard.text.len - ctx.input.keyboard.text_len;
|
|
usz len = text.len > remaining ? remaining : text.len;
|
|
char[] s = ctx.input.keyboard.text[ctx.input.keyboard.text_len ..];
|
|
s[..len-1] = text[..len-1];
|
|
ctx.input.keyboard.text_len += len;
|
|
ctx.input.events.text_input = true;
|
|
}
|
|
|
|
fn void Ctx.input_text_unicode(&ctx, int[] text)
|
|
{
|
|
if (text.len == 0) { return; }
|
|
|
|
char[32] tmp;
|
|
usz remaining = ctx.input.keyboard.text.len - ctx.input.keyboard.text_len;
|
|
char[] s = ctx.input.keyboard.text[ctx.input.keyboard.text_len ..];
|
|
|
|
usz off;
|
|
foreach (idx, cp: text) {
|
|
if (off >= remaining) { break; }
|
|
usz enc = grapheme::encode_utf8(cp, tmp[..], tmp.len);
|
|
s[off..off+enc] = tmp[..enc];
|
|
off += enc;
|
|
}
|
|
ctx.input.keyboard.text_len += off;
|
|
|
|
ctx.input.events.text_input = true;
|
|
}
|
|
|
|
// Mouse Buttons down
|
|
fn void Ctx.input_mod_keys(&ctx, ModKeys modkeys)
|
|
{
|
|
ctx.input.keyboard.down = modkeys;
|
|
ctx.input.events.mod_key = (uint)ctx.input.keyboard.down != 0;
|
|
}
|