diff --git a/src/app.cpp b/src/app.cpp index d5e93b4..70b2640 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -239,13 +239,14 @@ void App::initLog() mkpath(data_path + "/settings"); mkpath(data_path + "/frames"); #elif __WEB__ - data_path = "/"; - mkdir("/brushes", 0777); - mkdir("/brushes/thumbs", 0777); - mkdir("/patterns", 0777); - mkdir("/patterns/thumbs", 0777); - mkdir("/settings", 0777); - mkdir("/frames", 0777); + data_path = "/PanoPainter"; + mkdir(data_path.c_str(), 0777); + mkdir((data_path + "/brushes").c_str(), 0777); + mkdir((data_path + "/brushes/thumbs").c_str(), 0777); + mkdir((data_path + "/patterns").c_str(), 0777); + mkdir((data_path + "/patterns/thumbs").c_str(), 0777); + mkdir((data_path + "/settings").c_str(), 0777); + mkdir((data_path + "/frames").c_str(), 0777); #endif // TODO: save this path somewhere in the settings, don't overwrite every start diff --git a/src/app_dialogs.cpp b/src/app_dialogs.cpp index 297d855..3c2233c 100644 --- a/src/app_dialogs.cpp +++ b/src/app_dialogs.cpp @@ -16,6 +16,7 @@ void webgl_pick_file(std::function callback); void webgl_pick_file_save(const std::string& path, const std::string& name, std::function callback); +void webgl_sync(); #endif std::shared_ptr App::show_progress(const std::string& title, int total /*= 0*/) diff --git a/src/app_events.cpp b/src/app_events.cpp index 41351ea..fd01662 100644 --- a/src/app_events.cpp +++ b/src/app_events.cpp @@ -21,6 +21,7 @@ std::string win32_clipboard_get_text(); void webgl_pick_file(std::function callback); void webgl_pick_file_save(const std::string& path, const std::string& name, std::function callback); +void webgl_sync(); #endif diff --git a/src/canvas.cpp b/src/canvas.cpp index f9b1e66..a9b6861 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -9,6 +9,8 @@ #ifdef __APPLE__ #include #import "objc_utils.h" +#elif __WEB__ +void webgl_sync(); #endif @@ -2180,6 +2182,9 @@ bool Canvas::project_save_thread(std::string file_path, bool show_progress) { m_unsaved = false; m_newdoc = false; +#if __WEB__ + webgl_sync(); +#endif } if (show_progress) diff --git a/src/keymap.h b/src/keymap.h index b3392fe..939925d 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -656,6 +656,128 @@ kKey convert_key(int key) CASE(AKEYCODE_BRIGHTNESS_DOWN, kKey::Unknown); CASE(AKEYCODE_BRIGHTNESS_UP, kKey::Unknown); CASE(AKEYCODE_MEDIA_AUDIO_TRACK, kKey::Unknown); +#elif __WEB__ + CASE(GLFW_KEY_UNKNOWN, kKey::Unknown); + CASE(GLFW_KEY_SPACE, kKey::KeySpacebar); + CASE(GLFW_KEY_APOSTROPHE, kKey::Unknown); + CASE(GLFW_KEY_COMMA, kKey::Unknown); + CASE(GLFW_KEY_MINUS, kKey::Unknown); + CASE(GLFW_KEY_PERIOD, kKey::Unknown); + CASE(GLFW_KEY_SLASH, kKey::Unknown); + CASE(GLFW_KEY_0, kKey::Key0); + CASE(GLFW_KEY_1, kKey::Key1); + CASE(GLFW_KEY_2, kKey::Key2); + CASE(GLFW_KEY_3, kKey::Key3); + CASE(GLFW_KEY_4, kKey::Key4); + CASE(GLFW_KEY_5, kKey::Key5); + CASE(GLFW_KEY_6, kKey::Key6); + CASE(GLFW_KEY_7, kKey::Key7); + CASE(GLFW_KEY_8, kKey::Key8); + CASE(GLFW_KEY_9, kKey::Key9); + CASE(GLFW_KEY_SEMICOLON, kKey::Unknown); + CASE(GLFW_KEY_EQUAL, kKey::Unknown); + CASE(GLFW_KEY_A, kKey::KeyA); + CASE(GLFW_KEY_B, kKey::KeyB); + CASE(GLFW_KEY_C, kKey::KeyC); + CASE(GLFW_KEY_D, kKey::KeyD); + CASE(GLFW_KEY_E, kKey::KeyE); + CASE(GLFW_KEY_F, kKey::KeyF); + CASE(GLFW_KEY_G, kKey::KeyG); + CASE(GLFW_KEY_H, kKey::KeyH); + CASE(GLFW_KEY_I, kKey::KeyI); + CASE(GLFW_KEY_J, kKey::KeyJ); + CASE(GLFW_KEY_K, kKey::KeyK); + CASE(GLFW_KEY_L, kKey::KeyL); + CASE(GLFW_KEY_M, kKey::KeyM); + CASE(GLFW_KEY_N, kKey::KeyN); + CASE(GLFW_KEY_O, kKey::KeyO); + CASE(GLFW_KEY_P, kKey::KeyP); + CASE(GLFW_KEY_Q, kKey::KeyQ); + CASE(GLFW_KEY_R, kKey::KeyR); + CASE(GLFW_KEY_S, kKey::KeyS); + CASE(GLFW_KEY_T, kKey::KeyT); + CASE(GLFW_KEY_U, kKey::KeyU); + CASE(GLFW_KEY_V, kKey::KeyV); + CASE(GLFW_KEY_W, kKey::KeyW); + CASE(GLFW_KEY_X, kKey::KeyX); + CASE(GLFW_KEY_Y, kKey::KeyY); + CASE(GLFW_KEY_Z, kKey::KeyZ); + CASE(GLFW_KEY_LEFT_BRACKET, kKey::Unknown); + CASE(GLFW_KEY_BACKSLASH, kKey::Unknown); + CASE(GLFW_KEY_RIGHT_BRACKET, kKey::Unknown); + CASE(GLFW_KEY_GRAVE_ACCENT, kKey::Unknown); + CASE(GLFW_KEY_WORLD_1, kKey::Unknown); + CASE(GLFW_KEY_WORLD_2, kKey::Unknown); + CASE(GLFW_KEY_ESCAPE, kKey::Unknown); + CASE(GLFW_KEY_ENTER, kKey::Unknown); + CASE(GLFW_KEY_TAB, kKey::KeyTab); + CASE(GLFW_KEY_BACKSPACE, kKey::KeyBackspace); + CASE(GLFW_KEY_INSERT, kKey::Unknown); + CASE(GLFW_KEY_DELETE, kKey::KeyDel); + CASE(GLFW_KEY_RIGHT, kKey::Unknown); + CASE(GLFW_KEY_LEFT, kKey::Unknown); + CASE(GLFW_KEY_DOWN, kKey::Unknown); + CASE(GLFW_KEY_UP, kKey::Unknown); + CASE(GLFW_KEY_PAGE_UP, kKey::Unknown); + CASE(GLFW_KEY_PAGE_DOWN, kKey::Unknown); + CASE(GLFW_KEY_HOME, kKey::Unknown); + CASE(GLFW_KEY_END, kKey::Unknown); + CASE(GLFW_KEY_CAPS_LOCK, kKey::Unknown); + CASE(GLFW_KEY_SCROLL_LOCK, kKey::Unknown); + CASE(GLFW_KEY_NUM_LOCK, kKey::Unknown); + CASE(GLFW_KEY_PRINT_SCREEN, kKey::Unknown); + CASE(GLFW_KEY_PAUSE, kKey::Unknown); + CASE(GLFW_KEY_F1, kKey::Unknown); + CASE(GLFW_KEY_F2, kKey::Unknown); + CASE(GLFW_KEY_F3, kKey::Unknown); + CASE(GLFW_KEY_F4, kKey::Unknown); + CASE(GLFW_KEY_F5, kKey::Unknown); + CASE(GLFW_KEY_F6, kKey::Unknown); + CASE(GLFW_KEY_F7, kKey::Unknown); + CASE(GLFW_KEY_F8, kKey::Unknown); + CASE(GLFW_KEY_F9, kKey::Unknown); + CASE(GLFW_KEY_F10, kKey::Unknown); + CASE(GLFW_KEY_F11, kKey::Unknown); + CASE(GLFW_KEY_F12, kKey::Unknown); + CASE(GLFW_KEY_F13, kKey::Unknown); + CASE(GLFW_KEY_F14, kKey::Unknown); + CASE(GLFW_KEY_F15, kKey::Unknown); + CASE(GLFW_KEY_F16, kKey::Unknown); + CASE(GLFW_KEY_F17, kKey::Unknown); + CASE(GLFW_KEY_F18, kKey::Unknown); + CASE(GLFW_KEY_F19, kKey::Unknown); + CASE(GLFW_KEY_F20, kKey::Unknown); + CASE(GLFW_KEY_F21, kKey::Unknown); + CASE(GLFW_KEY_F22, kKey::Unknown); + CASE(GLFW_KEY_F23, kKey::Unknown); + CASE(GLFW_KEY_F24, kKey::Unknown); + CASE(GLFW_KEY_F25, kKey::Unknown); + CASE(GLFW_KEY_KP_0, kKey::Unknown); + CASE(GLFW_KEY_KP_1, kKey::Unknown); + CASE(GLFW_KEY_KP_2, kKey::Unknown); + CASE(GLFW_KEY_KP_3, kKey::Unknown); + CASE(GLFW_KEY_KP_4, kKey::Unknown); + CASE(GLFW_KEY_KP_5, kKey::Unknown); + CASE(GLFW_KEY_KP_6, kKey::Unknown); + CASE(GLFW_KEY_KP_7, kKey::Unknown); + CASE(GLFW_KEY_KP_8, kKey::Unknown); + CASE(GLFW_KEY_KP_9, kKey::Unknown); + CASE(GLFW_KEY_KP_DECIMAL, kKey::Unknown); + CASE(GLFW_KEY_KP_DIVIDE, kKey::Unknown); + CASE(GLFW_KEY_KP_MULTIPLY, kKey::Unknown); + CASE(GLFW_KEY_KP_SUBTRACT, kKey::Unknown); + CASE(GLFW_KEY_KP_ADD, kKey::Unknown); + CASE(GLFW_KEY_KP_ENTER, kKey::Unknown); + CASE(GLFW_KEY_KP_EQUAL, kKey::Unknown); + CASE(GLFW_KEY_LEFT_SHIFT, kKey::Unknown); + CASE(GLFW_KEY_LEFT_CONTROL, kKey::Unknown); + CASE(GLFW_KEY_LEFT_ALT, kKey::Unknown); + CASE(GLFW_KEY_LEFT_SUPER, kKey::Unknown); + CASE(GLFW_KEY_RIGHT_SHIFT, kKey::Unknown); + CASE(GLFW_KEY_RIGHT_CONTROL, kKey::Unknown); + CASE(GLFW_KEY_RIGHT_ALT, kKey::Unknown); + CASE(GLFW_KEY_RIGHT_SUPER, kKey::Unknown); + CASE(GLFW_KEY_MENU, kKey::Unknown); #endif default: return kKey::Unknown; diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index 94cc83b..8794115 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -6,7 +6,10 @@ #ifdef __APPLE__ #include +#elif __WEB__ +void webgl_sync(); #endif + #include "canvas.h" #include "app.h" #include "abr.h" @@ -266,6 +269,10 @@ bool NodePanelBrush::save() sw << *b; } f.write((char*)sw.m_data.data(), sw.m_data.size()); + f.close(); +#if __WEB__ + webgl_sync(); +#endif return true; } return false; diff --git a/webgl/CMakeLists.txt b/webgl/CMakeLists.txt index 73ca270..6d0147d 100644 --- a/webgl/CMakeLists.txt +++ b/webgl/CMakeLists.txt @@ -94,7 +94,7 @@ add_executable(panopainter ../src/node_input_box.cpp ../src/node_dialog_export_ppbr.cpp ) -target_compile_options(panopainter PRIVATE -std=c++14 -O2) +target_compile_options(panopainter PRIVATE -std=c++14 -O3) set_target_properties(panopainter PROPERTIES SUFFIX ".html" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/html" @@ -105,8 +105,6 @@ set_target_properties(panopainter PROPERTIES -s USE_PTHREADS=1\ -s ASSERTIONS=2\ -s TOTAL_MEMORY=256Mb\ - -s ALLOW_MEMORY_GROWTH=1\ - -s WASM_MEM_MAX=512MB\ --embed-file data\ --js-library ../src/mylib.js\ --bind" diff --git a/webgl/src/main.cpp b/webgl/src/main.cpp index 065584b..c8a1bd9 100644 --- a/webgl/src/main.cpp +++ b/webgl/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace emscripten; @@ -105,6 +106,22 @@ void CanvasOnPointerMove(std::string type, float x, float y, float f) }); } +void StartApp() +{ + App::I = &app; + app.initLog(); + app.create(); + app.width = 1024; + app.height = 768; + app.glfw_window = wnd; + + // app.render_thread_tick(); + // app.ui_thread_tick(); + app.ui_task_async([]{ + app.init(); + }); +} + EMSCRIPTEN_BINDINGS(TaskCallback_bind) { class_>("TaskCallbackOpen"); class_>("TaskCallbackSave"); @@ -116,9 +133,11 @@ EMSCRIPTEN_BINDINGS(TaskCallback_bind) { function("CanvasOnPointerDown", &CanvasOnPointerDown); function("CanvasOnPointerUp", &CanvasOnPointerUp); function("CanvasOnPointerMove", &CanvasOnPointerMove); + function("StartApp", &StartApp); } extern "C" { +extern void js_sync(); extern void js_pick_file(TaskCallback* tc); extern void js_pick_file_save(std::string path, std::string name, TaskCallback* tc); } @@ -128,6 +147,7 @@ void webgl_pick_file(std::function callback) js_pick_file(new TaskCallback([callback](std::string tmp_file_path){ printf("callback called: %s\n", tmp_file_path.c_str()); callback(tmp_file_path); + js_sync(); })); } @@ -137,9 +157,17 @@ void webgl_pick_file_save(const std::string& path, js_pick_file_save(path, name, new TaskCallback([callback](bool success){ printf("save callback called: %s\n", success ? "ok" : "failed"); callback(success); + js_sync(); })); } +void webgl_sync() +{ + app.ui_task_async([]{ + js_sync(); + }); +} + void main_loop() { app.render_thread_tick(); @@ -178,6 +206,25 @@ int main() }); }); */ + glfwSetKeyCallback(wnd, [](GLFWwindow* wnd, int key, int scancode, int action, int mods){ + app.ui_task_async([=]{ + if (action == GLFW_PRESS) + app.key_down(convert_key(key)); + else if (action == GLFW_RELEASE) + app.key_up(convert_key(key)); + }); + }); + glfwSetCharCallback(wnd, [](GLFWwindow* wnd, unsigned int codepoint){ + std::wstring_convert, char32_t> converter; + std::string u8str = converter.to_bytes(codepoint); + if (!u8str.empty()) + { + app.ui_task_async([c=u8str[0]]{ + app.key_char(c); + }); + } + LOG("codepoint: %du -> %s", codepoint, u8str.c_str()); + }); glfwSetWindowSizeCallback(wnd, [](GLFWwindow* wnd, int width, int height){ app.ui_task_async([=]{ app.resize(width, height); @@ -209,6 +256,14 @@ int main() Module.CanvasOnPointerUp(event.pointerType, event.layerX, event.layerY, event.button); }; Module.canvas.style.touchAction = 'none'; + Module.js_fs_synching = false; + FS.mkdir('/PanoPainter'); + FS.mount(IDBFS, {}, '/PanoPainter'); + FS.syncfs(true, function (err) { + console.log("syncFS result:"); + console.log(err); + Module.StartApp(); + }); ); printf("GL version: %s\n", glGetString(GL_VERSION)); @@ -216,19 +271,6 @@ int main() printf("GL renderer: %s\n", glGetString(GL_RENDERER)); printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); - App::I = &app; - app.initLog(); - app.create(); - app.width = 1024; - app.height = 768; - app.glfw_window = wnd; - - // app.render_thread_tick(); - // app.ui_thread_tick(); - app.ui_task_async([]{ - app.init(); - }); - LOG("start threads"); //app.render_thread_start(); // app.ui_thread_start(); diff --git a/webgl/src/mylib.js b/webgl/src/mylib.js index 9eccab1..f381d9a 100644 --- a/webgl/src/mylib.js +++ b/webgl/src/mylib.js @@ -1,3 +1,13 @@ +function js_sync() { + if (Module.js_fs_synching) + return; + Module.js_fs_synching = true; + FS.syncfs(function (err) { + console.log("syncFS result:"); + console.log(err); + Module.js_fs_synching = false; + }); +} function js_pick_file(fn) { var input = document.createElement('input'); input.type = 'file'; @@ -55,6 +65,7 @@ function js_pick_file_save(path, name, fn) { } mergeInto(LibraryManager.library, { + js_sync: js_sync, js_pick_file: js_pick_file, js_pick_file_save: js_pick_file_save, });