add history to layer create, delete, move, rename, and merge
This commit is contained in:
@@ -55,10 +55,10 @@ void App::open_document(std::string path)
|
||||
{
|
||||
async_start();
|
||||
title_update();
|
||||
for (auto& i : canvas->m_canvas->m_order)
|
||||
for (int layer_index = 0; layer_index < canvas->m_canvas->m_layers.size(); layer_index++)
|
||||
{
|
||||
auto l = layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str(), false);
|
||||
l->m_visibility->set_value(canvas->m_canvas->m_layers[i]->m_visible);
|
||||
auto l = layers->add_layer(canvas->m_canvas->m_layers[layer_index]->m_name.c_str(), false);
|
||||
l->m_visibility->set_value(canvas->m_canvas->m_layers[layer_index]->m_visible);
|
||||
}
|
||||
async_end();
|
||||
}
|
||||
|
||||
@@ -169,8 +169,8 @@ void App::cloud_browse()
|
||||
async_start();
|
||||
doc_name = dialog->selected_name;
|
||||
title_update();
|
||||
for (auto& i : canvas->m_canvas->m_order)
|
||||
layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str(), false);
|
||||
for (auto& l : canvas->m_canvas->m_layers)
|
||||
layers->add_layer(l->m_name.c_str(), false);
|
||||
ActionManager::clear();
|
||||
m->destroy();
|
||||
async_redraw();
|
||||
|
||||
@@ -114,12 +114,11 @@ void App::dialog_newdoc()
|
||||
|
||||
layers->clear();
|
||||
canvas->m_canvas->m_layers.clear();
|
||||
canvas->m_canvas->m_order.clear();
|
||||
canvas->m_canvas->resize(res, res);
|
||||
canvas->reset_camera();
|
||||
ActionManager::clear();
|
||||
|
||||
layers->add_layer("Default", false);
|
||||
layers->add_layer("Default", false, true);
|
||||
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
canvas->m_canvas->m_newdoc = false;
|
||||
@@ -536,8 +535,32 @@ void App::dialog_layer_rename()
|
||||
|
||||
dialog->btn_ok->on_click = [this,dialog](Node*)
|
||||
{
|
||||
layers->m_current_layer->set_name(dialog->get_name().c_str());
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_current_layer_idx]->m_name = dialog->get_name();
|
||||
struct ActionLayerRename : public Action
|
||||
{
|
||||
std::string m_old_name;
|
||||
std::string m_new_name;
|
||||
bool m_unsaved;
|
||||
Layer* m_layer;
|
||||
std::shared_ptr<NodeLayer> m_layer_node;
|
||||
ActionLayerRename(std::string old_name, std::string new_name, std::shared_ptr<NodeLayer> layer_node, Layer* layer) :
|
||||
m_old_name(old_name), m_new_name(new_name), m_layer_node(layer_node), m_layer(layer) { }
|
||||
virtual void run() override { }
|
||||
virtual size_t memory() override { return 0; }
|
||||
virtual void undo() override
|
||||
{
|
||||
m_layer_node->set_name(m_old_name.c_str());
|
||||
m_layer->m_name = m_old_name;
|
||||
}
|
||||
virtual Action* get_redo() override
|
||||
{
|
||||
return new ActionLayerRename(m_new_name, m_old_name, m_layer_node, m_layer);
|
||||
}
|
||||
};
|
||||
auto layer_node = std::static_pointer_cast<NodeLayer>(layers->m_current_layer->shared_from_this());
|
||||
auto* layer = canvas->m_canvas->m_layers[canvas->m_canvas->m_current_layer_idx].get();
|
||||
ActionManager::add(new ActionLayerRename(layers->m_current_layer->m_label_text, dialog->get_name(), layer_node, layer));
|
||||
layer_node->set_name(dialog->get_name().c_str());
|
||||
layer->m_name = dialog->get_name();
|
||||
dialog->destroy();
|
||||
App::I.hideKeyboard();
|
||||
};
|
||||
|
||||
@@ -166,16 +166,16 @@ void App::init_sidebar()
|
||||
brush_update();
|
||||
};
|
||||
|
||||
layers->on_layer_add = [this](Node*, std::unique_ptr<class Layer> layer, int index) {
|
||||
canvas->m_canvas->layer_add(layers->m_layers.back()->m_label_text.c_str(), std::move(layer), index);
|
||||
layers->on_layer_add = [this](Node*, std::shared_ptr<class Layer> layer, int index) {
|
||||
canvas->m_canvas->layer_add(layers->m_layers.back()->m_label_text.c_str(), layer, index);
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
title_update();
|
||||
};
|
||||
|
||||
layers->on_layer_duplicate = [this](Node*, int source_index) {
|
||||
Canvas::I->layer_add(layers->m_layers.back()->m_label_text.c_str());
|
||||
auto& dst = Canvas::I->m_layers.back();
|
||||
auto& src = Canvas::I->m_layers[Canvas::I->m_order[source_index]];
|
||||
Canvas::I->layer_add(layers->m_layers.back()->m_label_text.c_str(), nullptr, source_index + 1);
|
||||
auto& dst = Canvas::I->m_layers[source_index + 1];
|
||||
auto& src = Canvas::I->m_layers[source_index];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!src->m_dirty_face[i])
|
||||
@@ -192,7 +192,7 @@ void App::init_sidebar()
|
||||
};
|
||||
|
||||
layers->on_layer_change = [this](Node*, int old_idx, int new_idx) {
|
||||
canvas->m_canvas->m_current_layer_idx = canvas->m_canvas->m_order[new_idx];
|
||||
canvas->m_canvas->m_current_layer_idx = new_idx;
|
||||
};
|
||||
|
||||
layers->on_layer_order = [this](Node*, int old_idx, int new_idx) {
|
||||
@@ -208,31 +208,31 @@ void App::init_sidebar()
|
||||
};
|
||||
|
||||
layers->on_layer_opacity_changed = [this](Node*, int idx, float value) {
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]]->m_opacity = value;
|
||||
canvas->m_canvas->m_layers[idx]->m_opacity = value;
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
title_update();
|
||||
};
|
||||
|
||||
layers->on_layer_visibility_changed = [this](Node*, int idx, bool visible) {
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]]->m_visible = visible;
|
||||
canvas->m_canvas->m_layers[idx]->m_visible = visible;
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
title_update();
|
||||
};
|
||||
|
||||
layers->on_layer_alpha_lock_changed = [this](Node*, int idx, bool locked) {
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]]->m_alpha_locked = locked;
|
||||
canvas->m_canvas->m_layers[idx]->m_alpha_locked = locked;
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
title_update();
|
||||
};
|
||||
|
||||
layers->on_layer_blend_mode_changed = [this](Node*, int idx, int mode) {
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]]->m_blend_mode = mode;
|
||||
canvas->m_canvas->m_layers[idx]->m_blend_mode = mode;
|
||||
canvas->m_canvas->m_unsaved = true;
|
||||
title_update();
|
||||
};
|
||||
|
||||
layers->on_layer_highlight_changed = [this](Node*, int idx, bool highlight) {
|
||||
canvas->m_canvas->m_layers[canvas->m_canvas->m_order[idx]]->m_hightlight = highlight;
|
||||
canvas->m_canvas->m_layers[idx]->m_hightlight = highlight;
|
||||
};
|
||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke"))
|
||||
{
|
||||
@@ -1152,32 +1152,21 @@ void App::init_menu_layer()
|
||||
set_text("Rename Layer (Select a layer)");
|
||||
|
||||
popup->find<NodeButtonCustom>("layer-merge")->on_click = [this, popup](Node*) {
|
||||
const auto& order = canvas->m_canvas->m_order;
|
||||
//layers->get_child_index(layers->)
|
||||
int current_idx_order = (int)std::distance(order.begin(), std::find(order.begin(), order.end(), canvas->m_canvas->m_current_layer_idx));
|
||||
int current_idx_order = Canvas::I->m_current_layer_idx;
|
||||
if (current_idx_order > 0)
|
||||
{
|
||||
int dest_layer_idx = order[current_idx_order - 1];
|
||||
canvas->m_canvas->layer_merge(canvas->m_canvas->m_current_layer_idx, dest_layer_idx);
|
||||
canvas->m_canvas->layer_remove(current_idx_order);
|
||||
layers->clear();
|
||||
for (auto& i : canvas->m_canvas->m_order)
|
||||
layers->add_layer(canvas->m_canvas->m_layers[i]->m_name.c_str(), false);
|
||||
layers->m_current_layer->m_selected = false;
|
||||
layers->m_current_layer = layers->m_layers[current_idx_order - 1];
|
||||
layers->m_current_layer->m_selected = true;
|
||||
layers->m_current_layer->on_selected(layers->m_current_layer);
|
||||
layers->merge(current_idx_order, current_idx_order - 1, true);
|
||||
}
|
||||
popup->mouse_release();
|
||||
popup->destroy();
|
||||
};
|
||||
if (layers->m_current_layer)
|
||||
{
|
||||
const auto& order = canvas->m_canvas->m_order;
|
||||
int current_idx_order = (int)std::distance(order.begin(), std::find(order.begin(), order.end(), canvas->m_canvas->m_current_layer_idx));
|
||||
int current_idx_order = canvas->m_canvas->m_current_layer_idx;
|
||||
if (current_idx_order > 0)
|
||||
{
|
||||
int down_layer_idx = order[current_idx_order - 1];
|
||||
int down_layer_idx = current_idx_order - 1;
|
||||
popup->find<NodeButtonCustom>("layer-merge")->
|
||||
find<NodeText>("menu-label")->
|
||||
set_text(("Merge with " + canvas->m_canvas->m_layers[down_layer_idx]->m_name).c_str());
|
||||
@@ -1219,7 +1208,7 @@ void App::initLayout()
|
||||
|
||||
init_sidebar();
|
||||
|
||||
layers->add_layer("Default", false);
|
||||
layers->add_layer("Default", false, true);
|
||||
|
||||
init_toolbar_draw();
|
||||
init_toolbar_main();
|
||||
|
||||
@@ -203,7 +203,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp = proj * camera *
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_order.size() * 20)) *
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_layers.size() * 20)) *
|
||||
canvas->m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1));
|
||||
|
||||
@@ -217,9 +217,9 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
for (size_t i = 0; i < canvas->m_canvas->m_order.size(); i++)
|
||||
for (size_t i = 0; i < canvas->m_canvas->m_layers.size(); i++)
|
||||
{
|
||||
auto layer_index = canvas->m_canvas->m_order[i];
|
||||
auto layer_index = i;
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
if (!(canvas->m_canvas->m_show_tmp && canvas->m_canvas->m_current_layer_idx == layer_index) &&
|
||||
@@ -228,7 +228,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
!canvas->m_canvas->m_layers[layer_index]->m_dirty_face[plane_index]))
|
||||
continue;
|
||||
|
||||
int z = (int)(canvas->m_canvas->m_order.size() - i);
|
||||
int z = (int)(canvas->m_canvas->m_layers.size() - i);
|
||||
auto plane_mvp_z = proj * camera *
|
||||
glm::scale(glm::vec3(z) * 20.f) *
|
||||
//glm::eulerAngleYXZ(yaw, pitch, roll) *
|
||||
|
||||
@@ -92,14 +92,14 @@ void Canvas::pick_update(int plane)
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_sampler.bind(0);
|
||||
for (auto layer_index : m_order)
|
||||
for (auto& l : m_layers)
|
||||
{
|
||||
if (!m_layers[layer_index]->m_visible || m_layers[layer_index]->m_opacity == 0.f)
|
||||
if (!l->m_visible || l->m_opacity == 0.f)
|
||||
continue;
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index]->m_opacity);
|
||||
m_layers[layer_index]->m_rtt[i].bindTexture();
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, l->m_opacity);
|
||||
l->m_rtt[i].bindTexture();
|
||||
m_plane.draw_fill();
|
||||
m_layers[layer_index]->m_rtt[i].unbindTexture();
|
||||
l->m_rtt[i].unbindTexture();
|
||||
}
|
||||
m_sampler.unbind();
|
||||
|
||||
@@ -905,10 +905,9 @@ void Canvas::draw_merge(std::array<bool, 6> faces /*= SIXPLETTE(false)*/)
|
||||
|
||||
// check if any layer use blend, otherwise draw directly on main framebuffer
|
||||
bool use_blend = false;
|
||||
for (size_t i = 0; i < m_order.size(); i++)
|
||||
for (auto& l : m_layers)
|
||||
{
|
||||
auto layer_index = m_order[i];
|
||||
use_blend |= m_layers[layer_index]->m_blend_mode != 0;
|
||||
use_blend |= l->m_blend_mode != 0;
|
||||
}
|
||||
|
||||
// if not using shader blend, use gl rasterizer blend
|
||||
@@ -935,7 +934,7 @@ void Canvas::draw_merge(std::array<bool, 6> faces /*= SIXPLETTE(false)*/)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
for (int layer_index : m_order)
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
if (!(m_show_tmp && m_current_layer_idx == layer_index) &&
|
||||
(!m_layers[layer_index]->m_visible ||
|
||||
@@ -1223,37 +1222,31 @@ void Canvas::stroke_start(glm::vec3 point, float pressure)
|
||||
}
|
||||
m_show_tmp = true;
|
||||
}
|
||||
void Canvas::layer_add(std::string name, std::unique_ptr<Layer> layer /*= nullptr*/, int index /*= 0*/)
|
||||
void Canvas::layer_add(std::string name, std::shared_ptr<Layer> layer /*= nullptr*/, int index /*= 0*/)
|
||||
{
|
||||
LOG("canvas layer_add %s", name.c_str());
|
||||
int idx = (int)m_layers.size();
|
||||
if (layer)
|
||||
{
|
||||
m_layers.push_back(std::move(layer));
|
||||
m_layers.insert(m_layers.begin() + index, layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layers.push_back(std::make_unique<Layer>());
|
||||
m_layers.back()->create(m_width, m_height, name);
|
||||
m_layers.insert(m_layers.begin() + index, std::make_unique<Layer>());
|
||||
m_layers[index]->create(m_width, m_height, name);
|
||||
}
|
||||
m_order.push_back(idx);
|
||||
m_current_layer_idx = idx;
|
||||
m_current_layer_idx = index;
|
||||
}
|
||||
void Canvas::layer_remove(int idx) // m_order index
|
||||
{
|
||||
LOG("canvas layer_remove %d", idx);
|
||||
int n = m_order[idx];
|
||||
for (auto& i : m_order)
|
||||
if (i > n)
|
||||
i--;
|
||||
//m_layers[n]->destroy();
|
||||
m_layers.erase(m_layers.begin() + n);
|
||||
m_order.erase(m_order.begin() + idx);
|
||||
m_current_layer_idx = m_order[std::min<int>((int)m_layers.size() - 1, idx)];
|
||||
m_layers.erase(m_layers.begin() + idx);
|
||||
m_current_layer_idx = std::min<int>((int)m_layers.size() - 1, idx);
|
||||
}
|
||||
void Canvas::layer_order(int idx, int pos) // m_order index
|
||||
{
|
||||
std::swap(m_order[idx], m_order[pos]);
|
||||
std::swap(m_layers[idx], m_layers[pos]);
|
||||
}
|
||||
void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
||||
{
|
||||
@@ -1635,7 +1628,7 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
}
|
||||
m_sampler_bg.bind(0); // nearest
|
||||
m_sampler_mask.bind(1); // linear
|
||||
for (auto layer_index : m_order)
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
if (!m_layers[layer_index]->m_visible ||
|
||||
m_layers[layer_index]->m_opacity == 0.f ||
|
||||
@@ -1918,9 +1911,8 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
delete rgba_data;
|
||||
|
||||
rtt.clear({ 0, 0, 0, 1 });
|
||||
for (size_t i = 0; i < m_order.size(); i++)
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
auto layer_index = m_order[i];
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
if ((!m_layers[layer_index]->m_visible ||
|
||||
@@ -1937,7 +1929,7 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
m_sampler_linear.bind(1);
|
||||
ShaderManager::use(kShader::TextureColorize);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, { glm::vec3((float)(i + 1) / (float)(m_order.size() + 1)), 1.f });
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, { glm::vec3((float)(layer_index + 1) / (float)(m_layers.size() + 1)), 1.f });
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -2000,7 +1992,7 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
App::I.async_update();
|
||||
}
|
||||
int progress = 0;
|
||||
int total = (int)(m_order.size() + 1) * 6;
|
||||
int total = (int)(m_layers.size() + 1) * 6;
|
||||
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
@@ -2023,7 +2015,7 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
};
|
||||
|
||||
int seq = 0;
|
||||
for (auto layer_index : m_order)
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -2150,11 +2142,11 @@ void Canvas::export_cubes()
|
||||
const int stride = m_width * 4;
|
||||
auto buffer = std::make_unique<uint8_t[]>(m_width * m_height * 4);
|
||||
auto flipped = std::make_unique<uint8_t[]>(m_width * m_height * 4);
|
||||
for (int layer = 0; layer < m_order.size(); layer++)
|
||||
{
|
||||
for (int layer = 0; layer < m_layers.size(); layer++)
|
||||
{
|
||||
for (int plane = 0; plane < 6; plane++)
|
||||
{
|
||||
auto& l = m_layers[m_order[layer]];
|
||||
auto& l = m_layers[layer];
|
||||
l->m_rtt[plane].bindFramebuffer();
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
|
||||
l->m_rtt[plane].unbindFramebuffer();
|
||||
@@ -2332,7 +2324,7 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
|
||||
for (int i = 0; i < (int)m_layers.size(); i++)
|
||||
{
|
||||
int n_order = m_order[i];
|
||||
int n_order = i;
|
||||
fwrite(&n_order, sizeof(int), 1, fp);
|
||||
|
||||
float layer_alpha = m_layers[i]->m_opacity;
|
||||
@@ -2504,13 +2496,11 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
for (auto& l : m_layers)
|
||||
l->destroy();
|
||||
m_layers.clear();
|
||||
m_order.clear();
|
||||
//clear_all();
|
||||
resize(m_width, m_height);
|
||||
App::I.async_end();
|
||||
|
||||
std::vector<int> tmp_order;
|
||||
std::vector<std::unique_ptr<Layer>> tmp_layers;
|
||||
std::vector<std::shared_ptr<Layer>> tmp_layers;
|
||||
|
||||
for (int i = 0; i < n_layers; i++)
|
||||
{
|
||||
@@ -2580,11 +2570,9 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
tmp_layers.back()->create(m_width, m_height, name.c_str());
|
||||
tmp_layers.back()->clear({ 0, 0, 0, 0 });
|
||||
tmp_layers.back()->restore(snap);
|
||||
tmp_order.push_back(n_order);
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
std::swap(tmp_order, m_order);
|
||||
std::swap(tmp_layers, m_layers);
|
||||
|
||||
fclose(fp);
|
||||
@@ -2665,7 +2653,7 @@ Image Canvas::thumbnail_generate(int w, int h)
|
||||
}
|
||||
m_sampler_bg.bind(0); // nearest
|
||||
m_sampler_mask.bind(1); // linear
|
||||
for (auto layer_index : m_order)
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
if (!m_layers[layer_index]->m_visible ||
|
||||
m_layers[layer_index]->m_opacity == 0.f ||
|
||||
@@ -3080,7 +3068,7 @@ void Layer::restore(const Snapshot& snap)
|
||||
}
|
||||
}
|
||||
|
||||
Layer::Snapshot Layer::snapshot()
|
||||
Layer::Snapshot Layer::snapshot(glm::vec4 dirty_box[6] /*= nullptr*/, bool dirty_face[6] /*= nullptr*/)
|
||||
{
|
||||
Snapshot snap;
|
||||
static int counter = 0;
|
||||
@@ -3088,18 +3076,18 @@ Layer::Snapshot Layer::snapshot()
|
||||
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
snap.m_dirty_box[i] = m_dirty_box[i];
|
||||
snap.m_dirty_face[i] = m_dirty_face[i];
|
||||
snap.m_dirty_box[i] = dirty_box ? dirty_box[i] : m_dirty_box[i];
|
||||
snap.m_dirty_face[i] = dirty_face ? dirty_face[i] : m_dirty_face[i];
|
||||
|
||||
if (!m_dirty_face[i])
|
||||
if (!snap.m_dirty_face[i])
|
||||
continue;
|
||||
|
||||
snap.image[i] = std::make_unique<uint8_t[]>(m_rtt[i].bytes());
|
||||
|
||||
//glReadBuffer(GL_BACK);
|
||||
m_rtt[i].bindFramebuffer();
|
||||
glm::vec2 box_sz = zw(m_dirty_box[i]) - xy(m_dirty_box[i]);
|
||||
glReadPixels(m_dirty_box[i].x, m_dirty_box[i].y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, snap.image[i].get());
|
||||
glm::vec2 box_sz = zw(snap.m_dirty_box[i]) - xy(snap.m_dirty_box[i]);
|
||||
glReadPixels(snap.m_dirty_box[i].x, snap.m_dirty_box[i].y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, snap.image[i].get());
|
||||
m_rtt[i].unbindFramebuffer();
|
||||
//glReadBuffer(GL_NONE);
|
||||
}
|
||||
|
||||
@@ -94,9 +94,8 @@ public:
|
||||
std::unique_ptr<Stroke> m_current_stroke;
|
||||
std::unique_ptr<Stroke> m_dual_stroke;
|
||||
bool m_show_tmp = false;
|
||||
std::vector<std::unique_ptr<Layer>> m_layers;
|
||||
std::vector<std::shared_ptr<Layer>> m_layers;
|
||||
Layer m_layers_merge;
|
||||
std::vector<int> m_order;
|
||||
std::vector<glm::vec2> m_plane_shape[6]; // screen space projection of the plane
|
||||
glm::mat4 m_plane_unproject[6] = SIXPLETTE(glm::mat4(1));
|
||||
glm::vec3 m_plane_dir[6] = SIXPLETTE(glm::vec3(0));
|
||||
@@ -164,7 +163,7 @@ public:
|
||||
bool create(int width, int height);
|
||||
void resize(int width, int height);
|
||||
void layer_remove(int idx);
|
||||
void layer_add(std::string name, std::unique_ptr<Layer> layer = nullptr, int index = 0);
|
||||
void layer_add(std::string name, std::shared_ptr<Layer> layer = nullptr, int index = 0);
|
||||
void layer_order(int idx, int pos);
|
||||
void layer_merge(int source_idx, int dest_idx);
|
||||
void stroke_start(glm::vec3 point, float pressure);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "pch.h"
|
||||
#include "canvas_layer.h"
|
||||
|
||||
uint32_t Layer::s_count = 0;
|
||||
|
||||
void Layer::Snapshot::create(int w, int h)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
|
||||
@@ -9,10 +9,12 @@ class LayerFrame
|
||||
|
||||
class Layer
|
||||
{
|
||||
static uint32_t s_count;
|
||||
public:
|
||||
Layer() = default;
|
||||
Layer() { id = s_count++; }
|
||||
Layer(const Layer&) = delete;
|
||||
~Layer() { LOG("LAYER AUTO DESTROY"); destroy(); }
|
||||
uint32_t id;
|
||||
RTT m_rtt[6];
|
||||
glm::vec4 m_dirty_box[6] = SIXPLETTE(glm::vec4(0));
|
||||
bool m_dirty_face[6] = SIXPLETTE(false);
|
||||
@@ -26,7 +28,7 @@ public:
|
||||
int h = 0;
|
||||
struct Snapshot
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> image[6] = SIXPLETTE(0);
|
||||
std::shared_ptr<uint8_t[]> image[6] = SIXPLETTE(0);
|
||||
glm::vec4 m_dirty_box[6] = SIXPLETTE(glm::vec4(0));
|
||||
bool m_dirty_face[6] = SIXPLETTE(false);
|
||||
int width = 0;
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
void resize(int width, int height);
|
||||
bool create(int width, int height, std::string name);
|
||||
void clear(const glm::vec4& c);
|
||||
Snapshot snapshot();
|
||||
Snapshot snapshot(glm::vec4 dirty_box[6] = nullptr, bool dirty_face[6] = nullptr);
|
||||
void restore(const Snapshot& snap);
|
||||
void destroy();
|
||||
void optimize();
|
||||
|
||||
@@ -133,7 +133,7 @@ void NodeCanvas::draw()
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp = proj * camera *
|
||||
glm::scale(glm::vec3(m_canvas->m_order.size() + 500)) *
|
||||
glm::scale(glm::vec3(m_canvas->m_layers.size() + 500)) *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1));
|
||||
|
||||
@@ -175,10 +175,9 @@ void NodeCanvas::draw()
|
||||
{
|
||||
// check if any layer use blend, otherwise draw directly on main framebuffer
|
||||
bool use_blend = false;
|
||||
for (size_t i = 0; i < m_canvas->m_order.size(); i++)
|
||||
for (size_t i = 0; i < m_canvas->m_layers.size(); i++)
|
||||
{
|
||||
auto layer_index = m_canvas->m_order[i];
|
||||
use_blend |= m_canvas->m_layers[layer_index]->m_blend_mode != 0;
|
||||
use_blend |= m_canvas->m_layers[i]->m_blend_mode != 0;
|
||||
}
|
||||
|
||||
if (use_blend)
|
||||
@@ -192,7 +191,7 @@ void NodeCanvas::draw()
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp = proj * camera *
|
||||
glm::scale(glm::vec3(m_canvas->m_order.size() + 500)) *
|
||||
glm::scale(glm::vec3(m_canvas->m_layers.size() + 500)) *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1));
|
||||
|
||||
@@ -209,9 +208,9 @@ void NodeCanvas::draw()
|
||||
|
||||
const auto& b = m_canvas->m_current_stroke->m_brush;
|
||||
|
||||
for (size_t i = 0; i < m_canvas->m_order.size(); i++)
|
||||
for (size_t i = 0; i < m_canvas->m_layers.size(); i++)
|
||||
{
|
||||
auto layer_index = m_canvas->m_order[i];
|
||||
auto layer_index = i;
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
if (!(m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index) &&
|
||||
@@ -226,7 +225,7 @@ void NodeCanvas::draw()
|
||||
m_blender_rtt.clear();
|
||||
}
|
||||
|
||||
int z = (int)(m_canvas->m_order.size() - i);
|
||||
int z = (int)(m_canvas->m_layers.size() - i);
|
||||
auto plane_mvp_z = proj * camera *
|
||||
glm::scale(glm::vec3(z + 1)) *
|
||||
glm::eulerAngleYXZ(yaw, pitch, roll) *
|
||||
@@ -418,7 +417,7 @@ void NodeCanvas::draw()
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp = proj * camera *
|
||||
glm::scale(glm::vec3(m_canvas->m_order.size() + 500.f)) *
|
||||
glm::scale(glm::vec3(m_canvas->m_layers.size() + 500.f)) *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1.f));
|
||||
|
||||
@@ -462,7 +461,7 @@ void NodeCanvas::draw()
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp = proj * camera *
|
||||
glm::scale(glm::vec3(m_canvas->m_order.size() + 500.f)) *
|
||||
glm::scale(glm::vec3(m_canvas->m_layers.size() + 500.f)) *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1.f));
|
||||
|
||||
|
||||
@@ -131,20 +131,22 @@ void NodePanelLayer::init()
|
||||
next = tmp;
|
||||
}
|
||||
int source_index = m_layers_container->get_child_index(m_current_layer);
|
||||
add_layer(next.c_str());
|
||||
auto l = add_layer(next.c_str(), false, false, nullptr, nullptr, source_index + 1);
|
||||
if (on_layer_duplicate)
|
||||
on_layer_duplicate(this, source_index);
|
||||
if (on_layer_change)
|
||||
on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer));
|
||||
update_attributes();
|
||||
|
||||
auto a = new ActionLayerAdd;
|
||||
a->m_panel = this;
|
||||
a->m_layer_node = l->shared_from_this();
|
||||
a->m_layer_order = m_layers_container->get_child_index(l);
|
||||
a->m_layer_id = Canvas::I->m_layers[a->m_layer_order]->id;
|
||||
ActionManager::add(a);
|
||||
};
|
||||
btn_add->on_click = [this](Node*) {
|
||||
add_layer();
|
||||
if (on_layer_add)
|
||||
on_layer_add(this, nullptr, 0);
|
||||
if (on_layer_change)
|
||||
on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer));
|
||||
update_attributes();
|
||||
add_layer(true, true);
|
||||
};
|
||||
btn_remove->on_click = [this](Node*) {
|
||||
if (m_layers.size() == 1)
|
||||
@@ -159,6 +161,11 @@ void NodePanelLayer::init()
|
||||
{
|
||||
on_layer_order(this, old_idx, new_idx);
|
||||
}
|
||||
auto a = new ActionLayerMove;
|
||||
a->m_panel = this;
|
||||
a->m_layer_node = m_current_layer->shared_from_this();
|
||||
a->m_offset = -1;
|
||||
ActionManager::add(a);
|
||||
};
|
||||
btn_down->on_click = [this](Node*) {
|
||||
int old_idx = m_layers_container->get_child_index(m_current_layer);
|
||||
@@ -168,6 +175,11 @@ void NodePanelLayer::init()
|
||||
{
|
||||
on_layer_order(this, old_idx, new_idx);
|
||||
}
|
||||
auto a = new ActionLayerMove;
|
||||
a->m_panel = this;
|
||||
a->m_layer_node = m_current_layer->shared_from_this();
|
||||
a->m_offset = +1;
|
||||
ActionManager::add(a);
|
||||
};
|
||||
m_opacity = find<NodeSliderH>("opacity");
|
||||
m_opacity->on_value_changed = [this](Node*, float value) {
|
||||
@@ -183,13 +195,13 @@ void NodePanelLayer::init()
|
||||
};
|
||||
}
|
||||
|
||||
NodeLayer* NodePanelLayer::add_layer(const char* name, bool add_history /*= true*/, std::unique_ptr<class Layer> layer /*= nullptr*/, int index /*= 0*/)
|
||||
NodeLayer* NodePanelLayer::add_layer(const char* name, bool add_history /*= true*/, bool create_events /*= false*/,
|
||||
std::shared_ptr<Layer> layer /*= nullptr*/, std::shared_ptr<NodeLayer> layer_node /*= nullptr*/, int index /*= 0*/)
|
||||
{
|
||||
NodeLayer* l = new NodeLayer;
|
||||
if (layer)
|
||||
m_layers_container->add_child(l, index);
|
||||
else
|
||||
m_layers_container->add_child(l);
|
||||
if (index == -1)
|
||||
index = m_layers_container->m_children.size();
|
||||
auto l = layer_node ? layer_node : std::make_shared<NodeLayer>();
|
||||
m_layers_container->add_child(l, index);
|
||||
l->init();
|
||||
l->create();
|
||||
l->loaded();
|
||||
@@ -200,36 +212,45 @@ NodeLayer* NodePanelLayer::add_layer(const char* name, bool add_history /*= true
|
||||
l->on_highlight = std::bind(&NodePanelLayer::handle_layer_highlight, this, std::placeholders::_1, std::placeholders::_2);
|
||||
if (m_current_layer)
|
||||
m_current_layer->m_selected = false;
|
||||
m_current_layer = l;
|
||||
m_current_layer = l.get();
|
||||
m_current_layer->m_selected = true;
|
||||
m_layers.push_back(l);
|
||||
m_layers.push_back(l.get());
|
||||
|
||||
if (add_history)
|
||||
{
|
||||
if (create_events)
|
||||
{
|
||||
if (on_layer_add)
|
||||
on_layer_add(this, nullptr, m_layers_container->get_child_index(m_current_layer));
|
||||
if (on_layer_change)
|
||||
on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer));
|
||||
update_attributes();
|
||||
}
|
||||
|
||||
auto a = new ActionLayerAdd;
|
||||
a->m_panel = this;
|
||||
a->m_layer_node = l->shared_from_this();
|
||||
a->m_layer_order = m_layers_container->get_child_index(l);
|
||||
a->m_layer_order = m_layers_container->get_child_index(l.get());
|
||||
a->m_layer_id = Canvas::I->m_layers[a->m_layer_order]->id;
|
||||
ActionManager::add(a);
|
||||
update_attributes();
|
||||
}
|
||||
else
|
||||
else if (create_events)
|
||||
{
|
||||
if (on_layer_add)
|
||||
on_layer_add(this, std::move(layer), index);
|
||||
on_layer_add(this, layer, index);
|
||||
if (on_layer_change)
|
||||
on_layer_change(this, -1, m_layers_container->get_child_index(m_current_layer));
|
||||
update_attributes();
|
||||
}
|
||||
|
||||
return l;
|
||||
return l.get();
|
||||
}
|
||||
|
||||
void NodePanelLayer::add_layer()
|
||||
void NodePanelLayer::add_layer(bool add_history /*= true*/, bool create_events /*= false*/)
|
||||
{
|
||||
static char s[64];
|
||||
sprintf(s, "Layer-%d", id_counter++);
|
||||
add_layer(s);
|
||||
add_layer(s, add_history, create_events);
|
||||
}
|
||||
|
||||
NodeLayer* NodePanelLayer::get_layer_at(int index)
|
||||
@@ -239,11 +260,12 @@ NodeLayer* NodePanelLayer::get_layer_at(int index)
|
||||
|
||||
void NodePanelLayer::remove_layer(NodeLayer* layer, bool add_history /*= true*/)
|
||||
{
|
||||
auto it = std::find(m_layers.begin(), m_layers.end(), m_current_layer);
|
||||
auto i = m_layers_container->get_child_index(m_current_layer);
|
||||
auto it = std::find(m_layers.begin(), m_layers.end(), layer);
|
||||
auto i = m_layers_container->get_child_index(layer);
|
||||
int old_idx = i;// (int)std::distance(m_layers.begin(), it);
|
||||
(*it)->m_selected = false;
|
||||
auto copy = (*it)->shared_from_this();
|
||||
m_layers_container->remove_child(m_current_layer);
|
||||
m_layers_container->remove_child(layer);
|
||||
m_layers.erase(it);
|
||||
i = std::min<int>(i, (int)m_layers.size() - 1);
|
||||
m_current_layer = (NodeLayer*)m_layers_container->get_child_at(i);
|
||||
@@ -254,7 +276,7 @@ void NodePanelLayer::remove_layer(NodeLayer* layer, bool add_history /*= true*/)
|
||||
auto a = new ActionLayerRemove;
|
||||
a->m_panel = this;
|
||||
a->m_layer_node = copy;
|
||||
a->m_layer = std::move(Canvas::I->m_layers[Canvas::I->m_order[old_idx]]);
|
||||
a->m_layer = Canvas::I->m_layers[old_idx];
|
||||
a->m_layer_order = old_idx;
|
||||
ActionManager::add(a);
|
||||
}
|
||||
@@ -342,6 +364,31 @@ kEventResult NodePanelLayer::handle_event(Event* e)
|
||||
return kEventResult::Available;
|
||||
}
|
||||
|
||||
void NodePanelLayer::merge(int src_index, int dst_index, bool create_history)
|
||||
{
|
||||
if (create_history)
|
||||
{
|
||||
auto a = new ActionLayerMerge;
|
||||
a->m_direction = ActionLayerMerge::Direction::Undo;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
a->m_dirty_box[i] = Canvas::I->m_layers[dst_index]->m_dirty_box[i];
|
||||
a->m_dirty_face[i] = Canvas::I->m_layers[dst_index]->m_dirty_face[i];
|
||||
}
|
||||
a->m_snap = Canvas::I->m_layers[dst_index]->snapshot(
|
||||
Canvas::I->m_layers[src_index]->m_dirty_box, Canvas::I->m_layers[src_index]->m_dirty_face);
|
||||
a->m_layer = Canvas::I->m_layers[src_index];
|
||||
a->m_layer_node = std::static_pointer_cast<NodeLayer>(m_layers_container->m_children[src_index]);
|
||||
a->m_layer_node->m_selected = false;
|
||||
a->m_panel = std::static_pointer_cast<NodePanelLayer>(shared_from_this());
|
||||
a->m_src_index = src_index;
|
||||
a->m_dst_index = dst_index;
|
||||
ActionManager::add(a);
|
||||
}
|
||||
Canvas::I->layer_merge(Canvas::I->m_current_layer_idx, dst_index);
|
||||
remove_layer((NodeLayer*)m_layers_container->m_children[src_index].get(), false);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Action* ActionLayerAdd::get_redo()
|
||||
@@ -349,8 +396,10 @@ Action* ActionLayerAdd::get_redo()
|
||||
auto a = new ActionLayerRemove;
|
||||
a->m_panel = m_panel;
|
||||
a->m_layer_node = m_layer_node;
|
||||
a->m_layer = std::move(Canvas::I->m_layers[Canvas::I->m_order[m_layer_order]]);
|
||||
a->m_layer = *std::find_if(Canvas::I->m_layers.begin(), Canvas::I->m_layers.end(),
|
||||
[id=m_layer_id](const auto& x){ return x->id == id; });
|
||||
a->m_layer_order = m_layer_order;
|
||||
LOG("ActionLayerAdd::get_redo %s", a->m_layer->m_name.c_str());
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -372,13 +421,17 @@ Action* ActionLayerRemove::get_redo()
|
||||
a->m_panel = m_panel;
|
||||
a->m_layer_node = m_layer_node;
|
||||
a->m_layer_order = m_layer_order;
|
||||
a->m_layer_id = m_layer->id;
|
||||
LOG("ActionLayerRemove::get_redo %s", ((NodeLayer*)m_layer_node.get())->m_label_text.c_str());
|
||||
return a;
|
||||
}
|
||||
|
||||
void ActionLayerRemove::undo()
|
||||
{
|
||||
std::string name = m_layer->m_name;
|
||||
m_panel->add_layer(name.c_str(), false, std::move(m_layer), m_layer_order);
|
||||
m_panel->add_layer(name.c_str(), false, true, m_layer,
|
||||
std::dynamic_pointer_cast<NodeLayer>(m_layer_node), m_layer_order);
|
||||
LOG("ActionLayerRemove::undo %s", name.c_str());
|
||||
}
|
||||
|
||||
size_t ActionLayerRemove::memory()
|
||||
@@ -390,15 +443,61 @@ size_t ActionLayerRemove::memory()
|
||||
|
||||
Action* ActionLayerMove::get_redo()
|
||||
{
|
||||
return nullptr;
|
||||
auto a = new ActionLayerMove;
|
||||
a->m_panel = m_panel;
|
||||
a->m_layer_node = m_layer_node;
|
||||
a->m_offset = -m_offset;
|
||||
return a;
|
||||
}
|
||||
|
||||
void ActionLayerMove::undo()
|
||||
{
|
||||
|
||||
int old_idx = m_panel->m_layers_container->get_child_index(m_layer_node.get());
|
||||
m_panel->m_layers_container->move_child_offset(m_layer_node.get(), -m_offset);
|
||||
int new_idx = m_panel->m_layers_container->get_child_index(m_layer_node.get());
|
||||
if (m_panel->on_layer_order && old_idx != new_idx)
|
||||
{
|
||||
m_panel->on_layer_order(m_panel, old_idx, new_idx);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ActionLayerMove::memory()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ActionLayerMerge::undo()
|
||||
{
|
||||
if (m_direction == Direction::Undo)
|
||||
{
|
||||
Canvas::I->m_layers[m_dst_index]->restore(m_snap);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
Canvas::I->m_layers[m_dst_index]->m_dirty_box[i] = m_dirty_box[i];
|
||||
Canvas::I->m_layers[m_dst_index]->m_dirty_face[i] = m_dirty_face[i];
|
||||
}
|
||||
auto name = m_layer->m_name;
|
||||
m_panel->add_layer(name.c_str(), false, true, m_layer, m_layer_node, m_src_index);
|
||||
}
|
||||
else if (m_direction == Direction::Redo)
|
||||
{
|
||||
m_panel->merge(m_src_index, m_dst_index, false);
|
||||
}
|
||||
}
|
||||
|
||||
Action* ActionLayerMerge::get_redo()
|
||||
{
|
||||
auto a = new ActionLayerMerge;
|
||||
a->m_dirty_box = m_dirty_box;
|
||||
a->m_dirty_face = m_dirty_face;
|
||||
a->m_dst_index = m_dst_index;
|
||||
a->m_src_index = m_src_index;
|
||||
a->m_layer = m_layer;
|
||||
a->m_layer_node = m_layer_node;
|
||||
a->m_panel = m_panel;
|
||||
a->m_snap = m_snap;
|
||||
a->m_direction = m_direction == Direction::Undo ? Direction::Redo : Direction::Undo;
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "node_combobox.h"
|
||||
#include "node_scroll.h"
|
||||
#include "action.h"
|
||||
#include "canvas_layer.h"
|
||||
|
||||
class NodeLayer : public NodeBorder
|
||||
{
|
||||
@@ -50,7 +51,7 @@ public:
|
||||
std::function<void(Node* target, int idx, int mode)> on_layer_blend_mode_changed;
|
||||
std::function<void(Node* target, int index)> on_layer_delete;
|
||||
std::function<void(Node* target, int index)> on_layer_duplicate;
|
||||
std::function<void(Node* target, std::unique_ptr<class Layer> layer, int index)> on_layer_add;
|
||||
std::function<void(Node* target, std::shared_ptr<class Layer> layer, int index)> on_layer_add;
|
||||
std::function<void(Node* target, int old_idx, int new_idx)> on_layer_order;
|
||||
NodeLayer* m_current_layer = nullptr;
|
||||
std::vector<NodeLayer*> m_layers;
|
||||
@@ -61,8 +62,10 @@ public:
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void init() override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
void add_layer();
|
||||
NodeLayer* add_layer(const char* name, bool add_history = true, std::unique_ptr<class Layer> layer = nullptr, int index = 0);
|
||||
void merge(int src_index, int dst_index, bool create_history);
|
||||
void add_layer(bool add_history = true, bool create_events = false);
|
||||
NodeLayer* add_layer(const char* name, bool add_history = true, bool create_events = false,
|
||||
std::shared_ptr<Layer> layer = nullptr, std::shared_ptr<NodeLayer> layer_node = nullptr, int index = -1);
|
||||
NodeLayer* get_layer_at(int index);
|
||||
void remove_layer(NodeLayer* layer, bool add_history = true);
|
||||
void handle_layer_opacity(NodeLayer* target, float value);
|
||||
@@ -81,6 +84,7 @@ public:
|
||||
NodePanelLayer* m_panel;
|
||||
std::shared_ptr<Node> m_layer_node;
|
||||
int m_layer_order;
|
||||
uint32_t m_layer_id;
|
||||
virtual void run() override { }
|
||||
virtual Action* get_redo() override;
|
||||
virtual void undo() override;
|
||||
@@ -92,7 +96,7 @@ class ActionLayerRemove : public Action
|
||||
public:
|
||||
NodePanelLayer* m_panel;
|
||||
std::shared_ptr<Node> m_layer_node;
|
||||
std::unique_ptr<class Layer> m_layer;
|
||||
std::shared_ptr<class Layer> m_layer;
|
||||
int m_layer_order;
|
||||
virtual void run() override { }
|
||||
virtual Action* get_redo() override;
|
||||
@@ -103,11 +107,28 @@ public:
|
||||
class ActionLayerMove : public Action
|
||||
{
|
||||
public:
|
||||
int m_index_old;
|
||||
int m_index_new;
|
||||
NodePanelLayer* m_panel;
|
||||
std::shared_ptr<Node> m_layer_node;
|
||||
int m_offset;
|
||||
virtual void run() override { }
|
||||
virtual Action* get_redo() override;
|
||||
virtual void undo() override;
|
||||
virtual size_t memory() override;
|
||||
};
|
||||
|
||||
struct ActionLayerMerge : public Action
|
||||
{
|
||||
enum class Direction { Undo, Redo } m_direction;
|
||||
Layer::Snapshot m_snap;
|
||||
std::shared_ptr<Layer> m_layer;
|
||||
std::shared_ptr<NodeLayer> m_layer_node;
|
||||
std::shared_ptr<NodePanelLayer> m_panel;
|
||||
int m_src_index = 0; // removed layer
|
||||
int m_dst_index = 0;
|
||||
std::array<glm::vec4, 6> m_dirty_box;
|
||||
std::array<bool, 6> m_dirty_face;
|
||||
virtual void run() override { }
|
||||
virtual size_t memory() override { return 0; }
|
||||
virtual void undo() override;
|
||||
virtual Action* get_redo() override;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user