implement layers merge down

This commit is contained in:
2017-08-10 09:18:56 +01:00
parent e134ba553d
commit 76b572831f
9 changed files with 158 additions and 8 deletions

View File

@@ -165,7 +165,7 @@
</border>
</layout>
<!-- Dialog Relane Layer -->
<!-- Dialog Rename Layer -->
<layout id="dialog-layer-rename">
<border positioning="absolute" position="0 0" color=".4 .4 .4 .8" width="100%" height="100%" align="center" justify="center">
<border thickness="1" border-color=".2" pad="3">
@@ -345,6 +345,10 @@
<icon icon="application_edit" width="20"/>
<text id="menu-label" text="Rename Layer" margin="0 0 0 5" font-face="arial" font-size="11"/>
</button-custom>
<button-custom id="layer-merge" height="30" align="center" color=".2" pad="0 0 0 10" dir="row">
<icon icon="application_edit" width="20"/>
<text id="menu-label" text="Merge with" margin="0 0 0 5" font-face="arial" font-size="11"/>
</button-custom>
</popup-menu>
</layout>

View File

@@ -175,6 +175,7 @@
<ClCompile Include="engine\node_canvas.cpp" />
<ClCompile Include="engine\node_checkbox.cpp" />
<ClCompile Include="engine\node_color_quad.cpp" />
<ClCompile Include="engine\node_dialog_layer_rename.cpp" />
<ClCompile Include="engine\node_dialog_open.cpp" />
<ClCompile Include="engine\node_icon.cpp" />
<ClCompile Include="engine\node_image.cpp" />
@@ -262,6 +263,7 @@
<ClInclude Include="engine\node_canvas.h" />
<ClInclude Include="engine\node_checkbox.h" />
<ClInclude Include="engine\node_color_quad.h" />
<ClInclude Include="engine\node_dialog_layer_rename.h" />
<ClInclude Include="engine\node_dialog_open.h" />
<ClInclude Include="engine\node_icon.h" />
<ClInclude Include="engine\node_image.h" />

View File

@@ -195,6 +195,9 @@
<ClCompile Include="libs\wacom\WinTab\Utils.cpp">
<Filter>Source Files\libs\WinTab</Filter>
</ClCompile>
<ClCompile Include="engine\node_dialog_layer_rename.cpp">
<Filter>Source Files\ui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="engine\app.h">
@@ -362,5 +365,8 @@
<ClInclude Include="libs\wacom\WinTab\MSGPACK.H">
<Filter>Source Files\libs\WinTab</Filter>
</ClInclude>
<ClInclude Include="engine\node_dialog_layer_rename.h">
<Filter>Header Files\ui</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -376,8 +376,8 @@ void App::initLayout()
popup->mouse_release();
popup->destroy();
};
popup->find<NodeButtonCustom>("layer-rename")->on_click = [this](Node*) {
// load thumbnail test
auto open_dialog = std::make_shared<NodeDialogLayerRename>();
open_dialog->m_manager = &layout;
open_dialog->data_path = data_path;
@@ -391,6 +391,7 @@ void App::initLayout()
open_dialog->btn_ok->on_click = [this,open_dialog](Node*)
{
layers->m_current_layer->set_name(open_dialog->get_name().c_str());
canvas->m_canvas->m_layers[canvas->m_canvas->m_current_layer_idx].m_name = open_dialog->get_name();
open_dialog->destroy();
};
@@ -405,6 +406,47 @@ void App::initLayout()
popup->find<NodeButtonCustom>("layer-rename")->
find<NodeText>("menu-label")->
set_text("Rename Layer (Select a layer)");
popup->find<NodeButtonCustom>("layer-merge")->on_click = [this](Node*) {
const auto& order = canvas->m_canvas->m_order;
int current_idx_order = std::distance(order.begin(), std::find(order.begin(), order.end(), canvas->m_canvas->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());
layers->m_current_layer = layers->m_layers[current_idx_order - 1];
layers->m_current_layer->m_selected = true;
}
popup->mouse_release();
popup->destroy();
};
if (layers->m_current_layer)
{
const auto& order = canvas->m_canvas->m_order;
int current_idx_order = std::distance(order.begin(), std::find(order.begin(), order.end(), canvas->m_canvas->m_current_layer_idx));
if (current_idx_order > 0)
{
int down_layer_idx = order[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());
}
else
{
popup->find<NodeButtonCustom>("layer-merge")->
find<NodeText>("menu-label")->
set_text("Merge Layer (Select upper layers)");
}
}
else
popup->find<NodeButtonCustom>("layer-merge")->
find<NodeText>("menu-label")->
set_text("Merge Layer (Select a layer)");
};
}
if (auto* toolbar = layout[main_id]->find<Node>("toolbar"))

View File

@@ -612,6 +612,89 @@ void ui::Canvas::layer_order(int idx, int pos)
{
std::swap(m_order[idx], m_order[pos]);
}
void ui::Canvas::layer_merge(int source_idx, int dest_idx)
{
m_dirty = false;
// save viewport and clear color states
GLint vp[4];
GLfloat cc[4];
glGetIntegerv(GL_VIEWPORT, vp);
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
GLboolean blend = glIsEnabled(GL_BLEND);
// allocate action to add to history
auto action = new ActionStroke;
// prepare common states
glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND);
for (int i = 0; i < 6; i++)
{
if (!m_layers[source_idx].m_dirty_face[i])
continue; // no stroke on this face, skip it
m_layers[dest_idx].m_rtt[i].bindFramebuffer();
/*
// save image before commit
glm::vec2 box_sz = m_dirty_box[i].zw() - m_dirty_box[i].xy();
action->m_image[i] = std::make_unique<uint8_t[]>(box_sz.x * box_sz.y * 4);
glReadPixels(m_dirty_box[i].x, m_dirty_box[i].y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get());
action->m_box[i] = m_dirty_box[i];
action->m_old_box[i] = m_layers[m_current_layer_idx].m_dirty_box[i];
action->m_old_dirty[i] = m_layers[m_current_layer_idx].m_dirty_face[i];
*/
auto& lbox = m_layers[dest_idx].m_dirty_box[i];
lbox.xy = glm::min(m_layers[source_idx].m_dirty_box[i].xy(), lbox.xy());
lbox.zw = glm::max(m_layers[source_idx].m_dirty_box[i].zw(), lbox.zw());
m_layers[dest_idx].m_dirty_face[i] = true;
// copy to tmp2 for layer blending
glActiveTexture(GL_TEXTURE0);
m_tex2[i].bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height);
m_tex2[i].unbind();
m_sampler.bind(0);
m_sampler_bg.bind(1);
{
ui::ShaderManager::use(kShader::CompDraw);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0); // dest
ui::ShaderManager::u_int(kShaderUniform::TexStroke, 1); // source
ui::ShaderManager::u_float(kShaderUniform::Alpha, 1);
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
glActiveTexture(GL_TEXTURE0);
m_tex2[i].bind();
glActiveTexture(GL_TEXTURE1);
m_layers[source_idx].m_rtt[i].bindTexture();
m_plane.draw_fill();
m_layers[source_idx].m_rtt[i].unbindTexture();
glActiveTexture(GL_TEXTURE0);
m_tex2[i].unbind();
}
m_layers[dest_idx].m_rtt[i].unbindFramebuffer();
}
// restore viewport and clear color states
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glViewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
glActiveTexture(GL_TEXTURE0);
/*
// save history
action->m_layer_idx = m_current_layer_idx;
action->m_canvas = this;
action->m_stroke = std::move(m_current_stroke);
ActionManager::add(action);
*/
}
void ui::Canvas::resize(int width, int height)
{
m_width = width;

View File

@@ -101,6 +101,7 @@ public:
void layer_remove(int idx);
void layer_add(std::string name);
void layer_order(int idx, int pos);
void layer_merge(int source_idx, int dest_idx);
void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush);
void stroke_update(glm::vec2 point, float pressure);
void stroke_draw();

View File

@@ -330,12 +330,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
PostQuitMessage(0);
break;
case WM_SIZE:
App::I.resize((float)LOWORD(lp), (float)HIWORD(lp));
App::I.clear();
App::I.redraw = true;
App::I.update(0.f);
SwapBuffers(hDC);
{
auto w = (float)LOWORD(lp);
auto h = (float)HIWORD(lp);
if (h != 0)
{
App::I.resize(w, h);
App::I.clear();
App::I.redraw = true;
App::I.update(0.f);
SwapBuffers(hDC);
}
break;
}
case WM_ACTIVATE:
{
int active = GET_WM_ACTIVATE_STATE(wp, lp);

View File

@@ -104,6 +104,7 @@ void NodeCanvas::draw()
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
ui::ShaderManager::u_int(kShaderUniform::TexStroke, 1);
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_current_stroke->m_brush.m_tip_opacity);
ui::ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[m_canvas->m_current_layer_idx].m_alpha_locked);
}
else if(m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
{
@@ -111,6 +112,7 @@ void NodeCanvas::draw()
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
ui::ShaderManager::u_int(kShaderUniform::TexStroke, 1);
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_current_stroke->m_brush.m_tip_opacity);
ui::ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[m_canvas->m_current_layer_idx].m_alpha_locked);
}
else
{
@@ -119,7 +121,6 @@ void NodeCanvas::draw()
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity);
}
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
ui::ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[m_canvas->m_current_layer_idx].m_alpha_locked);
// if (!(m_canvas->m_state == ui::Canvas::kCanvasMode::Erase &&
// m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index))

View File

@@ -167,6 +167,10 @@ void NodePanelLayer::add_layer(const char* name)
l->on_selected = std::bind(&NodePanelLayer::handle_layer_selected, this, std::placeholders::_1);
l->on_opacity_changed = std::bind(&NodePanelLayer::handle_layer_opacity, this, std::placeholders::_1, std::placeholders::_2);
l->on_visibility_changed = std::bind(&NodePanelLayer::handle_layer_visibility, this, std::placeholders::_1, std::placeholders::_2);
if (m_current_layer)
m_current_layer->m_selected = false;
m_current_layer = l;
m_current_layer->m_selected = true;
m_layers.push_back(l);
}