make react component
This commit is contained in:
44
src/client/pico8-client/Pico8Console.tsx
Normal file
44
src/client/pico8-client/Pico8Console.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import { css } from "@emotion/css";
|
||||
import { PicoCart, PicoPlayerHandle, makePicoConsole } from "./renderCart";
|
||||
import { ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||
|
||||
type Pico8ConsoleImperatives = {
|
||||
getPicoConsoleHandle(): PicoPlayerHandle | null;
|
||||
}
|
||||
|
||||
export const Pico8Console = forwardRef((props: { carts: PicoCart[] }, forwardedRef: ForwardedRef<Pico8ConsoleImperatives>) => {
|
||||
const {carts} = props;
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [handle, setHandle] = useState<PicoPlayerHandle | null>(null);
|
||||
const attachConsole = useCallback(async () => {
|
||||
const picoConsole = await makePicoConsole({
|
||||
carts,
|
||||
});
|
||||
if (ref.current) {
|
||||
ref.current.appendChild(picoConsole.canvas);
|
||||
}
|
||||
setHandle(picoConsole);
|
||||
}, [carts]);
|
||||
useImperativeHandle(forwardedRef, () => ({
|
||||
getPicoConsoleHandle() {
|
||||
return handle;
|
||||
}
|
||||
}), [handle]);
|
||||
useEffect(() => {
|
||||
attachConsole();
|
||||
}, [attachConsole]);
|
||||
return (
|
||||
<div ref={ref} className={css`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& > canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`}></div>
|
||||
);
|
||||
});
|
@ -1,9 +1,9 @@
|
||||
// @ts-ignore
|
||||
import "./build/veryRawRenderCart.js";
|
||||
|
||||
type PicoBool = 0 | 1;
|
||||
export type PicoBool = 0 | 1;
|
||||
|
||||
type RenderCart = (Module: {canvas: HTMLCanvasElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
||||
export type RenderCart = (Module: {canvas: HTMLCanvasElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
||||
p8_touch_detected?: PicoBool;
|
||||
p8_dropped_cart?: string;
|
||||
p8_dropped_cart_name?: string;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { assertNever } from "@firebox/tsutil";
|
||||
import { pngToRom } from "./pngToRom";
|
||||
import { renderCart as rawRenderCart } from "./rawRenderCart";
|
||||
import { RenderCart, renderCart as rawRenderCart } from "./rawRenderCart";
|
||||
|
||||
type PicoCart = {
|
||||
export type PicoCart = {
|
||||
name: string;
|
||||
src: string;
|
||||
} | {
|
||||
@ -20,7 +20,9 @@ type PlayerButtons = {
|
||||
menu: boolean;
|
||||
}
|
||||
|
||||
type PicoPlayerHandle = {
|
||||
export type PicoPlayerHandle = {
|
||||
raw: ReturnType<RenderCart>;
|
||||
rawModule: unknown;
|
||||
// external things
|
||||
readonly canvas: HTMLCanvasElement;
|
||||
|
||||
@ -35,16 +37,16 @@ type PicoPlayerHandle = {
|
||||
setGamepadCount: (count: number) => void;
|
||||
readonly gpio: number[]; // read + write (should be 256-tuple)
|
||||
|
||||
// state (all communicated out)
|
||||
// state
|
||||
readonly state: {
|
||||
readonly frameNumber: number;
|
||||
readonly isPaused: boolean;
|
||||
readonly hasFocus: boolean;
|
||||
readonly requestPointerLock: boolean;
|
||||
readonly requirePageNavigateConfirmation: boolean;
|
||||
readonly showDpad: boolean;
|
||||
readonly shutdownRequested: boolean;
|
||||
readonly soundVolume: number;
|
||||
frameNumber: number;
|
||||
isPaused: boolean;
|
||||
hasFocus: boolean;
|
||||
requestPointerLock: boolean;
|
||||
requirePageNavigateConfirmation: boolean;
|
||||
showDpad: boolean;
|
||||
shutdownRequested: boolean;
|
||||
soundVolume: number;
|
||||
};
|
||||
|
||||
// misc?
|
||||
@ -109,6 +111,8 @@ export const makePicoConsole = async (props: {
|
||||
];
|
||||
handle.pico8_gamepads = {count: 0};
|
||||
return {
|
||||
raw: handle,
|
||||
rawModule: Module,
|
||||
canvas,
|
||||
state: {
|
||||
frameNumber: handle.pico8_state.frame_number!,
|
||||
|
Reference in New Issue
Block a user