import * as React from 'react'; import {HOME_BUTTON_IMAGE} from '/constants'; import {sendKeyDown} from '/packet'; export interface OverlayControlsProps { firstMenuElement: React.RefObject, setHiddenMenu: (c: boolean) => void, webSocket: WebSocket | null; }; interface ControlMap { [id: string]: {key: number, ref: React.RefObject, sym: string, classes: string, transformX?: number, transformY?: number} }; export default function OverlayControls({firstMenuElement, setHiddenMenu, webSocket}: OverlayControlsProps) { function showOverlayMenu() { setHiddenMenu(false); setTimeout(() => { if (firstMenuElement.current == null) { return; } firstMenuElement.current.focus(); }, 100); } const [onGoingTouches, setOnGoingTouches] = React.useState<{[id: string]: number}>({}); function mouseDown(e: React.MouseEvent | React.TouchEvent, key: number) { e.preventDefault(); if (webSocket == null) { console.log('There is not websocket'); return; } sendKeyDown(webSocket, true, key); } function mouseUp(e: React.MouseEvent | React.TouchEvent, key: number) { e.preventDefault(); if (webSocket == null) { console.log('There is not websocket'); return; } sendKeyDown(webSocket, false, key); } const controls: ControlMap = {}; controls.a = { ref: React.useRef(null), key: 0, sym: 'A', classes: 'control-a control-button-a-b control control-button', }; controls.b = { ref: React.useRef(null), key: 1, sym: 'B', transformX: 50, classes: 'control-b control-button-a-b control control-button', }; controls.l = { key: 2, sym: 'L', classes: 'control-l control-button-l-r control', ref: React.useRef(null), }; controls.r = { key: 3, sym: 'R', classes: 'control-r control-button-l-r control', ref: React.useRef(null), }; controls.start = { ref: React.useRef(null), key: 4, sym: 'START', classes: 'control-start control-button-start-select control', transformX: 25, }; controls.select = { ref: React.useRef(null), key: 5, sym: 'SEL', classes: 'control-select control-button-start-select control', transformX: -25, }; controls.up = { ref: React.useRef(null), key: 6, sym: '^', transformX: 100, classes: 'control-up control control-pad-button', } controls.down = { ref: React.useRef(null), key: 7, sym: 'v', transformX: 100, classes: 'control-down control control-pad-button', } controls.left = { ref: React.useRef(null), key: 8, sym: '<', classes: 'control-left control control-pad-button', } controls.right = { ref: React.useRef(null), key: 9, sym: '>', transformX: 200, classes: 'control-right control control-pad-button', } function determineKey(e: React.TouchEvent, touch: React.Touch): number | null { const x = touch.pageX; const y = touch.pageY; for (const control of Object.keys(controls)) { const ref = controls[control].ref.current; if (ref == null) { console.log('No ref found'); continue; } let top = ref.getBoundingClientRect().top + document.documentElement.scrollTop; const currentControl = controls[control]; const transformX = currentControl.transformX; const transformY = currentControl.transformY; let offsetLeft = ref.offsetLeft; const offsetWidth = ref.offsetWidth; let offsetTop = top; const offsetHeight = ref.offsetHeight; if (transformX != null) { offsetLeft += offsetWidth * (transformX / 100); } if (transformY != null) { offsetTop += offsetHeight * (transformY / 100); } console.log(x, y, offsetLeft, offsetTop, offsetWidth, offsetHeight); if (x >= offsetLeft && x <= offsetLeft + offsetWidth && y >= offsetTop && y <= offsetTop + offsetHeight) { return controls[control].key; } } return null; } function touchStartControls(e: React.TouchEvent) { e.preventDefault(); if (webSocket == null) { console.log('There is not websocket'); return; } for (let i = 0; i < e.changedTouches.length; i++) { const touch = e.changedTouches[i]; let key: number|null = determineKey(e, touch); if (key == null) { continue; } const idx = touch.identifier; onGoingTouches[idx] = key; sendKeyDown(webSocket, true, key); } return false; } function touchMoveControls(e: React.TouchEvent) { e.preventDefault(); if (webSocket == null) { console.log('There is not websocket'); return; } for (let i = 0; i < e.changedTouches.length; i++) { const touch = e.changedTouches[i]; let key: number|null = determineKey(e, touch); const idx = touch.identifier; if (key == null) { continue; } if (onGoingTouches[idx] != null) { sendKeyDown(webSocket, false, onGoingTouches[idx]); delete onGoingTouches[idx]; } onGoingTouches[idx] = key; sendKeyDown(webSocket, true, key); } return false; } function touchEndControls(e: React.TouchEvent) { e.preventDefault(); if (webSocket == null) { console.log('There is not websocket'); return; } for (let i = 0; i < e.changedTouches.length; i++) { const touch = e.changedTouches[i]; const idx = touch.identifier; if (onGoingTouches[idx] == null) { return; } sendKeyDown(webSocket, false, onGoingTouches[idx]); delete onGoingTouches[idx]; } return false; } const keyMap: string[] = ["KeyZ", "KeyX", "KeyA", "KeyS", "Enter", "Space", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]; function onPressControl(e: React.KeyboardEvent) { if (webSocket == null) { console.log('There is not websocket'); return; } let key = keyMap.findIndex((c: string) => c == e.code); if (key != -1) { e.preventDefault(); sendKeyDown(webSocket, true, key); } } function onUnpressControl(e: React.KeyboardEvent) { if (webSocket == null) { console.log('There is not websocket'); return; } let key = keyMap.findIndex((c: string) => c == e.code); if (key != -1) { e.preventDefault(); sendKeyDown(webSocket, false, key); } } document.onselectstart = () => false; return ( ); }