From 8ff0e868cacc979a85318d9d1f05be2ab1c63aab Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Tue, 20 Oct 2020 03:13:10 +0530 Subject: [PATCH] Add image lazy loading --- CMakeLists.txt | 10 +++---- extra/js/drive.js | 63 +++++++++++++++++++++++++++++++++---------- extra/make_mapping.sh | 10 +++++++ extra/shell.html | 5 ++-- src/bitmap.cpp | 39 ++++++++++++++++++++++++--- src/bitmap.h | 7 ++++- src/emscripten.cpp | 4 +-- src/emscripten.hpp | 2 +- src/tilemap.cpp | 11 ++++++++ src/tilemap.h | 1 + 10 files changed, 123 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8495afa..4789a3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,12 +64,12 @@ find_package(PkgConfig REQUIRED) if (EXTERNAL_LIB_PATH) set(CMAKE_PREFIX_PATH ${EXTERNAL_LIB_PATH}) - + if(EXISTS "${EXTERNAL_LIB_PATH}/${LIB_PATH}/pkgconfig/") SET(ENV{PKG_CONFIG_PATH} "${EXTERNAL_LIB_PATH}/${LIB_PATH}/pkgconfig/") endif() if(APPLE) - set(PLATFORM_SHARED_LIBS + set(PLATFORM_SHARED_LIBS libSDL2.dylib libSDL2_image-2.0.0.dylib libSDL2_ttf-2.0.0.dylib libSDL_sound-1.0.1.dylib libfreetype.6.dylib libsigc-2.0.0.dylib CACHE STRING "List of shared libraries that need to be copied into the OS X bundle") @@ -404,7 +404,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE deps/libsigc++ deps/pixman/pixman deps/physfs/src - deps/mruby/include + deps/mruby/include ${SDL2_INCLUDE_DIRS} ${FLUID_INCLUDE_DIRS} @@ -435,11 +435,11 @@ SET(ASYNCIFY "-s ASYNCIFY=1 -s 'ASYNCIFY_IMPORTS=[\"load_file_async_js\"]'") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EMS_FLAGS} ${ERR_FLAGS} ${ASYNCIFY}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EMS_FLAGS} ${ERR_FLAGS} ${ASYNCIFY}") -SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMS_FLAGS} ${ASYNCIFY} -lopenal -s DISABLE_EXCEPTION_CATCHING=1 -s ASSERTIONS=0 -s SAFE_HEAP=0 -s MINIFY_HTML=0 --shell-file extra/shell.html -s EMULATE_FUNCTION_POINTER_CASTS=0 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMS_FLAGS} ${ASYNCIFY} -lopenal -s DISABLE_EXCEPTION_CATCHING=1 -s ASSERTIONS=0 -s SAFE_HEAP=0 -s MINIFY_HTML=0 --shell-file extra/shell.html -s EMULATE_FUNCTION_POINTER_CASTS=0 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s EXPORTED_FUNCTIONS='[\"_main\",\"_reloadBitmap\"]' -s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'") set_target_properties( ${PROJECT_NAME} - PROPERTIES + PROPERTIES OUTPUT_NAME "mkxp" SUFFIX ".html" ) diff --git a/extra/js/drive.js b/extra/js/drive.js index ed8748f..78b0e76 100644 --- a/extra/js/drive.js +++ b/extra/js/drive.js @@ -19,7 +19,13 @@ function _base64ToBytes(base64) { return bytes; } -window.loadFileAsync = function(fullPath, callback) { +// Canvas used for image generation +var generationCanvas = document.createElement('canvas') + +window.loadFileAsync = function(fullPath, bitmap, callback) { + // noop + callback = callback || (() => {}); + // Make cache object if (!window.fileAsyncCache) window.fileAsyncCache = {}; @@ -27,7 +33,7 @@ window.loadFileAsync = function(fullPath, callback) { if (window.fileAsyncCache.hasOwnProperty(fullPath)) return callback(); // Show spinner - if (window.setBusy) window.setBusy(); + if (!bitmap && window.setBusy) window.setBusy(); // Get mapping key const mappingKey = fullPath.toLowerCase().replace(new RegExp("\\.[^/.]+$"), ""); @@ -46,18 +52,47 @@ window.loadFileAsync = function(fullPath, callback) { const path = "/game/" + mappingValue.substring(0, mappingValue.lastIndexOf("/")); const filename = mappingValue.substring(mappingValue.lastIndexOf("/") + 1).split("?")[0]; - // Delete original file if existent - try { - FS.unlink(path + "/" + filename); - } catch (err) {} + // Main loading function + const load = (cb1) => { + getLazyAsset(iurl, filename, (data) => { + // Delete original file if existent + try { FS.unlink(path + "/" + filename); } catch (err) {} - // Get the new file - getLazyAsset(iurl, filename, () => { - FS.createPreloadedFile(path, filename, iurl, true, true, function() { - window.fileAsyncCache[fullPath] = 1; - if (window.setNotBusy) window.setNotBusy(); - if (window.fileLoadedAsync) window.fileLoadedAsync(fullPath); - callback(); + FS.createPreloadedFile(path, filename, new Uint8Array(data), true, true, function() { + window.fileAsyncCache[fullPath] = 1; + if (!bitmap && window.setNotBusy) window.setNotBusy(); + if (window.fileLoadedAsync) window.fileLoadedAsync(fullPath); + callback(); + if (cb1) cb1(); + }, console.error); + }); + } + + // Show progress if doing it synchronously only + if (bitmap && bitmapSizeMapping[mappingKey]) { + // Remove existing file + try { FS.unlink(path + "/" + filename); } catch (err) {} + + // Get image + const sm = bitmapSizeMapping[mappingKey]; + generationCanvas.width = sm[0]; + generationCanvas.height = sm[1]; + + // Create dummy from data uri + FS.createPreloadedFile(path, filename, generationCanvas.toDataURL(), true, true, function() { + // Return control to C++ + callback(); callback = () => {}; + + // Lazy load and refresh + load(() => { + const reloadBitmap = Module.cwrap('reloadBitmap', 'number', ['number']) + reloadBitmap(bitmap); + }); }, console.error); - }); + } else { + if (bitmap) { + console.warn('No sizemap for image', mappingKey); + } + load(); + } } diff --git a/extra/make_mapping.sh b/extra/make_mapping.sh index 8965c86..5ed3acc 100755 --- a/extra/make_mapping.sh +++ b/extra/make_mapping.sh @@ -1,6 +1,7 @@ #!/bin/bash echo "var mapping = {" > mapping.js +echo "var bitmapSizeMapping = {" > bitmap-map.js for file in {*,*/*,*/**/*} do @@ -17,7 +18,16 @@ fi echo "\"$fl\": \"${file}?h=${md5}\"," >> mapping.js +if [ -f $file ] +then + sz=`identify -format "%w,%h" "${file}" 2>/dev/null` + if [ $? -eq 0 ]; then + echo "\"$fl\": [${sz}]," >> bitmap-map.js + fi +fi + done echo "};" >> mapping.js +echo "};" >> bitmap-map.js diff --git a/extra/shell.html b/extra/shell.html index ff790a8..2a0c2d3 100644 --- a/extra/shell.html +++ b/extra/shell.html @@ -8,6 +8,7 @@ + MKXP