implement action redo

This commit is contained in:
2018-05-10 22:32:34 +02:00
parent f31e22631a
commit 4f55b477da
6 changed files with 66 additions and 2 deletions

View File

@@ -709,6 +709,7 @@
</button-custom> </button-custom>
</node> </node>
<button id="btn-undo" width="50" height="100%" margin="0 5 0 0" text="Undo"/> <button id="btn-undo" width="50" height="100%" margin="0 5 0 0" text="Undo"/>
<button id="btn-redo" width="50" height="100%" margin="0 5 0 0" text="Redo"/>
<!-- <!--
<button-custom id="btn-layer" width="50" height="100%" margin="0 5 0 0" thickness="1" border-color="0 0 0 1" pad="6" align="center" justify="center"> <button-custom id="btn-layer" width="50" height="100%" margin="0 5 0 0" thickness="1" border-color="0 0 0 1" pad="6" align="center" justify="center">
<icon width="100%" height="100%" icon="disk"/> <icon width="100%" height="100%" icon="disk"/>

View File

@@ -7,6 +7,7 @@ ActionManager ActionManager::I;
void ActionManager::add(Action *action) void ActionManager::add(Action *action)
{ {
I.m_redos = std::stack<std::unique_ptr<Action>>();
I.m_actions.emplace(action); I.m_actions.emplace(action);
I.m_memory += action->memory(); I.m_memory += action->memory();
//LOG("History: %.2f KB", I.m_memory / 1024.f); //LOG("History: %.2f KB", I.m_memory / 1024.f);
@@ -15,6 +16,11 @@ void ActionManager::add(Action *action)
void ActionManager::undo() void ActionManager::undo()
{ {
if (I.m_actions.empty())
return;
I.m_redos.emplace(I.m_actions.top()->get_redo());
I.m_actions.top()->undo(); I.m_actions.top()->undo();
I.m_memory -= I.m_actions.top()->memory(); I.m_memory -= I.m_actions.top()->memory();
I.m_actions.pop(); I.m_actions.pop();
@@ -22,6 +28,20 @@ void ActionManager::undo()
App::I.update_memory_usage(I.m_memory); App::I.update_memory_usage(I.m_memory);
} }
void ActionManager::redo()
{
if (I.m_redos.empty())
return;
I.m_actions.emplace(I.m_redos.top()->get_redo());
I.m_memory += I.m_actions.top()->memory();
I.m_redos.top()->undo();
I.m_redos.pop();
//LOG("History: %.2f KB", I.m_memory / 1024.f);
App::I.update_memory_usage(I.m_memory);
}
void ActionManager::clear() void ActionManager::clear()
{ {
while (!I.m_actions.empty()) while (!I.m_actions.empty())

View File

@@ -5,6 +5,7 @@ class Action
public: public:
virtual void run() = 0; virtual void run() = 0;
virtual void undo() = 0; virtual void undo() = 0;
virtual Action* get_redo() = 0;
virtual size_t memory() = 0; virtual size_t memory() = 0;
virtual ~Action(){}; virtual ~Action(){};
}; };
@@ -14,9 +15,11 @@ class ActionManager
public: public:
static ActionManager I; static ActionManager I;
std::stack<std::unique_ptr<Action>> m_actions; std::stack<std::unique_ptr<Action>> m_actions;
std::stack<std::unique_ptr<Action>> m_redos;
size_t m_memory = 0; size_t m_memory = 0;
static void add(Action* action); static void add(Action* action);
static void undo(); static void undo();
static void redo();
static void clear(); static void clear();
static bool empty() static bool empty()
{ {

View File

@@ -55,8 +55,13 @@ void App::init_toolbar_main()
if (auto* button = layout[main_id]->find<NodeButton>("btn-undo")) if (auto* button = layout[main_id]->find<NodeButton>("btn-undo"))
{ {
button->on_click = [this, button](Node*) { button->on_click = [this, button](Node*) {
if (!ActionManager::empty()) ActionManager::undo();
ActionManager::undo(); };
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-redo"))
{
button->on_click = [this, button](Node*) {
ActionManager::redo();
}; };
} }
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-clean-memory")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-clean-memory"))

View File

@@ -160,6 +160,35 @@ void ui::Canvas::snap_history(const std::vector<int>& planes)
action->clear_layer = true; action->clear_layer = true;
ActionManager::add(action); ActionManager::add(action);
} }
ui::ActionStroke* ui::Canvas::create_action(int layer)
{
auto action = new ActionStroke;
for (int i = 0; i < 6; i++)
{
if (!m_layers[layer].m_dirty_face[i])
continue; // no stroke on this face, skip it
m_layers[layer].m_rtt[i].bindFramebuffer();
// save image before commit
glm::vec2 box_or = xy(m_layers[layer].m_dirty_box[i]);
glm::vec2 box_sz = zw(m_layers[layer].m_dirty_box[i]) - xy(m_layers[layer].m_dirty_box[i]);
action->m_image[i] = std::make_unique<uint8_t[]>(box_sz.x * box_sz.y * 4);
glReadPixels(box_or.x, box_or.y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get());
action->m_box[i] = m_layers[layer].m_dirty_box[i];
action->m_old_box[i] = m_layers[layer].m_dirty_box[i];
action->m_old_dirty[i] = m_layers[layer].m_dirty_face[i];
m_layers[layer].m_rtt[i].unbindFramebuffer();
}
// save history
action->m_layer_idx = layer;
action->m_canvas = this;
action->m_stroke = std::move(m_current_stroke);
action->clear_layer = true;
return action;
}
void ui::Canvas::stroke_end() void ui::Canvas::stroke_end()
{ {
if (!m_current_stroke) if (!m_current_stroke)

View File

@@ -131,6 +131,7 @@ public:
void snapshot_save(std::string data_path); void snapshot_save(std::string data_path);
void snapshot_restore(); void snapshot_restore();
void snap_history(const std::vector<int>& planes); void snap_history(const std::vector<int>& planes);
class ActionStroke* create_action(int layer);
void clear_context(); void clear_context();
void import_equirectangular(std::string file_path); void import_equirectangular(std::string file_path);
void import_equirectangular_thread(std::string file_path); void import_equirectangular_thread(std::string file_path);
@@ -174,6 +175,11 @@ public:
virtual void run() override virtual void run() override
{ {
}
virtual Action* get_redo()
{
auto redo = m_canvas->create_action(m_layer_idx);
return redo;
} }
virtual void undo() override virtual void undo() override
{ {