diff --git a/data/layout.xml b/data/layout.xml
index 75025cc..4e92493 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -96,7 +96,7 @@
-
+
diff --git a/src/app.cpp b/src/app.cpp
index a19e2e8..d5e93b4 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -26,6 +26,8 @@ void destroy_window();
#elif __LINUX__
std::string linux_home_path();
int mkpath(const std::string& dir, mode_t mode = DEFFILEMODE);
+#elif __WEB__
+#include
#endif
App* App::I = nullptr; // singleton
@@ -52,7 +54,7 @@ void App::create()
void App::open_document(std::string path)
{
- std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
+ std::regex r(R"((.*)[\\/]?([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return;
@@ -236,6 +238,14 @@ void App::initLog()
mkpath(data_path + "/patterns/thumbs");
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);
#endif
// TODO: save this path somewhere in the settings, don't overwrite every start
diff --git a/src/app_events.cpp b/src/app_events.cpp
index c5c57ac..96f92ac 100644
--- a/src/app_events.cpp
+++ b/src/app_events.cpp
@@ -15,8 +15,10 @@ void win32_show_cursor(bool visible);
bool win32_clipboard_set_text(const std::string & s);
std::string win32_clipboard_get_text();
#elif __APPLE__
-#else
+#elif __LINUX__
#include
+#elif __WEB__
+void webgl_pick_file(std::function callback);
#endif
@@ -149,6 +151,11 @@ void App::pick_image(std::function callback)
std::string path = win32_open_file("Image Files (*.jpg, *.png)\0*.jpg;*.png");
if (!path.empty())
callback(path);
+#elif __LINUX__
+ if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false))
+ callback(p);
+#elif __WEB__
+ webgl_pick_file(callback);
#endif
}
@@ -196,6 +203,8 @@ void App::pick_file(std::vector types, std::functionon_click = [this](Node*) {
App::I->pick_file({ "JPG", "PNG" }, [this](std::string path) {
std::string name, base, ext;
- std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
+ std::regex r(R"((.*)[\\/]?([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return;
@@ -546,7 +546,7 @@ void NodePanelBrushPreset::init()
});
};
m_btn_download = find("download");
- m_btn_download->on_click = [] (Node*) {
+ m_btn_download->on_click = [this] (Node*) {
App::I->dialog_preset_download();
};
m_notification = find("notification");
@@ -701,7 +701,7 @@ bool NodePanelBrushPreset::export_ppbr(const std::string& path_in, const PPBRInf
path += ".ppbr";
LOG("export ppbr to: %s", path.c_str());
- std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)?$)");
+ std::regex r(R"((.*)[\\/]?([^\\/]+)\.(\w+)?$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return false;
@@ -965,7 +965,7 @@ bool NodePanelBrushPreset::import_abr(const std::string& path)
LOG("ABR detected");
std::string name, base, ext;
- std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
+ std::regex r(R"((.*)[\\/]?([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return false;
@@ -1035,7 +1035,7 @@ bool NodePanelBrushPreset::import_abr(const std::string& path)
bool NodePanelBrushPreset::import_brush(const std::string& path)
{
- std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
+ std::regex r(R"((.*)[\\/]?([^\\/]+)\.(\w+)$)");
std::smatch m;
if (!std::regex_search(path, m, r))
return false;
diff --git a/webgl/CMakeLists.txt b/webgl/CMakeLists.txt
index 4e4cc27..73ca270 100644
--- a/webgl/CMakeLists.txt
+++ b/webgl/CMakeLists.txt
@@ -1,136 +1,130 @@
cmake_minimum_required(VERSION 3.4.1)
project(panopainter)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
- -std=c++14 -O2 \
- -s USE_GLFW=3 \
- -s USE_WEBGL2=1 \
- -s FULL_ES3=1 \
- -s USE_PTHREADS=1 \
- -s ASSERTIONS=2 \
- -s TOTAL_MEMORY=64Mb \
- -s ALLOW_MEMORY_GROWTH=1 \
- -s WASM_MEM_MAX=512MB \
-")
add_executable(panopainter
src/main.cpp
- ../libs/yoga/yoga/log.cpp
- ../libs/yoga/yoga/Utils.cpp
- ../libs/yoga/yoga/YGConfig.cpp
- ../libs/yoga/yoga/YGEnums.cpp
- ../libs/yoga/yoga/YGLayout.cpp
- ../libs/yoga/yoga/YGMarker.cpp
- ../libs/yoga/yoga/YGNode.cpp
- ../libs/yoga/yoga/YGNodePrint.cpp
- ../libs/yoga/yoga/YGStyle.cpp
- ../libs/yoga/yoga/YGValue.cpp
- ../libs/yoga/yoga/Yoga.cpp
- ../libs/tinyxml2/tinyxml2.cpp
- ../libs/jpeg/jpgd.cpp
- ../libs/jpeg/jpge.cpp
- ../libs/poly2tri/poly2tri/common/shapes.cc
- ../libs/poly2tri/poly2tri/sweep/advancing_front.cc
- ../libs/poly2tri/poly2tri/sweep/cdt.cc
- ../libs/poly2tri/poly2tri/sweep/sweep_context.cc
- ../libs/poly2tri/poly2tri/sweep/sweep.cc
- ../libs/fmt/src/format.cc
- ../src/pch.cpp
- ../src/util.cpp
- ../src/rtt.cpp
- ../src/bezier.cpp
- ../src/asset.cpp
- ../src/image.cpp
- ../src/texture.cpp
- ../src/font.cpp
- ../src/shader.cpp
- ../src/shape.cpp
- ../src/app.cpp
- ../src/app_cloud.cpp
- ../src/app_dialogs.cpp
- ../src/app_events.cpp
- ../src/app_layout.cpp
- ../src/app_shaders.cpp
+ ../libs/yoga/yoga/log.cpp
+ ../libs/yoga/yoga/Utils.cpp
+ ../libs/yoga/yoga/YGConfig.cpp
+ ../libs/yoga/yoga/YGEnums.cpp
+ ../libs/yoga/yoga/YGLayout.cpp
+ ../libs/yoga/yoga/YGMarker.cpp
+ ../libs/yoga/yoga/YGNode.cpp
+ ../libs/yoga/yoga/YGNodePrint.cpp
+ ../libs/yoga/yoga/YGStyle.cpp
+ ../libs/yoga/yoga/YGValue.cpp
+ ../libs/yoga/yoga/Yoga.cpp
+ ../libs/tinyxml2/tinyxml2.cpp
+ ../libs/jpeg/jpgd.cpp
+ ../libs/jpeg/jpge.cpp
+ ../libs/poly2tri/poly2tri/common/shapes.cc
+ ../libs/poly2tri/poly2tri/sweep/advancing_front.cc
+ ../libs/poly2tri/poly2tri/sweep/cdt.cc
+ ../libs/poly2tri/poly2tri/sweep/sweep_context.cc
+ ../libs/poly2tri/poly2tri/sweep/sweep.cc
+ ../libs/fmt/src/format.cc
+ ../src/pch.cpp
+ ../src/util.cpp
+ ../src/rtt.cpp
+ ../src/bezier.cpp
+ ../src/asset.cpp
+ ../src/image.cpp
+ ../src/texture.cpp
+ ../src/font.cpp
+ ../src/shader.cpp
+ ../src/shape.cpp
+ ../src/app.cpp
+ ../src/app_cloud.cpp
+ ../src/app_dialogs.cpp
+ ../src/app_events.cpp
+ ../src/app_layout.cpp
+ ../src/app_shaders.cpp
../src/app_vr.cpp
- ../src/brush.cpp
- ../src/canvas.cpp
- ../src/canvas_layer.cpp
- ../src/canvas_actions.cpp
- ../src/canvas_modes.cpp
- ../src/log.cpp
- ../src/action.cpp
- ../src/layout.cpp
- ../src/version.cpp
- ../src/node.cpp
- ../src/node_about.cpp
- ../src/node_border.cpp
- ../src/node_button.cpp
- ../src/node_button_custom.cpp
- ../src/node_canvas.cpp
- ../src/node_checkbox.cpp
- ../src/node_color_quad.cpp
- ../src/node_colorwheel.cpp
- ../src/node_combobox.cpp
- ../src/node_changelog.cpp
- ../src/node_dialog_browse.cpp
- ../src/node_dialog_cloud.cpp
- ../src/node_dialog_open.cpp
- ../src/node_dialog_picker.cpp
- ../src/node_dialog_layer_rename.cpp
- ../src/node_dialog_resize.cpp
- ../src/node_icon.cpp
- ../src/node_image.cpp
- ../src/node_image_texture.cpp
- ../src/node_message_box.cpp
- ../src/node_panel_brush.cpp
- ../src/node_panel_color.cpp
- ../src/node_panel_grid.cpp
+ ../src/brush.cpp
+ ../src/canvas.cpp
+ ../src/canvas_layer.cpp
+ ../src/canvas_actions.cpp
+ ../src/canvas_modes.cpp
+ ../src/log.cpp
+ ../src/action.cpp
+ ../src/layout.cpp
+ ../src/version.cpp
+ ../src/node.cpp
+ ../src/node_about.cpp
+ ../src/node_border.cpp
+ ../src/node_button.cpp
+ ../src/node_button_custom.cpp
+ ../src/node_canvas.cpp
+ ../src/node_checkbox.cpp
+ ../src/node_color_quad.cpp
+ ../src/node_colorwheel.cpp
+ ../src/node_combobox.cpp
+ ../src/node_changelog.cpp
+ ../src/node_dialog_browse.cpp
+ ../src/node_dialog_cloud.cpp
+ ../src/node_dialog_open.cpp
+ ../src/node_dialog_picker.cpp
+ ../src/node_dialog_layer_rename.cpp
+ ../src/node_dialog_resize.cpp
+ ../src/node_icon.cpp
+ ../src/node_image.cpp
+ ../src/node_image_texture.cpp
+ ../src/node_message_box.cpp
+ ../src/node_panel_brush.cpp
+ ../src/node_panel_color.cpp
+ ../src/node_panel_grid.cpp
../src/node_panel_floating.cpp
- ../src/node_panel_layer.cpp
- ../src/node_panel_stroke.cpp
+ ../src/node_panel_layer.cpp
+ ../src/node_panel_stroke.cpp
../src/node_panel_quick.cpp
- ../src/node_popup_menu.cpp
- ../src/node_progress_bar.cpp
- ../src/node_settings.cpp
- ../src/node_slider.cpp
- ../src/node_stroke_preview.cpp
- ../src/node_text.cpp
- ../src/node_text_input.cpp
+ ../src/node_popup_menu.cpp
+ ../src/node_progress_bar.cpp
+ ../src/node_settings.cpp
+ ../src/node_slider.cpp
+ ../src/node_stroke_preview.cpp
+ ../src/node_text.cpp
+ ../src/node_text_input.cpp
../src/node_tool_bucket.cpp
- ../src/node_usermanual.cpp
- ../src/node_viewport.cpp
- ../src/node_scroll.cpp
- ../src/abr.cpp
- ../src/binary_stream.cpp
- ../src/serializer.cpp
- ../src/settings.cpp
- ../src/node_input_box.cpp
- ../src/node_dialog_export_ppbr.cpp
+ ../src/node_usermanual.cpp
+ ../src/node_viewport.cpp
+ ../src/node_scroll.cpp
+ ../src/abr.cpp
+ ../src/binary_stream.cpp
+ ../src/serializer.cpp
+ ../src/settings.cpp
+ ../src/node_input_box.cpp
+ ../src/node_dialog_export_ppbr.cpp
+)
+target_compile_options(panopainter PRIVATE -std=c++14 -O2)
+set_target_properties(panopainter PROPERTIES
+ SUFFIX ".html"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/html"
+ LINK_FLAGS "\
+ -s USE_GLFW=3\
+ -s USE_WEBGL2=1\
+ -s FULL_ES3=1\
+ -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"
)
-set_target_properties(panopainter PROPERTIES SUFFIX ".html")
-set_target_properties(panopainter PROPERTIES LINK_FLAGS "\
- --embed-file data \
- -s USE_GLFW=3 \
- -s USE_WEBGL2=1 \
- -s FULL_ES3=1 \
- -s USE_PTHREADS=1 \
- -s ASSERTIONS=2 \
- -s TOTAL_MEMORY=64Mb \
- -s ALLOW_MEMORY_GROWTH=1 \
- -s WASM_MEM_MAX=512MB \
-")
target_include_directories(panopainter PRIVATE
src
- ../src
- ../libs/glm
- ../libs/tinyxml2
- ../libs/yoga
- ../libs/stb
- ../libs/jpeg
- ../libs/poly2tri/poly2tri
- ../libs/base64
- ../libs/sqlite3
- ../libs/nanort
- ../libs/hash-library
- ../libs/fmt/include
- ../libs/glad/include
- ../libs/tinyfiledialogs
+ ../src
+ ../libs/glm
+ ../libs/tinyxml2
+ ../libs/yoga
+ ../libs/stb
+ ../libs/jpeg
+ ../libs/poly2tri/poly2tri
+ ../libs/base64
+ ../libs/sqlite3
+ ../libs/nanort
+ ../libs/hash-library
+ ../libs/fmt/include
+ ../libs/glad/include
+ ../libs/tinyfiledialogs
)
diff --git a/webgl/src/main.cpp b/webgl/src/main.cpp
index e484e17..f1d7dd8 100644
--- a/webgl/src/main.cpp
+++ b/webgl/src/main.cpp
@@ -1,16 +1,68 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+using namespace emscripten;
+
App app;
GLFWwindow* wnd;
float theta = 0;
glm::vec2 g_cursor_pos;
+class TaskCallback
+{
+ std::function fn;
+public:
+ template TaskCallback(T callback) : fn(callback) {}
+ void call(const std::string& tmp_file_path)
+ {
+ fn(tmp_file_path);
+ }
+ TaskCallback()
+ {
+ printf("callback created\n");
+ }
+ ~TaskCallback()
+ {
+ printf("callback destroyed\n");
+ }
+};
+
+void TaskCallback_call(uintptr_t tc, std::string tmp_file_path)
+{
+ auto x = reinterpret_cast(tc);
+ x->call(tmp_file_path);
+}
+
+void TaskCallback_delete(uintptr_t tc)
+{
+ auto x = reinterpret_cast(tc);
+ delete x;
+}
+
+EMSCRIPTEN_BINDINGS(TaskCallback_bind) {
+ class_("TaskCallback");
+ function("TaskCallback_call", &TaskCallback_call);
+ function("TaskCallback_delete", &TaskCallback_delete);
+}
+
+extern "C" {
+extern void js_pick_file(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);
+ }));
+}
+
void main_loop()
{
app.render_thread_tick();
@@ -30,7 +82,7 @@ int main()
{
if (glfwInit() != GL_TRUE)
printf("Failed to init GLFW");
- wnd = glfwCreateWindow(800, 600, "hello", nullptr, nullptr);
+ wnd = glfwCreateWindow(1024, 768, "PanoPainter", nullptr, nullptr);
glfwMakeContextCurrent(wnd);
glfwSetCursorPosCallback(wnd, [](GLFWwindow* wnd, double x, double y){
@@ -72,8 +124,8 @@ int main()
App::I = &app;
app.initLog();
app.create();
- app.width = 800;
- app.height = 600;
+ app.width = 1024;
+ app.height = 768;
app.glfw_window = wnd;
// app.render_thread_tick();
diff --git a/webgl/src/mylib.js b/webgl/src/mylib.js
new file mode 100644
index 0000000..b57765b
--- /dev/null
+++ b/webgl/src/mylib.js
@@ -0,0 +1,28 @@
+function js_pick_file(fn) {
+ var input = document.createElement('input');
+ input.type = 'file';
+
+ input.onchange = function(e) {
+ // getting a hold of the file reference
+ var file = e.target.files[0];
+
+ // setting up the reader
+ var reader = new FileReader();
+ reader.readAsArrayBuffer(file);
+ //reader.readAsText(file,'UTF-8');
+ // here we tell the reader what to do when it's done reading...
+ reader.onload = function(readerEvent) {
+ console.log("reader.onload " + file.name);
+ var content = new Uint8Array(readerEvent.target.result); // this is the content!
+ console.log( content );
+ FS.writeFile(file.name, content);
+ Module.TaskCallback_call(fn, file.name);
+ Module.TaskCallback_delete(fn);
+ }
+ }
+
+ input.click();
+}
+mergeInto(LibraryManager.library, {
+ js_pick_file: js_pick_file,
+});