diff --git a/engine/action.cpp b/engine/action.cpp index 2461e8d..552f3c7 100644 --- a/engine/action.cpp +++ b/engine/action.cpp @@ -20,12 +20,15 @@ void ActionManager::undo() return; I.m_redos.emplace(I.m_actions.top()->get_redo()); + I.m_redos.top()->was_saved = !ui::Canvas::I->m_unsaved; I.m_actions.top()->undo(); I.m_memory -= I.m_actions.top()->memory(); + ui::Canvas::I->m_unsaved = !I.m_actions.top()->was_saved; I.m_actions.pop(); //LOG("History: %.2f KB", I.m_memory / 1024.f); App::I.update_memory_usage(I.m_memory); + App::I.title_update(); } void ActionManager::redo() @@ -34,12 +37,15 @@ void ActionManager::redo() return; I.m_actions.emplace(I.m_redos.top()->get_redo()); + I.m_actions.top()->was_saved = !ui::Canvas::I->m_unsaved; I.m_memory += I.m_actions.top()->memory(); I.m_redos.top()->undo(); + ui::Canvas::I->m_unsaved = !I.m_redos.top()->was_saved; I.m_redos.pop(); //LOG("History: %.2f KB", I.m_memory / 1024.f); App::I.update_memory_usage(I.m_memory); + App::I.title_update(); } void ActionManager::clear() diff --git a/engine/action.h b/engine/action.h index 4057834..4532298 100644 --- a/engine/action.h +++ b/engine/action.h @@ -3,6 +3,7 @@ class Action { public: + bool was_saved = false; virtual void run() = 0; virtual void undo() = 0; virtual Action* get_redo() = 0; diff --git a/engine/app.cpp b/engine/app.cpp index 0a32898..158d83c 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -40,21 +40,23 @@ bool App::request_close() async_start(); auto* m = layout[main_id]->add_child(); m->m_title->set_text("Unsaved document"); - m->m_message->set_text("Would you like to save before closing?"); + m->m_message->set_text("Do you want to close without saving?"); m->btn_ok->m_text->set_text("Yes"); m->btn_ok->on_click = [](Node*) { - }; - m->btn_cancel->m_text->set_text("No"); - m->btn_cancel->on_click = [this](Node*) { - #ifdef _WIN32 +#ifdef _WIN32 destroy_window(); PostQuitMessage(0); - #endif - #ifdef __OSX__ +#endif +#ifdef __OSX__ [osx_view close]; - #endif +#endif ui::Canvas::I->m_unsaved = false; }; + m->btn_cancel->m_text->set_text("No"); + m->btn_cancel->on_click = [this,m](Node*) { + m->destroy(); + dialog_already_opened = false; + }; async_redraw(); async_end(); dialog_already_opened = true; @@ -267,7 +269,7 @@ void App::init() initShaders(); initAssets(); initLayout(); - + title_update(); GLfloat width_range[2]; glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, width_range); diff --git a/engine/app.h b/engine/app.h index f09ee6a..60f44ab 100644 --- a/engine/app.h +++ b/engine/app.h @@ -64,7 +64,7 @@ public: Node* current_panel = nullptr; NodeScroll* panels; const uint16_t main_id = const_hash("main"); - std::string doc_name; + std::string doc_name = "no-name"; float width; float height; bool keys[256]; @@ -155,7 +155,7 @@ public: std::shared_ptr show_progress(const std::string& title); void brush_update(); - void title_update(std::string name, int resolution); + void title_update(); void update_memory_usage(size_t bytes); void update_rec_frames(); diff --git a/engine/app_cloud.cpp b/engine/app_cloud.cpp index dd242db..f9e7081 100644 --- a/engine/app_cloud.cpp +++ b/engine/app_cloud.cpp @@ -146,7 +146,7 @@ void App::cloud_browse() async_start(); doc_name = dialog->selected_name; - title_update(doc_name, canvas->m_canvas->m_width); + title_update(); for (auto& i : canvas->m_canvas->m_order) layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str()); ActionManager::clear(); diff --git a/engine/app_dialogs.cpp b/engine/app_dialogs.cpp index 72c34ae..ee41822 100644 --- a/engine/app_dialogs.cpp +++ b/engine/app_dialogs.cpp @@ -42,7 +42,7 @@ void App::dialog_newdoc() std::array resolutions{512, 1024, 1536, 2048}; int res = resolutions[dialog->m_resolution->m_current_index]; doc_name = name; - title_update(name, res); + title_update(); layers->clear(); canvas->m_canvas->m_layers.clear(); @@ -109,7 +109,7 @@ void App::dialog_open() canvas->m_canvas->project_open(dialog->selected_path, [this] { // on complete async_start(); - title_update(doc_name, canvas->m_canvas->m_width); + title_update(); for (auto& i : canvas->m_canvas->m_order) layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str()); async_end(); @@ -143,7 +143,7 @@ void App::dialog_browse() canvas->m_canvas->project_open(dialog->selected_path, [this] { // on complete async_start(); - title_update(doc_name, canvas->m_canvas->m_width); + title_update(); for (auto& i : canvas->m_canvas->m_order) layers->add_layer(canvas->m_canvas->m_layers[i].m_name.c_str()); async_end(); @@ -179,7 +179,7 @@ void App::dialog_save_ver() } doc_name = next; - title_update(doc_name, canvas->m_canvas->m_width); + title_update(); canvas->m_canvas->project_save(data_path + "/" + next + ".pano"); } @@ -214,7 +214,7 @@ void App::dialog_save() auto action = [this, dialog, name, path] { doc_name = name; - title_update(doc_name, canvas->m_canvas->m_width); + title_update(); canvas->m_canvas->project_save(path); dialog->destroy(); App::I.hideKeyboard(); diff --git a/engine/app_layout.cpp b/engine/app_layout.cpp index 30cc77c..d2faafa 100644 --- a/engine/app_layout.cpp +++ b/engine/app_layout.cpp @@ -11,10 +11,10 @@ using namespace ui; static glm::vec4 color_button_normal{ .1, .1, .1, 1 }; static glm::vec4 color_button_hlight{ 1, .0, .0, 1 }; -void App::title_update(std::string name, int resolution) +void App::title_update() { static char str[256]; - snprintf(str, 256, "Panodoc: %s%s (%dpx)", doc_name.c_str(), canvas->m_canvas->m_unsaved ? "*" : "", resolution); + snprintf(str, 256, "Panodoc: %s%s (%dpx)", doc_name.c_str(), canvas->m_canvas->m_unsaved ? "*" : "", canvas->m_canvas->m_width); if (auto docname = layout[main_id]->find("txt-docname")) docname->set_text(str); } diff --git a/engine/canvas.cpp b/engine/canvas.cpp index d3faa59..7f5e5b8 100644 --- a/engine/canvas.cpp +++ b/engine/canvas.cpp @@ -135,10 +135,13 @@ void ui::Canvas::clear(const glm::vec4& c/*={0,0,0,1}*/) { snap_history({ 0, 1, 2, 3, 4, 5 }); m_layers[m_current_layer_idx].clear(c); + m_unsaved = true; + App::I.title_update(); } void ui::Canvas::snap_history(const std::vector& planes) { auto action = new ActionStroke; + action->was_saved = !m_unsaved; for (auto i : planes) { if (!m_layers[m_current_layer_idx].m_dirty_face[i]) @@ -462,7 +465,7 @@ void ui::Canvas::stroke_commit() { if (!m_dirty || m_layers.empty()) return; - m_unsaved = true; + m_dirty = false; m_dirty_stroke = true; // new stroke ready for timelapse capture App::I.redraw = true; @@ -476,7 +479,11 @@ void ui::Canvas::stroke_commit() // allocate action to add to history auto action = new ActionStroke; - + action->was_saved = !m_unsaved; + + m_unsaved = true; + App::I.title_update(); + // prepare common states glViewport(0, 0, m_width, m_height); glDisable(GL_BLEND); @@ -854,6 +861,7 @@ void ui::Canvas::import_equirectangular_thread(std::string file_path) gl_state gl; gl.save(); snap_history({0,1,2,3,4,5}); + m_unsaved = true; Image img; img.load_file(file_path); diff --git a/engine/main.cpp b/engine/main.cpp index c41d37b..5a1c992 100644 --- a/engine/main.cpp +++ b/engine/main.cpp @@ -671,6 +671,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) break; } } + + // avoid annoying alt system menu + if (wp == SC_KEYMENU && (lp >> 16) <= 0) return 0; + return DefWindowProc(hWnd, msg, wp, lp); } diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp index f965165..e71fd03 100644 --- a/engine/node_canvas.cpp +++ b/engine/node_canvas.cpp @@ -13,6 +13,7 @@ void NodeCanvas::init() m_mouse_ignore = false; m_canvas = std::make_unique(); m_canvas->create(CANVAS_RES, CANVAS_RES); + m_canvas->m_unsaved = false; m_sampler.create(GL_NEAREST); m_sampler_linear.create(GL_LINEAR); m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);