From 7408b98e0507955e8f3e55c10ee7ff3ccdace652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ma=C5=A1karinec?= Date: Tue, 30 Jan 2024 11:03:03 +0100 Subject: [PATCH] input: Fix mouse delta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Maškarinec --- src/staembed.c | 387 +++++-------------------------------------------- src/window.c | 2 + 2 files changed, 40 insertions(+), 349 deletions(-) diff --git a/src/staembed.c b/src/staembed.c index 3af0f2a1..f7c928a5 100644 --- a/src/staembed.c +++ b/src/staembed.c @@ -1820,224 +1820,6 @@ const char *th_em_modulesrc[] = { "\treturn o\n" "}\n" "", -"// Umka standard library\n" -"\n" -"// Memory\n" -"\n" -"fn rtlmemcpy(dest, src: ^void, count: int)\n" -"\n" -"fn tobytes*(buf: interface{}): []uint8 {\n" -" if buf.__self == null {\n" -" error(\"Buffer is null\")\n" -" }\n" -" if selfhasptr(buf) {\n" -" error(\"Cannot access reference types\")\n" -" }\n" -" bytes := make([]uint8, sizeofself(buf))\n" -" rtlmemcpy(&bytes[0], buf.__self, sizeofself(buf))\n" -" return bytes\n" -"}\n" -"\n" -"fn frombytes*(buf: interface{}, bytes: []uint8) {\n" -" if buf.__self == null {\n" -" error(\"Buffer is null\")\n" -" } \n" -" if selfhasptr(buf) {\n" -" error(\"Cannot access reference types\")\n" -" }\n" -" if sizeofself(buf) != len(bytes) {\n" -" error(\"Illegal buffer size\")\n" -" }\n" -" rtlmemcpy(buf.__self, &bytes[0], sizeofself(buf)) \n" -"}\n" -"\n" -"// File I/O\n" -"\n" -"type File* = ^struct {}\n" -"\n" -"const (\n" -" seekBegin* = 0\n" -" seekCur* = 1\n" -" seekEnd* = 2\n" -") \n" -"\n" -"fn rtlfopen (name: str, mode: str): File; \n" -"fn fopen* (name: str, mode: str): File {return rtlfopen(name, mode)}\n" -"\n" -"fn rtlfclose (f: File): int\n" -"fn fclose* (f: File): int {return rtlfclose(f)}\n" -"\n" -"fn rtlfread(buf: ^void, size, cnt: int, f: File): int\n" -"\n" -"fn fread*(f: File, buf: interface{}): int {\n" -" if f == null {\n" -" error(\"File is null\")\n" -" }\n" -" if bytes := ^[]uint8(buf); bytes != null {\n" -" return rtlfread(&bytes[0], len(bytes^), 1, f)\n" -" }\n" -" if selfhasptr(buf) {\n" -" error(\"Cannot read reference types except ^[]uint8\")\n" -" }\n" -" return rtlfread(buf.__self, sizeofself(buf), 1, f)\n" -"}\n" -"\n" -"fn rtlfwrite(buf: ^void, size, cnt: int, f: File): int\n" -"\n" -"fn fwrite*(f: File, buf: interface{}): int {\n" -" if f == null {\n" -" error(\"File is null\")\n" -" }\n" -" if bytes := ^[]uint8(buf); bytes != null {\n" -" return rtlfwrite(&bytes[0], len(bytes^), 1, f)\n" -" } \n" -" if selfhasptr(buf) {\n" -" error(\"Cannot write reference types except ^[]uint8\")\n" -" }\n" -" return rtlfwrite(buf.__self, sizeofself(buf), 1, f)\n" -"}\n" -"\n" -"fn rtlfseek (f: File, offset, origin: int): int\n" -"fn fseek* (f: File, offset, origin: int): int {\n" -" if f == null {\n" -" error(\"File is null\")\n" -" }\n" -" return rtlfseek(f, offset, origin)\n" -"}\n" -"\n" -"fn rtlftell (f: File): int\n" -"fn ftell* (f: File): int {\n" -" if f == null {\n" -" error(\"File is null\")\n" -" }\n" -" return rtlftell(f)\n" -"}\n" -"\n" -"fn rtlremove (name: str): int\n" -"fn remove* (name: str): int {return rtlremove(name)}\n" -"\n" -"fn rtlfeof (f: File): int\n" -"fn feof* (f: File): bool {\n" -" if f == null {\n" -" error(\"File is null\")\n" -" } \n" -" return bool(rtlfeof(f))\n" -"}\n" -"\n" -"// I/O utilities\n" -"\n" -"fn println*(s: str): int {return printf(\"%s\\n\", s)}\n" -"fn fprintln*(f: File, s: str): int {return fprintf(f, \"%s\\n\", s)}\n" -"\n" -"fn getchar*(): char {\n" -" var c: char\n" -" scanf(\"%c\", &c)\n" -" return c\n" -"}\n" -"\n" -"// Strings\n" -"\n" -"fn ltrim*(s: str): str {\n" -" start := -1\n" -" slen := len(s)\n" -" for i := 0; i < slen; i++ {\n" -" if s[i] != \' \' && s[i] != \'\\t\' {\n" -" start = i\n" -" break\n" -" } \n" -" }\n" -" if start == -1 {return \"\"}\n" -" return slice(s, start)\n" -"}\n" -"\n" -"fn rtrim*(s: str): str {\n" -" stop := -1\n" -" slen := len(s)\n" -" for i := slen - 1; i >= 0; i-- {\n" -" if s[i] != \' \' && s[i] != \'\\t\' {\n" -" stop = i\n" -" break\n" -" } \n" -" }\n" -" if stop == -1 {return \"\"}\n" -" return slice(s, 0, stop + 1)\n" -"}\n" -"\n" -"fn trim*(s: str): str {\n" -" return ltrim(rtrim(s))\n" -"}\n" -"\n" -"// Conversions\n" -"\n" -"fn atoi*(s: str): int {\n" -" var x: int\n" -" sscanf(s, \"%lld\", &x)\n" -" return x\n" -"}\n" -"\n" -"fn atof*(s: str): real {\n" -" var x: real\n" -" sscanf(s, \"%lf\", &x)\n" -" return x\n" -"}\n" -"\n" -"fn itoa*(x: int): str {\n" -" s := str(make([]char, 256))\n" -" sprintf(s, \"%lld\", x)\n" -" return s\n" -"}\n" -"\n" -"fn ftoa*(x: real, decimals: int): str {\n" -" fmt := str(make([]char, 256))\n" -" s := str(make([]char, 256))\n" -" sprintf(fmt, \"%%.%dlf\", decimals)\n" -" sprintf(s, fmt, x)\n" -" return s\n" -"}\n" -"\n" -"// Math\n" -"\n" -"const pi* = 3.14159265358979323846\n" -"\n" -"// Random numbers\n" -"\n" -"const randMax* = 0x7FFFFFFF\n" -"randSeed := 0\n" -"\n" -"fn srand*(seed: int) {randSeed = seed}\n" -"\n" -"fn rand*(): int {\n" -" randSeed = ((randSeed * 1103515245) + 12345) & 0x7FFFFFFF\n" -" return randSeed\n" -"}\n" -"\n" -"fn frand*(): real {return real(rand()) / randMax}\n" -"\n" -"// Timer\n" -"\n" -"fn rtltime(): int\n" -"fn time*(): int {return rtltime()}\n" -"\n" -"fn rtlclock(): real\n" -"fn clock*(): real {return rtlclock()}\n" -"\n" -"// Command line and environment\n" -"\n" -"fn argc*(): int {return rtlargc}\n" -"\n" -"fn argv*(i: int): str {\n" -" if i < 0 || i >= rtlargc {\n" -" error(\"Command line parameter not found\")\n" -" }\n" -" return rtlargv[i]\n" -"}\n" -"\n" -"fn rtlgetenv(name: str): str\n" -"fn getenv*(name: str): str {\n" -" return \"\" + rtlgetenv(name)\n" -"}\n" -"\n" -"", "//~~\n" "// Particles allow for *performant* and random particle systems.\n" "//~~\n" @@ -3800,6 +3582,7 @@ const char *th_em_modulesrc[] = { "//~~fn TextBox.clear\n" "// Clears the textbox\n" "fn (this: ^TextBox) clear*() {\n" +"//~~\n" "\tthis.buffer = \"\"\n" "\tthis.cursor = 0\n" "}\n" @@ -3986,7 +3769,10 @@ const char *th_em_modulesrc[] = { "\t\t\tcolor: 0x888888ff } }\n" "}\n" "\n" +"//~~fn mk\n" +"// Creates a GUI instance.\n" "fn mk*(r: rect.Rect, s: Style): Gui {\n" +"//~~\n" "\tgui := Gui{}\n" "\tgui.pushStyle(s)\n" "\tgui.container = []Container{ Stack{ dm: r } }\n" @@ -3995,8 +3781,8 @@ const char *th_em_modulesrc[] = { "}\n" "", }; -const char *th_em_modulenames[] = { "anim.um", "audio.um", "csv.um", "ent.um", "image.um", "input.um", "misc.um", "canvas.um", "ray.um", "rect.um", "tilemap.um", "window.um", "std/std.um", "particles.um", "lerp.um", "font.um", "th.um", "signal.um", "atlas.um", "shader.um", "color.um", "coll.um", "placeholders.um", "nav.um", "ui.um", }; -int th_em_modulenames_count = 25; +const char *th_em_modulenames[] = { "anim.um", "audio.um", "csv.um", "ent.um", "image.um", "input.um", "misc.um", "canvas.um", "ray.um", "rect.um", "tilemap.um", "window.um", "particles.um", "lerp.um", "font.um", "th.um", "signal.um", "atlas.um", "shader.um", "color.um", "coll.um", "placeholders.um", "nav.um", "ui.um", }; +int th_em_modulenames_count = 24; const char *th_em_misc[] = { "BSD 3-Clause License\n" "\n" @@ -5498,7 +5284,6 @@ const char *th_em_moduledocs[] = { "\n" "\n" "", -"", "## \n" "\n" "```\n" @@ -7020,166 +6805,70 @@ const char *th_em_moduledocs[] = { "\n" "```\n" "fn (this: ^TextBox) clear*() {\n" -"\tthis.buffer = \"\"\n" -"\tthis.cursor = 0\n" -"}\n" "```\n" "\n" "Clears the textbox\n" "\n" "\n" -"## \n" +"## fn Gui.textBox\n" "\n" "```\n" -"\tgui.idx++\n" -"\n" -"\tr := gui.pushRect(cfg.rect)\n" -"\n" -"\thover := gui.hover(r)\n" -"\n" -"\tif gui.isEval {\n" -"\t\tif input.isJustPressed(input.mouse1) && hover {\n" -"\t\t\tgui.selection = gui.idx\n" -"\t\t}\n" -"\n" -"\t\tif input.isJustPressed(input.mouse1) && !hover &&\n" -"\t\t\tgui.selection == gui.idx {\n" -"\t\t\t\tgui.selection = 0\n" -"\t\t}\n" -"\n" -"\t\tif input.isJustPressed(input.key_escape) && gui.selection == gui.idx {\n" -"\t\t\tgui.selection = 0\n" -"\t\t}\n" -"\n" -"\t\tif gui.selection != gui.idx {\n" -"\t\t\treturn\n" -"\t\t}\n" -"\n" -"\t\tif input.isJustPressed(input.key_left) ||\n" -"\t\t\tinput.isPressedRepeat(input.key_left) {\n" -"\t\t\tif tb.cursor > 0 { tb.cursor-- }\n" -"\t\t}\n" -"\n" -"\t\tif input.isJustPressed(input.key_right) ||\n" -"\t\t\tinput.isPressedRepeat(input.key_right) {\n" -"\t\t\tif tb.cursor < len(tb.buffer) { tb.cursor++ }\n" -"\t\t}\n" -"\n" -"\t\tif input.isJustPressed(input.key_backspace) ||\n" -"\t\t\tinput.isPressedRepeat(input.key_backspace) {\n" -"\n" -"\t\t\tif tb.cursor > 0 {\n" -"\t\t\t\ttb.buffer = slice(tb.buffer, 0, tb.cursor - 1) +\n" -"\t\t\t\t\tslice(tb.buffer, tb.cursor)\n" -"\t\t\t\ttb.cursor--\n" -"\t\t\t}\n" -"\t\t}\n" -"\n" -"\t\tv := true\n" -"\n" -"\t\tif input.isPressed(input.key_ctrl) && input.isJustPressedc(\'u\') {\n" -"\t\t\ttb.clear()\n" -"\t\t\tv = false\n" -"\t\t}\n" -"\n" -"\t\ts := input.getStr()\n" -"\t\tfor i in s {\n" -"\t\t\tif int(s[i]) < int(\' \') || int(s[i]) == int(\'z\') + 1 {\n" -"\t\t\t\tv = false\n" -"\t\t\t}\n" -"\t\t}\n" -"\t\tif len(s) > 0 && v {\n" -"\t\t\ttb.buffer = slice(tb.buffer, 0, tb.cursor) + s +\n" -"\t\t\t\tslice(tb.buffer, tb.cursor)\n" -"\t\t\ttb.cursor += len(s)\n" -"\t\t}\n" -"\n" -"\t\treturn\n" -"\t}\n" -"\n" -"\n" -"\tstyle := gui.getStyle()\n" -"\n" -"\tstyle.negBox.draw(r)\n" -"\tcanvas.beginScissorRect(r)\n" -"\n" -"\tdm := style.ft.measure(tb.buffer).mulf(style.ftScale)\n" -"\n" -"\tp := th.Vf2{}\n" -"\tp.y = r.y + r.h/2 - dm.y/2\n" -"\tc := th.Vf2{r.x, p.y}\n" +"fn (gui: ^Gui) textBox*(tb: ^TextBox, cfg: TextBoxConfig = {}) {\n" +"```\n" "\n" -"\tcdmx := style.ft.measure(slice(tb.buffer, 0, tb.cursor)).x * style.ftScale\n" -"\tif cdmx < r.w - 2 {\n" -"\t\tp.x = r.x + 1\n" -"\t\tc.x = p.x + cdmx\n" -"\t} else {\n" -"\t\tc.x = r.x + r.w - 1\n" -"\t\tp.x = c.x - cdmx\n" -"\t}\n" +"Adds a single line textbox to the gui.\n" +"TODO:\n" +"* unicode is not supported.\n" +"* no selection\n" +"* multiline\n" +"* copy paste\n" +"* stuff like home and end\n" "\n" -"\taW := style.ft.measure(\"A\").x * style.ftScale\n" "\n" -"\tstyle.ft.draw(tb.buffer, p, style.ftColor, style.ftScale)\n" -"\tif gui.selection == gui.idx {\n" -"\t\tcanvas.drawRect(style.ftColor, rect.mk(c.x, c.y, aW / 4, dm.y))\n" -"\t}\n" +"## struct ImageConfig\n" "\n" -"\tcanvas.endScissor()\n" +"```\n" +"type ImageConfig* = struct {\n" +"\tstretchX, stretchY: bool\n" +"\tcenterX, centerY: bool\n" +"\tcolor: uint32\n" +"\tscale: th.Vf2\n" +"\trect: rect.Rect\n" "}\n" "```\n" "\n" +"Configuration for the images element. Behaves similarly to labels.\n" "\n" "\n" -"## \n" +"## fn Gui.image\n" "\n" "```\n" +"fn (gui: ^Gui) image*(i: image.Image, cfg: ImageConfig = {\n" +"\tstretchX: true,\n" +"\tstretchY: true,\n" +"\tcolor: th.white,\n" +"\tscale: { 1, 1 } }) {\n" "```\n" "\n" +"Draws an image.\n" "\n" "\n" -"## \n" +"## fn getDefaultStyle\n" "\n" "```\n" -"\n" -"\tif cfg.centerX { cfg.stretchX = true }\n" -"\tif cfg.centerY { cfg.stretchY = true }\n" -"\n" -"\tr := cfg.rect\n" -"\tdm := i.getDims().mul(cfg.scale)\n" -"\tif r.w == 0 { r.w = dm.x }\n" -"\tif r.h == 0 { r.h = dm.y }\n" -"\n" -"\tif cfg.stretchX { r.w = 0 }\n" -"\tif cfg.stretchY { r.h = 0 }\n" -"\n" -"\tr = gui.pushRect(r)\n" -"\n" -"\tif gui.isEval { return }\n" -"\n" -"\tx := r.x\n" -"\ty := r.y\n" -"\tif cfg.centerX {\n" -"\t\tx += (r.w - dm.x) / 2\n" -"\t}\n" -"\n" -"\tif cfg.centerY {\n" -"\t\ty += (r.h - dm.y) / 2\n" -"\t}\n" -"\n" -"\ti.draw(th.Transform{\n" -"\t\tp: { x, y },\n" -"\t\ts: cfg.scale }, cfg.color)\n" -"}\n" +"fn getDefaultStyle*(): Style {\n" "```\n" "\n" +"Returns the default tophat ui style.\n" "\n" "\n" -"## \n" +"## fn mk\n" "\n" "```\n" +"fn mk*(r: rect.Rect, s: Style): Gui {\n" "```\n" "\n" +"Creates a GUI instance.\n" "\n" "\n" "", diff --git a/src/window.c b/src/window.c index 498985d2..204eb213 100644 --- a/src/window.c +++ b/src/window.c @@ -90,6 +90,8 @@ frame() } } + thg->mouse_delta = (th_vf2){}; + th_input_cycle(); th_canvas_flush(); th_canvas_end_frame();