UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

102 lines (84 loc) 3.13 kB
import { event } from "@lincode/events" import IKeyboard, { keyboardDefaults, keyboardSchema } from "../interface/IKeyboard" import EventLoopItem from "./core/EventLoopItem" import { createEffect } from "@lincode/reactivity" import { appendableRoot } from "./core/Appendable" import { onKeyClear } from "../events/onKeyClear" import Nullable from "../interface/utils/Nullable" import { onBeforeRender } from "../events/onBeforeRender" import { getEditing } from "../states/useEditing" import { getEditorMounted } from "../states/useEditorMounted" import { getCameraRendered } from "../states/useCameraRendered" import mainCamera from "../engine/mainCamera" const [emitDown, onDown] = event<string>() const [emitUp, onUp] = event<string>() const [emitPress, onPress] = event() export const isPressed = new Set<string>() const processKey = (str: string) => { str = str.length === 1 ? str.toLocaleLowerCase() : str if (str === " ") str = "Space" return str } createEffect(() => { if ( getEditing() || (getEditorMounted() && getCameraRendered() === mainCamera) ) return const handle = onBeforeRender(() => isPressed.size > 0 && emitPress()) const handleKeyDown = (e: KeyboardEvent): void => { const key = processKey(e.key) isPressed.add(key) emitDown(key) } const handleKeyUp = (e: KeyboardEvent): void => { const key = processKey(e.key) isPressed.delete(key) emitUp(key) !isPressed.size && emitPress() } handle.watch( onKeyClear(() => { if (!isPressed.size) return const pressed = [...isPressed] isPressed.clear() for (const key of pressed) emitUp(key) }) ) document.addEventListener("keydown", handleKeyDown) document.addEventListener("keyup", handleKeyUp) return () => { handle.cancel() document.removeEventListener("keydown", handleKeyDown) document.removeEventListener("keyup", handleKeyUp) } }, [getEditing, getEditorMounted, getCameraRendered]) export class Keyboard extends EventLoopItem implements IKeyboard { public static componentName = "keyboard" public static defaults = keyboardDefaults public static schema = keyboardSchema public onKeyPress: Nullable<(key: string, keys: Set<string>) => void> public onKeyUp: Nullable<(key: string, keys: Set<string>) => void> public onKeyDown: Nullable<(key: string, keys: Set<string>) => void> public constructor() { super() this.watch( onPress(() => { if (!this.onKeyPress) return if (!isPressed.size) { this.onKeyPress("", isPressed) return } for (const key of isPressed) this.onKeyPress(key, isPressed) }) ) this.watch(onUp((key) => this.onKeyUp?.(key, isPressed))) this.watch(onDown((key) => this.onKeyDown?.(key, isPressed))) } } const keyboard = new Keyboard() appendableRoot.delete(keyboard) export default keyboard