From b281218ab87c476f54cb3eba4ad7810bf4dfbb76 Mon Sep 17 00:00:00 2001 From: mumra Date: Sat, 8 Mar 2025 23:55:52 +0000 Subject: [PATCH] set initial size correctly --- crawl-ref/source/main.cc | 2 +- crawl-ref/source/web/public/vite.svg | 1 + crawl-ref/source/web/src/Module.ts | 127 ++++++++++++++++++++++ crawl-ref/source/web/src/Spinner.tsx | 60 ++++++++++ crawl-ref/source/web/src/assets/react.svg | 1 + crawl-ref/source/web/src/atoms/state.ts | 11 ++ crawl-ref/source/web/src/reset.css | 80 ++++++++++++++ crawl-ref/source/web/src/useScript.ts | 21 ++++ crawl-ref/source/windowmanager-sdl.cc | 16 ++- 9 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 crawl-ref/source/web/public/vite.svg create mode 100644 crawl-ref/source/web/src/Module.ts create mode 100644 crawl-ref/source/web/src/Spinner.tsx create mode 100644 crawl-ref/source/web/src/assets/react.svg create mode 100644 crawl-ref/source/web/src/atoms/state.ts create mode 100644 crawl-ref/source/web/src/reset.css create mode 100644 crawl-ref/source/web/src/useScript.ts diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 6b38dae1388..4fc4f59af83 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -30,7 +30,7 @@ #endif #ifdef __EMSCRIPTEN__ -#include +# include #endif #include "ability.h" diff --git a/crawl-ref/source/web/public/vite.svg b/crawl-ref/source/web/public/vite.svg new file mode 100644 index 00000000000..e7b8dfb1b2a --- /dev/null +++ b/crawl-ref/source/web/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crawl-ref/source/web/src/Module.ts b/crawl-ref/source/web/src/Module.ts new file mode 100644 index 00000000000..8e3f4b8c7a0 --- /dev/null +++ b/crawl-ref/source/web/src/Module.ts @@ -0,0 +1,127 @@ +import { useSetAtom, useStore, atom } from "jotai"; +import { + hasErrorAtom, + progressAtom, + progressTotalAtom, + showSpinnerAtom, + statusAtom, +} from "./atoms/state"; +import { RefObject, useEffect, useRef } from "react"; + +declare global { + interface Window { + Module: EmscriptenModule; + } +} + +type CrawlEmscriptenModule = Partial< + EmscriptenModule & { + canvas: HTMLCanvasElement; + monitorRunDependencies: (left: number) => void; + setStatus: (text: string) => void; + } +>; + +const moduleInstanceAtom = atom({ + print(...args: unknown[]) { + console.log(...args); + // These replacements are necessary if you render to raw HTMLaw + //text = text.replace(/&/g, "&"); + //text = text.replace(//g, ">"); + //text = text.replace('\n', '
', 'g'); + // if (outputElement) { + // var text = args.join(" "); + // outputElement.value += text + "\n"; + // outputElement.scrollTop = outputElement.scrollHeight; // focus on bottom + // } + }, +}); + +const moduleAtom = atom( + (get) => get(moduleInstanceAtom), + (get, set, update: CrawlEmscriptenModule) => { + const nextModule = { ...window.Module, ...update }; + window.Module = nextModule; + set(moduleInstanceAtom, nextModule); + } +); + +export const useModule = (canvasRef: RefObject) => { + const setStatus = useSetAtom(statusAtom); + const setShowSpinner = useSetAtom(showSpinnerAtom); + const setProgress = useSetAtom(progressAtom); + const setProgressTotal = useSetAtom(progressTotalAtom); + const setModule = useSetAtom(moduleAtom); + const setHasError = useSetAtom(hasErrorAtom); + const store = useStore(); + const initialised = useRef(false); + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas || initialised.current) return; + initialised.current = true; + setModule({ + print: (...args: unknown[]) => { + console.log(...args); + }, + canvas, + setStatus(text: string) { + console.log(text); + setStatus(text); + }, + monitorRunDependencies(left: number) { + if (left == 0) { + setShowSpinner(false); + setStatus("All downloads complete."); + return; + } + let total = store.get(progressTotalAtom); + if (total === 0) { + total = left; + setProgressTotal(total); + } + setProgress(total - left); + setProgressTotal(left); + setStatus("Preparing... (" + (total - left) + "/" + total + ")"); + }, + onRuntimeInitialized: () => { + // store.get(moduleInstanceAtom).resize(window.innerWidth, window.innerHeight); + } + }); + // As a default initial behavior, pop up an alert when webgl context is lost. To make your + // application robust, you may want to override this behavior before shipping! + // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2 + canvasRef.current.addEventListener( + "webglcontextlost", + (e) => { + alert("WebGL context lost. You will need to reload the page."); + e.preventDefault(); + }, + false + ); + window.onerror = (event) => { + // TODO: do not warn on ok events like simulating an infinite loop or exitStatus + setHasError(true); + console.error(event); + setStatus("Exception thrown, see JavaScript console"); + }; + window.addEventListener("resize", ()=> { + // store.get(moduleInstanceAtom).resize(window.innerWidth, window.innerHeight); + }) + const script = document.createElement("script"); + + script.async = true; + script.src = "/crawl.js"; + + document.body.appendChild(script); + }, [ + canvasRef, + setHasError, + setModule, + setProgress, + setProgressTotal, + setShowSpinner, + setStatus, + store, + ]); +}; diff --git a/crawl-ref/source/web/src/Spinner.tsx b/crawl-ref/source/web/src/Spinner.tsx new file mode 100644 index 00000000000..1f3d7c0534e --- /dev/null +++ b/crawl-ref/source/web/src/Spinner.tsx @@ -0,0 +1,60 @@ +import styled from "@emotion/styled"; + +export const Spinner = styled.div` + position: absolute; + top: 0; + right: 0; + height: 30px; + width: 30px; + margin: 0; + margin-top: 20px; + margin-left: 20px; + display: inline-block; + vertical-align: top; + + -webkit-animation: rotation 0.8s linear infinite; + -moz-animation: rotation 0.8s linear infinite; + -o-animation: rotation 0.8s linear infinite; + animation: rotation 0.8s linear infinite; + + border-left: 5px solid rgb(235, 235, 235); + border-right: 5px solid rgb(235, 235, 235); + border-bottom: 5px solid rgb(235, 235, 235); + border-top: 5px solid rgb(120, 120, 120); + + border-radius: 100%; + background-color: rgb(189, 215, 46); + + @-webkit-keyframes rotation { + from { + -webkit-transform: rotate(0deg); + } + to { + -webkit-transform: rotate(360deg); + } + } + @-moz-keyframes rotation { + from { + -moz-transform: rotate(0deg); + } + to { + -moz-transform: rotate(360deg); + } + } + @-o-keyframes rotation { + from { + -o-transform: rotate(0deg); + } + to { + -o-transform: rotate(360deg); + } + } + @keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } +`; diff --git a/crawl-ref/source/web/src/assets/react.svg b/crawl-ref/source/web/src/assets/react.svg new file mode 100644 index 00000000000..6c87de9bb33 --- /dev/null +++ b/crawl-ref/source/web/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crawl-ref/source/web/src/atoms/state.ts b/crawl-ref/source/web/src/atoms/state.ts new file mode 100644 index 00000000000..5c288c19d04 --- /dev/null +++ b/crawl-ref/source/web/src/atoms/state.ts @@ -0,0 +1,11 @@ +import { atom } from "jotai"; + +export const statusAtom = atom("Downloading..."); + +export const showSpinnerAtom = atom(true); + +export const progressAtom = atom(0) + +export const progressTotalAtom = atom(0) + +export const hasErrorAtom = atom(false) diff --git a/crawl-ref/source/web/src/reset.css b/crawl-ref/source/web/src/reset.css new file mode 100644 index 00000000000..fffd207b829 --- /dev/null +++ b/crawl-ref/source/web/src/reset.css @@ -0,0 +1,80 @@ +html,body { + margin:0;padding:0; +} + +// https://piccalil.li/blog/a-more-modern-css-reset/ +// https://creativecommons.org/licenses/by/3.0/ + +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Prevent font size inflation */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +/* Remove default margin in favour of better control in authored CSS */ +body, h1, h2, h3, h4, p, +figure, blockquote, dl, dd { + margin-block-end: 0; +} + +/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ +ul[role='list'], +ol[role='list'] { + list-style: none; +} + +/* Set core body defaults */ +body { + min-height: 100vh; + line-height: 1.5; +} + +/* Set shorter line heights on headings and interactive elements */ +h1, h2, h3, h4, +button, input, label { + line-height: 1.1; +} + +/* Balance text wrapping on headings */ +h1, h2, +h3, h4 { + text-wrap: balance; +} + +/* A elements that don't have a class get default styles */ +a:not([class]) { + text-decoration-skip-ink: auto; + color: currentColor; +} + +/* Make images easier to work with */ +img, +picture { + max-width: 100%; + display: block; +} + +/* Inherit fonts for inputs and buttons */ +input, button, +textarea, select { + font-family: inherit; + font-size: inherit; +} + +/* Make sure textareas without a rows attribute are not tiny */ +textarea:not([rows]) { + min-height: 10em; +} + +/* Anything that has been anchored to should have extra scroll margin */ +:target { + scroll-margin-block: 5ex; +} diff --git a/crawl-ref/source/web/src/useScript.ts b/crawl-ref/source/web/src/useScript.ts new file mode 100644 index 00000000000..af4f0598af4 --- /dev/null +++ b/crawl-ref/source/web/src/useScript.ts @@ -0,0 +1,21 @@ +import { useEffect } from "react"; + +const useScript = (url: string, loadCondition: boolean) => { + useEffect(() => { + if (!loadCondition) { + return; + } + const script = document.createElement("script"); + + script.async = true; + script.src = url; + + document.body.appendChild(script); + + return () => { + document.body.removeChild(script); + }; + }, [url, loadCondition]); +}; + +export default useScript; diff --git a/crawl-ref/source/windowmanager-sdl.cc b/crawl-ref/source/windowmanager-sdl.cc index 830349d31dc..4a4beaac9c6 100644 --- a/crawl-ref/source/windowmanager-sdl.cc +++ b/crawl-ref/source/windowmanager-sdl.cc @@ -453,6 +453,16 @@ SDLWrapper::~SDLWrapper() SDL_Quit(); } +#ifdef __EMSCRIPTEN__ +EM_JS(int, _browser_viewport_width, (), { + return window.innerWidth; +}); + +EM_JS(int, _browser_viewport_height, (), { + return window.innerHeight; +}); +#endif + int SDLWrapper::init(coord_def *m_windowsz) { // Do SDL initialization @@ -488,9 +498,13 @@ int SDLWrapper::init(coord_def *m_windowsz) SDL_DisplayMode display_mode; SDL_GetDesktopDisplayMode(cur_display, &display_mode); - +#ifdef __EMSCRIPTEN + _desktop_width = _browser_viewport_width(); + _desktop_height = _browser_viewport_height(); +#else _desktop_width = display_mode.w; _desktop_height = display_mode.h; +#endif #ifdef __ANDROID__ SDL_StartTextInput();