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>
</node>
<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">
<icon width="100%" height="100%" icon="disk"/>

View File

@@ -7,6 +7,7 @@ ActionManager ActionManager::I;
void ActionManager::add(Action *action)
{
I.m_redos = std::stack<std::unique_ptr<Action>>();
I.m_actions.emplace(action);
I.m_memory += action->memory();
//LOG("History: %.2f KB", I.m_memory / 1024.f);
@@ -15,6 +16,11 @@ void ActionManager::add(Action *action)
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_memory -= I.m_actions.top()->memory();
I.m_actions.pop();
@@ -22,6 +28,20 @@ void ActionManager::undo()
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()
{
while (!I.m_actions.empty())

View File

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

View File

@@ -55,8 +55,13 @@ void App::init_toolbar_main()
if (auto* button = layout[main_id]->find<NodeButton>("btn-undo"))
{
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"))

View File

@@ -160,6 +160,35 @@ void ui::Canvas::snap_history(const std::vector<int>& planes)
action->clear_layer = true;
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()
{
if (!m_current_stroke)

View File

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