#include #include #include #include #include #include #include #include #include using namespace emscripten; App app; GLFWwindow* wnd; float theta = 0; glm::vec2 g_cursor_pos; template class TaskCallback { std::function fn; public: template TaskCallback(T callback) : fn(callback) {} void call(const std::string& tmp_file_path) { fn(tmp_file_path); } void call(bool success) { fn(success); } TaskCallback() { printf("callback created\n"); } ~TaskCallback() { printf("callback destroyed\n"); } }; void TaskCallback_open_call(uintptr_t tc, std::string tmp_file_path) { auto x = reinterpret_cast*>(tc); x->call(tmp_file_path); } void TaskCallback_open_delete(uintptr_t tc) { auto x = reinterpret_cast*>(tc); delete x; } void TaskCallback_save_call(uintptr_t tc, bool success) { auto x = reinterpret_cast*>(tc); x->call(success); } void TaskCallback_save_delete(uintptr_t tc) { auto x = reinterpret_cast*>(tc); delete x; } std::string UtilityGetString(uintptr_t s) { return *reinterpret_cast(s); } kEventSource StringToType(const std::string& type) { if (type == "pen") return kEventSource::Stylus; else if (type == "touch") return kEventSource::Touch; return kEventSource::Mouse; } int ConvertButtonType(int js_button) { if (js_button == 0) return 0; else if (js_button == 2) return 1; return 0; } void CanvasOnPointerDown(std::string type, float x, float y, float f, int button) { app.ui_task_async([=]{ if (button == 0 || button == 2) app.mouse_down(ConvertButtonType(button), x, y, f, StringToType(type), false); }); } void CanvasOnPointerUp(std::string type, float x, float y, int button) { app.ui_task_async([=]{ if (button == 0 || button == 2) app.mouse_up(ConvertButtonType(button), x, y, StringToType(type), false); }); } void CanvasOnPointerMove(std::string type, float x, float y, float f) { g_cursor_pos = { x, y }; app.ui_task_async([=]{ app.mouse_move(x, y, f, StringToType(type), false); }); } void CanvasOnWheel(float y) { app.ui_task_async([=]{ app.mouse_scroll(g_cursor_pos.x, g_cursor_pos.y, y); }); } 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"); function("TaskCallback_save_call", &TaskCallback_save_call); function("TaskCallback_save_delete", &TaskCallback_save_delete); function("TaskCallback_open_call", &TaskCallback_open_call); function("TaskCallback_open_delete", &TaskCallback_open_delete); function("UtilityGetString", &UtilityGetString); function("CanvasOnPointerDown", &CanvasOnPointerDown); function("CanvasOnPointerUp", &CanvasOnPointerUp); function("CanvasOnPointerMove", &CanvasOnPointerMove); function("CanvasOnWheel", &CanvasOnWheel); 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); } 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(); })); } void webgl_pick_file_save(const std::string& path, const std::string& name, std::function callback) { 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(); app.ui_thread_tick(); // theta += 0.1f; // float r = sinf(theta); // glClearColor(r, 0.9f, 0.9f, 1.0f); // glClear(GL_COLOR_BUFFER_BIT); // app.tick(0); // app.update(0); // app.draw(0); // SDL_GL_SwapWindow(wnd); } int main() { if (glfwInit() != GL_TRUE) printf("Failed to init GLFW"); wnd = glfwCreateWindow(1024, 768, "PanoPainter", nullptr, nullptr); glfwMakeContextCurrent(wnd); /* glfwSetCursorPosCallback(wnd, [](GLFWwindow* wnd, double x, double y){ g_cursor_pos = glm::vec2(x, y); app.ui_task_async([=]{ app.mouse_move(x, y, 1.f, kEventSource::Mouse, false); }); }); glfwSetMouseButtonCallback(wnd, [](GLFWwindow* wnd, int button, int action, int mods){ app.ui_task_async([=]{ if (action == GLFW_PRESS) app.mouse_down(button, g_cursor_pos.x, g_cursor_pos.y, 1.f, kEventSource::Mouse, false); else if (action == GLFW_RELEASE) app.mouse_up(button, g_cursor_pos.x, g_cursor_pos.y, kEventSource::Mouse, false); }); }); */ 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); }); }); glfwSetWindowCloseCallback(wnd, [](GLFWwindow* wnd){ app.ui_task([] { if (!app.request_close()) glfwSetWindowShouldClose(app.glfw_window, GLFW_FALSE); }); }); glfwSetWindowRefreshCallback(wnd, [](GLFWwindow* wnd){ app.ui_task_async([=]{ app.redraw = true; }, true); }); EM_ASM ( Module.canvas.onpointermove = function(event) { f = event.pointerType == "pen" ? event.pressure : 1.0; Module.CanvasOnPointerMove(event.pointerType, event.layerX, event.layerY, f); }; Module.canvas.onpointerdown = function(event) { f = event.pointerType == "pen" ? event.pressure : 1.0; Module.CanvasOnPointerDown(event.pointerType, event.layerX, event.layerY, f, event.button); }; Module.canvas.onpointerup = function(event) { Module.CanvasOnPointerUp(event.pointerType, event.layerX, event.layerY, event.button); }; Module.canvas.onwheel = function(event) { event.preventDefault(); Module.CanvasOnWheel(-event.deltaY / 100.0); }; 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(); Module.setCanvasSize(window.innerWidth, window.innerHeight); }); ); printf("GL version: %s\n", glGetString(GL_VERSION)); printf("GL vendor: %s\n", glGetString(GL_VENDOR)); printf("GL renderer: %s\n", glGetString(GL_RENDERER)); printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); LOG("start threads"); //app.render_thread_start(); // app.ui_thread_start(); emscripten_set_main_loop(main_loop, 0, true); printf("hello world 003\n"); return 0; }