From 8b7f6d305daf5951aaee4d78dc64c2e822b98bcb Mon Sep 17 00:00:00 2001 From: goldbuick Date: Tue, 31 Dec 2024 04:24:08 -0500 Subject: [PATCH 1/4] almost working new touch ui --- cafe/.env | 2 + package.json | 1 - yarn.lock | 5 - zss/config.ts | 4 + zss/device/api.ts | 12 ++ zss/device/vm.ts | 1 - zss/gadget/terminal.tsx | 13 +- zss/gadget/touchui/component.tsx | 289 ++++++++++++++++++------------- zss/gadget/userinput.tsx | 91 ++++++---- zss/userspace.ts | 11 +- 10 files changed, 258 insertions(+), 171 deletions(-) diff --git a/cafe/.env b/cafe/.env index 1809f91e..ee96ce7b 100644 --- a/cafe/.env +++ b/cafe/.env @@ -7,5 +7,7 @@ ZSS_SHOW_CODE=false ZSS_TRACE_CODE= ZSS_LOG_DEBUG=false ZSS_FORCE_CRT_OFF=false +ZSS_FORCE_LOW_REZ=false +ZSS_FORCE_TOUCH_UI=false ZSS_HMR_ONLY=false ZSS_ANALYZER=false diff --git a/package.json b/package.json index 2a677245..c51c05d1 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "msgpackr": "^1.11.2", "nanoid": "^5.0.3", "nanoid-dictionary": "^4.3.0", - "nipplejs": "^0.10.2", "path-browserify": "^1.0.0", "peerjs": "^1.5.4", "postprocessing": "^6.36.4", diff --git a/yarn.lock b/yarn.lock index 332c0b18..2c45ce98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4463,11 +4463,6 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -nipplejs@^0.10.2: - version "0.10.2" - resolved "https://registry.npmjs.org/nipplejs/-/nipplejs-0.10.2.tgz#0e8f5346bd60f7a0fe0d44c856bc1654cde2b70c" - integrity sha512-XGxFY8C2DOtobf1fK+MXINTzkkXJLjZDDpfQhOUZf4TSytbc9s4bmA0lB9eKKM8iDivdr9NQkO7DpIQfsST+9g== - node-gyp-build-optional-packages@5.2.2: version "5.2.2" resolved "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4" diff --git a/zss/config.ts b/zss/config.ts index 0f0654e9..31757aae 100644 --- a/zss/config.ts +++ b/zss/config.ts @@ -8,6 +8,8 @@ const SHOW_CODE = !!JSON.parse(import.meta.env.ZSS_SHOW_CODE) const TRACE_CODE = `${import.meta.env.ZSS_TRACE_CODE}` const LOG_DEBUG = !!JSON.parse(import.meta.env.ZSS_LOG_DEBUG) const FORCE_CRT_OFF = !!JSON.parse(import.meta.env.ZSS_FORCE_CRT_OFF) +const FORCE_LOW_REZ = !!JSON.parse(import.meta.env.ZSS_FORCE_LOW_REZ) +const FORCE_TOUCH_UI = !!JSON.parse(import.meta.env.ZSS_FORCE_TOUCH_UI) // runtime config export const RUNTIME = { @@ -31,4 +33,6 @@ export { TRACE_CODE, LOG_DEBUG, FORCE_CRT_OFF, + FORCE_LOW_REZ, + FORCE_TOUCH_UI, } diff --git a/zss/device/api.ts b/zss/device/api.ts index c6604ce8..a565e118 100644 --- a/zss/device/api.ts +++ b/zss/device/api.ts @@ -187,6 +187,18 @@ export function tape_editor_close(sender: string, player: string) { hub.emit('tape:editor:close', sender, undefined, player) } +export function userinput_up(sender: string, input: INPUT, player: string) { + hub.emit('userinput:up', sender, input, player) +} + +export function userinput_down(sender: string, input: INPUT, player: string) { + hub.emit('userinput:down', sender, input, player) +} + +export function userinput_update(sender: string, player: string) { + hub.emit('userinput:update', sender, undefined, player) +} + export function vm_books( sender: string, books: string, diff --git a/zss/device/vm.ts b/zss/device/vm.ts index cee5236f..9c65768a 100644 --- a/zss/device/vm.ts +++ b/zss/device/vm.ts @@ -131,7 +131,6 @@ const vm = createdevice('vm', ['init', 'tick', 'second'], (message) => { break case 'input': if (message.player) { - console.info(message) // player input const flags = memoryreadflags(message.player) const [input = INPUT.NONE, mods = 0] = message.data ?? [INPUT.NONE, 0] diff --git a/zss/gadget/terminal.tsx b/zss/gadget/terminal.tsx index 82ed4608..291b7ccc 100644 --- a/zss/gadget/terminal.tsx +++ b/zss/gadget/terminal.tsx @@ -5,7 +5,13 @@ import { deviceType, primaryInput } from 'detect-it' import { useEffect, useState } from 'react' import Stats from 'stats.js' import { NearestFilter, OrthographicCamera } from 'three' -import { FORCE_CRT_OFF, RUNTIME, STATS_DEV } from 'zss/config' +import { + FORCE_CRT_OFF, + FORCE_LOW_REZ, + FORCE_TOUCH_UI, + RUNTIME, + STATS_DEV, +} from 'zss/config' import { CRTShape } from 'zss/gadget/fx/crt' import decoimageurl from 'zss/gadget/fx/scratches.gif' import { useTexture } from 'zss/gadget/usetexture' @@ -54,12 +60,13 @@ export function Terminal() { // config DRAW_CHAR_SCALE const minrez = Math.min(viewwidth, viewheight) - const islowrez = minrez < 600 + const islowrez = minrez < 600 || FORCE_LOW_REZ RUNTIME.DRAW_CHAR_SCALE = islowrez ? 1 : 2 // config LAYOUT const islandscape = viewwidth > viewheight - const showtouchcontrols = deviceType === 'hybrid' || primaryInput === 'touch' + const showtouchcontrols = + FORCE_TOUCH_UI || deviceType === 'hybrid' || primaryInput === 'touch' // grit texture const splat = useTexture(decoimageurl) diff --git a/zss/gadget/touchui/component.tsx b/zss/gadget/touchui/component.tsx index c798fe5c..fb8caa5a 100644 --- a/zss/gadget/touchui/component.tsx +++ b/zss/gadget/touchui/component.tsx @@ -1,10 +1,15 @@ /* eslint-disable react/no-unknown-property */ -import nipplejs from 'nipplejs' -import { useEffect, useRef } from 'react' +import { radToDeg } from 'maath/misc' +import { useState } from 'react' +import { Vector2 } from 'three' import { RUNTIME } from 'zss/config' -import { tape_terminal_open, vm_input } from 'zss/device/api' +import { + tape_terminal_open, + userinput_down, + userinput_up, +} from 'zss/device/api' import { registerreadplayer } from 'zss/device/register' -import { ispresent } from 'zss/mapping/types' +import { snap } from 'zss/mapping/number' import { WRITE_TEXT_CONTEXT, createwritetextcontext, @@ -13,13 +18,15 @@ import { } from 'zss/words/textformat' import { COLOR } from 'zss/words/types' -import { Clickable } from '../clickable' -import { INPUT } from '../data/types' +import { INPUT, INPUT_SHIFT } from '../data/types' import { ShadeBoxDither } from '../framed/dither' import { useTiles } from '../hooks' +import { Rect } from '../rect' import { useScreenSize } from '../userscreen' import { TilesData, TilesRender } from '../usetiles' +const motion = new Vector2() + export type TouchUIProps = { width: number height: number @@ -27,15 +34,108 @@ export type TouchUIProps = { export function TouchUI({ width, height }: TouchUIProps) { const screensize = useScreenSize() - const sticksref = useRef( - nipplejs.create({ - zone: document.getElementById('frame') ?? undefined, - color: '#00A', - mode: 'dynamic', - dataOnly: true, - }), - ) const player = registerreadplayer() + const [movestick, setmovestick] = useState({ + startx: -1, + starty: -1, + tipx: -1, + tipy: -1, + pointerId: -1 as any, + }) + + function clearmovestick() { + if (movestick.startx !== -1) { + // reset input + handlestickdir(-1) + } + setmovestick({ + startx: -1, + starty: -1, + tipx: -1, + tipy: -1, + pointerId: -1, + }) + } + + function handlestickdir(snapdir: number, shoot = false) { + if (shoot) { + userinput_down('touchui', INPUT.SHIFT, player) + } else { + userinput_up('touchui', INPUT.SHIFT, player) + } + switch (snapdir) { + case -1: + //reset + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + break + case 0: + // left + userinput_down('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + case 45: + // left up + userinput_down('touchui', INPUT.MOVE_UP, player) + userinput_down('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + case 90: + // up + userinput_down('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + break + case 135: + // up right + userinput_down('touchui', INPUT.MOVE_UP, player) + userinput_down('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + case 180: + // right + userinput_down('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + case 225: + // right down + userinput_down('touchui', INPUT.MOVE_DOWN, player) + userinput_down('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + case 270: + // down + userinput_down('touchui', INPUT.MOVE_DOWN, player) + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + break + case 315: + // down left + userinput_down('touchui', INPUT.MOVE_DOWN, player) + userinput_down('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_UP, player) + break + case 360: + // left + userinput_down('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + break + } + } const FG = COLOR.PURPLE const BG = COLOR.ONCLEAR @@ -45,46 +145,6 @@ export function TouchUI({ width, height }: TouchUIProps) { ...store.getState(), } - const BUTTON_WIDTH = 5 - const BUTTON_HEIGHT = 3 - - useEffect(() => { - const { current } = sticksref - if (!ispresent(current)) { - return - } - - function handledirevt(evt: any) { - switch (evt.type) { - case 'removed': - break - case 'dir:up': - vm_input('touchui', INPUT.MOVE_UP, 0, player) - break - case 'dir:down': - vm_input('touchui', INPUT.MOVE_DOWN, 0, player) - break - case 'dir:left': - vm_input('touchui', INPUT.MOVE_LEFT, 0, player) - break - case 'dir:right': - vm_input('touchui', INPUT.MOVE_RIGHT, 0, player) - break - } - } - - current.on('dir:up', handledirevt) - current.on('dir:down', handledirevt) - current.on('dir:left', handledirevt) - current.on('dir:right', handledirevt) - return () => { - current.off('dir:up', handledirevt) - current.off('dir:down', handledirevt) - current.off('dir:left', handledirevt) - current.off('dir:right', handledirevt) - } - }, [player]) - // bail on odd states if (screensize.cols < 10 || screensize.rows < 10) { return null @@ -112,9 +172,62 @@ export function TouchUI({ width, height }: TouchUIProps) { ++context.y } + // + if (movestick.startx !== -1) { + // calc angle + motion.set( + movestick.startx - movestick.tipx, + movestick.starty - movestick.tipy, + ) + if (motion.length() > 42) { + const snapdir = snap(radToDeg(motion.angle()), 45) + handlestickdir(snapdir, false) + } + } + return ( + { + if (movestick.startx === -1) { + setmovestick({ + startx: e.x, + starty: e.y, + tipx: e.x, + tipy: e.y, + pointerId: e.pointerId, + }) + } + }} + onPointerMove={(e) => { + if (e.pointerId === movestick.pointerId) { + setmovestick((state) => ({ + ...state, + tipx: e.x, + tipy: e.y, + })) + } + }} + onPointerUp={() => { + clearmovestick() + // top-left button + // tape_terminal_open('touchui', player) + // top-right button + // vm_input('touchui', INPUT.MENU_BUTTON, 0, player) + // bottom-left button + // vm_input('touchui', INPUT.OK_BUTTON, 0, player) + // bottom-right button + // vm_input('touchui', INPUT.CANCEL_BUTTON, 0, player) + }} + onPointerCancel={() => { + clearmovestick() + }} + /> - - { - // top-left button - tape_terminal_open('touchui', player) - }} - /> - - - { - // top-right button - vm_input('touchui', INPUT.MENU_BUTTON, 0, player) - }} - /> - - - { - // bottom-left button - vm_input('touchui', INPUT.OK_BUTTON, 0, player) - }} - /> - - - { - // bottom-right button - vm_input('touchui', INPUT.CANCEL_BUTTON, 0, player) - }} - /> - ) diff --git a/zss/gadget/userinput.tsx b/zss/gadget/userinput.tsx index 297e5630..5df7d9fa 100644 --- a/zss/gadget/userinput.tsx +++ b/zss/gadget/userinput.tsx @@ -9,9 +9,11 @@ import { useEffect, useState, } from 'react' +import { createdevice } from 'zss/device' import { vm_cli } from 'zss/device/api' import { registerreadplayer } from 'zss/device/register' import { INPUT } from 'zss/gadget/data/types' +import { isnumber } from 'zss/mapping/types' import { ismac } from 'zss/words/system' import { NAME } from 'zss/words/types' @@ -254,6 +256,54 @@ document.addEventListener( { capture: true }, ) +createdevice('userinput', ['tock'], (message) => { + switch (message.target) { + case 'up': + if (isnumber(message.data)) { + inputup(message.data) + } + break + case 'down': + if (isnumber(message.data)) { + inputdown(message.data) + } + break + case 'update': { + const now = performance.now() + const delta = now - previous + + acc += delta + if (acc >= INPUT_RATE) { + acc %= INPUT_RATE + // signal input state + const mods: UserInputMods = { + alt: !!inputstate[INPUT.ALT], + ctrl: !!inputstate[INPUT.CTRL], + shift: !!inputstate[INPUT.SHIFT], + } + const inputs = [ + INPUT.MOVE_UP, + INPUT.MOVE_DOWN, + INPUT.MOVE_LEFT, + INPUT.MOVE_RIGHT, + INPUT.OK_BUTTON, + INPUT.CANCEL_BUTTON, + INPUT.MENU_BUTTON, + ] + inputs.forEach((input) => { + if (inputstate[input]) { + userinputinvoke(input, mods) + } + }) + } + + previous = now + GamepadHelper.update() + break + } + } +}) + // gamepad input const BUTTON_A = 0 @@ -280,9 +330,9 @@ const buttonlookup: Record = { [BUTTON_X]: INPUT.OK_BUTTON, [BUTTON_Y]: INPUT.CANCEL_BUTTON, [BUTTON_LEFT_SHOULDER]: INPUT.ALT, - [BUTTON_RIGHT_SHOULDER]: INPUT.ALT, - [BUTTON_LEFT_TRIGGER]: INPUT.CTRL, - [BUTTON_RIGHT_TRIGGER]: INPUT.CTRL, + [BUTTON_RIGHT_SHOULDER]: INPUT.CTRL, + [BUTTON_LEFT_TRIGGER]: INPUT.SHIFT, + [BUTTON_RIGHT_TRIGGER]: INPUT.SHIFT, [BUTTON_MENU]: INPUT.MENU_BUTTON, [BUTTON_UP]: INPUT.MOVE_UP, [BUTTON_DOWN]: INPUT.MOVE_DOWN, @@ -302,41 +352,6 @@ document.addEventListener('gamepadbuttonup', (event: GamepadEvent) => { inputup(buttonlookup[event.detail.button]) }) -function inputpoll() { - const now = performance.now() - const delta = now - previous - - acc += delta - if (acc >= INPUT_RATE) { - acc %= INPUT_RATE - // signal input state - const mods: UserInputMods = { - alt: !!inputstate[INPUT.ALT], - ctrl: !!inputstate[INPUT.CTRL], - shift: !!inputstate[INPUT.SHIFT], - } - const inputs = [ - INPUT.MOVE_UP, - INPUT.MOVE_DOWN, - INPUT.MOVE_LEFT, - INPUT.MOVE_RIGHT, - INPUT.OK_BUTTON, - INPUT.CANCEL_BUTTON, - INPUT.MENU_BUTTON, - ] - inputs.forEach((input) => { - if (inputstate[input]) { - userinputinvoke(input, mods) - } - }) - } - - previous = now - GamepadHelper.update() - setTimeout(inputpoll, 1) -} -inputpoll() - // mouse && touch input - used to activate :tap labels // components diff --git a/zss/userspace.ts b/zss/userspace.ts index f09270ba..2f764651 100644 --- a/zss/userspace.ts +++ b/zss/userspace.ts @@ -2,6 +2,15 @@ import './device/peer' import './device/gadgetclient' import './device/modem' -import './device/register' import './device/synth' import './device/tape' +import { userinput_update } from './device/api' +import { registerreadplayer } from './device/register' + +function inputpolling() { + const player = registerreadplayer() + userinput_update('userspace', player) + setTimeout(inputpolling, 10) +} + +inputpolling() From 710d03e2567dde065a3afdc41ae00c59fc1885dd Mon Sep 17 00:00:00 2001 From: Automated Version Bump Date: Tue, 31 Dec 2024 09:24:23 +0000 Subject: [PATCH 2/4] ci: version bump to v0.21.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c51c05d1..d6379c7d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zed-software-system", "private": true, - "version": "0.21.11", + "version": "0.21.12", "type": "module", "scripts": { "sloc": "npx sloc zss", From 9dc569a373a67761e2b6c40f0591f1ac12fc4753 Mon Sep 17 00:00:00 2001 From: goldbuick Date: Tue, 31 Dec 2024 06:49:04 -0500 Subject: [PATCH 3/4] working enough touch ui --- zss/gadget/touchui/component.tsx | 158 +++++++++++++++++-------------- 1 file changed, 88 insertions(+), 70 deletions(-) diff --git a/zss/gadget/touchui/component.tsx b/zss/gadget/touchui/component.tsx index fb8caa5a..ca1d0e32 100644 --- a/zss/gadget/touchui/component.tsx +++ b/zss/gadget/touchui/component.tsx @@ -1,12 +1,13 @@ /* eslint-disable react/no-unknown-property */ import { radToDeg } from 'maath/misc' import { useState } from 'react' -import { Vector2 } from 'three' +import { Vector2, Vector3 } from 'three' import { RUNTIME } from 'zss/config' import { tape_terminal_open, userinput_down, userinput_up, + vm_input, } from 'zss/device/api' import { registerreadplayer } from 'zss/device/register' import { snap } from 'zss/mapping/number' @@ -18,7 +19,7 @@ import { } from 'zss/words/textformat' import { COLOR } from 'zss/words/types' -import { INPUT, INPUT_SHIFT } from '../data/types' +import { INPUT } from '../data/types' import { ShadeBoxDither } from '../framed/dither' import { useTiles } from '../hooks' import { Rect } from '../rect' @@ -26,51 +27,76 @@ import { useScreenSize } from '../userscreen' import { TilesData, TilesRender } from '../usetiles' const motion = new Vector2() +const corner = new Vector3() export type TouchUIProps = { width: number height: number } +function ptwithin( + x: number, + y: number, + top: number, + right: number, + bottom: number, + left: number, +) { + return x >= left && x <= right && y >= top && y <= bottom +} + export function TouchUI({ width, height }: TouchUIProps) { const screensize = useScreenSize() const player = registerreadplayer() - const [movestick, setmovestick] = useState({ + const [movestick] = useState({ startx: -1, starty: -1, tipx: -1, tipy: -1, pointerId: -1 as any, }) + // const [drawstick, setdrawstick] = useState(-1) - function clearmovestick() { - if (movestick.startx !== -1) { + function clearmovestick(cx: number, cy: number) { + if (movestick.tipx === -1) { + // check touch targets + if (ptwithin(cx, cy, 3, 6, 6, 1)) { + // top-left button + tape_terminal_open('touchui', player) + console.info('top-left') + } + if (ptwithin(cx, cy, 3, width - 2, 6, width - 6)) { + // top-right button + vm_input('touchui', INPUT.MENU_BUTTON, 0, player) + console.info('top-right') + } + if (ptwithin(cx, cy, height - 5, 6, height - 2, 1)) { + // bottom-left button + vm_input('touchui', INPUT.OK_BUTTON, 0, player) + console.info('bottom-left') + } + if (ptwithin(cx, cy, height - 5, width - 2, height - 2, width - 6)) { + // bottom-right button + vm_input('touchui', INPUT.CANCEL_BUTTON, 0, player) + console.info('bottom-right') + } + } else { // reset input - handlestickdir(-1) + userinput_up('touchui', INPUT.MOVE_UP, player) + userinput_up('touchui', INPUT.MOVE_DOWN, player) + userinput_up('touchui', INPUT.MOVE_LEFT, player) + userinput_up('touchui', INPUT.MOVE_RIGHT, player) } - setmovestick({ - startx: -1, - starty: -1, - tipx: -1, - tipy: -1, - pointerId: -1, - }) + // reset + movestick.startx = -1 + movestick.starty = -1 + movestick.tipx = -1 + movestick.tipy = -1 + movestick.pointerId = -1 } - function handlestickdir(snapdir: number, shoot = false) { - if (shoot) { - userinput_down('touchui', INPUT.SHIFT, player) - } else { - userinput_up('touchui', INPUT.SHIFT, player) - } + function handlestickdir(snapdir: number) { switch (snapdir) { - case -1: - //reset - userinput_up('touchui', INPUT.MOVE_UP, player) - userinput_up('touchui', INPUT.MOVE_DOWN, player) - userinput_up('touchui', INPUT.MOVE_LEFT, player) - userinput_up('touchui', INPUT.MOVE_RIGHT, player) - break case 0: // left userinput_down('touchui', INPUT.MOVE_LEFT, player) @@ -153,36 +179,20 @@ export function TouchUI({ width, height }: TouchUIProps) { // render ui textformatedges(1, 1, width - 2, height - 2, context) - // action button targets + // draw action button targets context.y = 3 for (let i = 0; i < 3; ++i) { context.x = context.active.leftedge = 1 tokenizeandwritetextformat(`$BLUE$177$177$177$177$177`, context, false) context.x = context.active.leftedge = width - 7 - tokenizeandwritetextformat(`$PURPLE$177$177$177$177$177`, context, false) - ++context.y + tokenizeandwritetextformat(`$PURPLE$177$177$177$177$177\n`, context, false) } - context.y = height - 5 for (let i = 0; i < 3; ++i) { context.x = context.active.leftedge = 1 tokenizeandwritetextformat(`$GREEN$177$177$177$177$177`, context, false) context.x = context.active.leftedge = width - 7 - tokenizeandwritetextformat(`$RED$177$177$177$177$177`, context, false) - ++context.y - } - - // - if (movestick.startx !== -1) { - // calc angle - motion.set( - movestick.startx - movestick.tipx, - movestick.starty - movestick.tipy, - ) - if (motion.length() > 42) { - const snapdir = snap(radToDeg(motion.angle()), 45) - handlestickdir(snapdir, false) - } + tokenizeandwritetextformat(`$RED$177$177$177$177$177\n`, context, false) } return ( @@ -195,37 +205,45 @@ export function TouchUI({ width, height }: TouchUIProps) { visible={false} onPointerDown={(e) => { if (movestick.startx === -1) { - setmovestick({ - startx: e.x, - starty: e.y, - tipx: e.x, - tipy: e.y, - pointerId: e.pointerId, - }) + movestick.startx = e.x + movestick.starty = e.y + movestick.tipx = -1 + movestick.tipy = -1 + movestick.pointerId = e.pointerId + } else { + // flag as shooting now + userinput_down('touchui', INPUT.SHIFT, player) } }} onPointerMove={(e) => { if (e.pointerId === movestick.pointerId) { - setmovestick((state) => ({ - ...state, - tipx: e.x, - tipy: e.y, - })) + // calc angle + motion.set(movestick.startx - e.x, movestick.starty - e.y) + if (motion.length() > 42) { + const snapdir = snap(radToDeg(motion.angle()), 45) + // track for visuals + movestick.tipx = e.x + movestick.tipy = e.y + // invoke input directions + handlestickdir(snapdir) + } } }} - onPointerUp={() => { - clearmovestick() - // top-left button - // tape_terminal_open('touchui', player) - // top-right button - // vm_input('touchui', INPUT.MENU_BUTTON, 0, player) - // bottom-left button - // vm_input('touchui', INPUT.OK_BUTTON, 0, player) - // bottom-right button - // vm_input('touchui', INPUT.CANCEL_BUTTON, 0, player) - }} - onPointerCancel={() => { - clearmovestick() + onPointerUp={(e) => { + if (e.pointerId === movestick.pointerId) { + corner.copy(e.intersections[0].point) + e.intersections[0].object.worldToLocal(corner) + const dx = + Math.floor(width * 0.5) + + Math.floor(corner.x / RUNTIME.DRAW_CHAR_WIDTH()) + const dy = + Math.floor(height * 0.5) + + Math.floor(corner.y / RUNTIME.DRAW_CHAR_HEIGHT()) + clearmovestick(dx, dy) + } else { + // flag off shift + userinput_up('touchui', INPUT.SHIFT, player) + } }} /> Date: Tue, 31 Dec 2024 11:49:20 +0000 Subject: [PATCH 4/4] ci: version bump to v0.21.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6379c7d..f24c63db 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zed-software-system", "private": true, - "version": "0.21.12", + "version": "0.21.13", "type": "module", "scripts": { "sloc": "npx sloc zss",