diff --git a/src/EngineSettings.cpp b/src/EngineSettings.cpp index fc360198..732dd78c 100644 --- a/src/EngineSettings.cpp +++ b/src/EngineSettings.cpp @@ -316,6 +316,12 @@ void EngineSettings::Resolutions::load() { infile.close(); } +#ifdef __EMSCRIPTEN__ + // the window is the canvas the page sizes, which can be smaller + min_screen_w = 1; + min_screen_h = 1; +#endif + // prevent the window from being too small if (settings->screen_w < min_screen_w) settings->screen_w = min_screen_w; if (settings->screen_h < min_screen_h) settings->screen_h = min_screen_h; diff --git a/src/GameStatePlay.cpp b/src/GameStatePlay.cpp index d1772706..4c22a6c0 100644 --- a/src/GameStatePlay.cpp +++ b/src/GameStatePlay.cpp @@ -287,9 +287,32 @@ void GameStatePlay::checkLoot() { } +#ifdef __EMSCRIPTEN__ +#include + +// Set while an intermap teleport waits for the play page to download the +// next map's files (Module.wgMapReady), with the loading screen up. +static bool wg_map_wait = false; +// Set for the frame the map loads in, once its files are here. +static bool wg_map_go = false; + +static bool wgMapReady(const std::string& name) { + return EM_ASM_INT({ return Module.wgMapReady ? Module.wgMapReady(UTF8ToString($0)) : 1; }, name.c_str()); +} +#endif + void GameStatePlay::checkTeleport() { bool on_load_teleport = false; +#ifdef __EMSCRIPTEN__ + bool go = wg_map_go; + wg_map_go = false; + if (mapr->teleportation && !mapr->teleport_mapname.empty() && !go && !wgMapReady(mapr->teleport_mapname)) { + wg_map_wait = true; + return; + } +#endif + // both map events and player powers can cause teleportation if (mapr->teleportation || pc->stats.teleportation) { @@ -858,6 +881,15 @@ void GameStatePlay::logic() { if (inpt->window_resized) refreshWidgets(); +#ifdef __EMSCRIPTEN__ + if (wg_map_wait) { + if (!wgMapReady(mapr->teleport_mapname)) + return; + wg_map_wait = false; + wg_map_go = true; + } +#endif + curs->setLowHP(pc->isLowHpCursorEnabled() && pc->isLowHp()); checkCutscene(); @@ -1022,6 +1054,13 @@ void GameStatePlay::logic() { * Render all graphics for a single frame */ void GameStatePlay::render() { +#ifdef __EMSCRIPTEN__ + if (wg_map_wait) { + if (loading_tip) + loading_tip->render(loading_tip_buf, Point(settings->view_w, settings->view_h), TooltipData::STYLE_FLOAT); + return; + } +#endif if (mapr->is_spawn_map) return; diff --git a/src/PlatformEmscripten.cpp b/src/PlatformEmscripten.cpp index 1e82c616..a1bda83f 100644 --- a/src/PlatformEmscripten.cpp +++ b/src/PlatformEmscripten.cpp @@ -20,6 +20,8 @@ FLARE. If not, see http://www.gnu.org/licenses/ #define PLATFORM_CPP #include "Platform.h" +#include "InputState.h" +#include "RenderDevice.h" #include "Settings.h" #include "SharedResources.h" #include "Utils.h" @@ -66,6 +68,9 @@ Platform::Platform() config_input[Platform::Input::JOYSTICK_DEADZONE] = false; config_input[Platform::Input::JOYSTICK_RUMBLE] = false; + config_video[Platform::Video::FULLSCREEN] = false; + config_video[Platform::Video::THREADED_IMAGE_LOAD] = false; + config_misc[Platform::Misc::MODS] = false; } @@ -117,68 +122,39 @@ bool Platform::dirRemove(const std::string& path) { return true; } +// The play page writes the data under / and the player's saves and settings +// under /flare_data before main() runs, and keeps them itself. void Platform::FSInit() { - EM_ASM( - FS.mkdir('/flare_data'); - FS.mount(IDBFS,{},'/flare_data'); - - Module.print("start file sync.."); - Module.syncdone = 0; - - FS.syncfs(true, function(err) { - assert(!err); - Module.print("end file sync.."); - Module.syncdone = 1; - }); - ); + Filesystem::createDir("/flare_data"); } bool Platform::FSCheckReady() { - if(emscripten_run_script_int("Module.syncdone") == 1) { - FILE *config_file = fopen(std::string(settings->path_conf + "settings.txt").c_str(),"r"); - if (config_file == NULL) { - //persist Emscripten current data to Indexed Db - EM_ASM( - Module.print("Start File sync.."); - Module.syncdone = 0; - FS.syncfs(false, function(err) { - assert(!err); - Module.print("End File sync.."); - Module.syncdone = 1; - }); - ); - settings->saveSettings(); - return false; - } - else { - fclose(config_file); - return true; - } - } - return false; + return true; } void Platform::FSCommit() { - EM_ASM( - //persist changes - FS.syncfs(false,function (err) { - assert(!err); - }); - ); } void Platform::setScreenSize() { - // can't change window size dynamically with Emscripten, so default to 16:9 aspect ratio - settings->screen_w = 1920; - settings->screen_h = 1080; + // the play page sizes the canvas (wg_resize below) + settings->screen_w = static_cast(EM_ASM_INT(return Module.wgWidth || 1280;)); + settings->screen_h = static_cast(EM_ASM_INT(return Module.wgHeight || 720;)); settings->fullscreen = false; } -void Platform::setFullscreen(bool enable) { - if (enable) - emscripten_async_run_script("Module.canvas.requestFullscreen();", 0); - else - emscripten_async_run_script("parentDocument.exitFullscreen();", 0); +// full screen is the play page's button +void Platform::setFullscreen(bool) { +} + +// The play page calls this with the canvas size in device pixels. +extern "C" EMSCRIPTEN_KEEPALIVE void wg_resize(int w, int h) { + if (!render_device || !inpt || w <= 0 || h <= 0) return; + SDL_Window* window = SDL_GetWindowFromID(1); + if (!window) return; + SDL_SetWindowMinimumSize(window, 1, 1); + SDL_SetWindowSize(window, w, h); + render_device->windowResize(); + inpt->window_resized = true; } #endif // PLATFORM_CPP diff --git a/src/Settings.cpp b/src/Settings.cpp index f5f9b2c0..c0987b19 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -186,6 +186,11 @@ void Settings::loadSettings() { } } +#ifdef __EMSCRIPTEN__ + // this build has no threads + enable_threaded_image_load = false; +#endif + // Force using the software renderer if safe mode is enabled if (safe_video) { render_device_name = "sdl";