Skip to content

Commit

Permalink
working enough touch ui
Browse files Browse the repository at this point in the history
  • Loading branch information
goldbuick committed Dec 31, 2024
1 parent 710d03e commit 9dc569a
Showing 1 changed file with 88 additions and 70 deletions.
158 changes: 88 additions & 70 deletions zss/gadget/touchui/component.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -18,59 +19,84 @@ 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'
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)
Expand Down Expand Up @@ -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 (
Expand All @@ -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)
}
}}
/>
<ShadeBoxDither
Expand Down

0 comments on commit 9dc569a

Please sign in to comment.