diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 2e0f63d..185a1c9 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -1322,8 +1322,11 @@ void App::initLayout() auto frame_text = layout[main_id]->find("timeline-frame"); slider->on_value_changed = [this, frame_text](Node*, float value) { + auto& l = Canvas::I->layer(); + l.m_frame_index = (int)glm::clamp( + floor(value * l.m_frames.size()), 0, (int)l.m_frames.size() - 1); +/* auto& c = *Canvas::I; - for (int i = 0; i < c.m_layers.size(); i++) { auto l = layers->get_layer_at(i); @@ -1353,11 +1356,12 @@ void App::initLayout() snprintf(str, sizeof(str), "%02d", current_layer); frame_text->set_text(str); } +*/ }; if (auto btn_add = timeline->find("btn-add")) { btn_add->on_click = [this, slider] (Node*) { - layers->add_layer(true, true); + Canvas::I->layer().add_frame(); slider->set_value(1.f, true); }; } diff --git a/src/canvas.h b/src/canvas.h index df6e447..f382a34 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -175,6 +175,7 @@ public: void destroy(); bool create(int width, int height); void resize(int width, int height); + Layer& layer() { return *m_layers[m_current_layer_idx]; } void layer_remove(int idx); void layer_add(std::string name, std::shared_ptr layer = nullptr, int index = 0); void layer_order(int idx, int pos); diff --git a/src/canvas_layer.cpp b/src/canvas_layer.cpp index f84df79..7dc038d 100644 --- a/src/canvas_layer.cpp +++ b/src/canvas_layer.cpp @@ -158,17 +158,17 @@ void Layer::restore(const Snapshot& snap) //m_rtt[i].recreate(); App::I->render_task_async([this, i, &snap] - { - rtt(i).bindTexture(); - glm::vec2 box_sz = zw(box(i)) - xy(box(i)); - glTexSubImage2D(GL_TEXTURE_2D, 0, - box(i).x, box(i).y, - box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, - snap.image[i].get()); - rtt(i).unbindTexture(); - LOG("restore face %d - %d bytes (%dx%d)", i, - (int)box_sz.x * (int)box_sz.y * 4, (int)box_sz.x, (int)box_sz.y); - }); + { + rtt(i).bindTexture(); + glm::vec2 box_sz = zw(box(i)) - xy(box(i)); + glTexSubImage2D(GL_TEXTURE_2D, 0, + box(i).x, box(i).y, + box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, + snap.image[i].get()); + rtt(i).unbindTexture(); + LOG("restore face %d - %d bytes (%dx%d)", i, + (int)box_sz.x * (int)box_sz.y * 4, (int)box_sz.x, (int)box_sz.y); + }); } App::I->render_sync(); } @@ -189,13 +189,13 @@ Layer::Snapshot Layer::snapshot(std::array* dirty_box /*= nullptr* snap.image[i] = std::make_unique(rtt(i).bytes()); App::I->render_task_async([this, i, &snap] - { - rtt(i).bindFramebuffer(); - 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()); - rtt(i).unbindFramebuffer(); - }); + { + rtt(i).bindFramebuffer(); + 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()); + rtt(i).unbindFramebuffer(); + }); } App::I->render_sync(); return snap; @@ -203,36 +203,7 @@ Layer::Snapshot Layer::snapshot(std::array* dirty_box /*= nullptr* void Layer::clear(const glm::vec4& c) { - App::I->render_task([&] - { - // push clear color state - GLfloat cc[4]; - glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); - glClearColor(c.r, c.g, c.b, c.a); - - bool erase = (c.a == 0.f); - - for (int i = 0; i < 6; i++) - { - rtt(i).bindFramebuffer(); - glClear(GL_COLOR_BUFFER_BIT); - rtt(i).unbindFramebuffer(); - - if (erase) - { - box(i) = glm::vec4(w, h, 0, 0); // reset bounding box - face(i) = false; - } - else - { - box(i) = glm::vec4(0, 0, w, h); // reset bounding box - face(i) = true; - } - } - - // restore clear color state - glClearColor(cc[0], cc[1], cc[2], cc[3]); - }); + frame().clear(c); } bool Layer::create(int width, int height, std::string name) @@ -240,26 +211,18 @@ bool Layer::create(int width, int height, std::string name) m_name = name; w = width; h = height; + m_frame_index = 0; if (m_frames.empty()) m_frames.emplace_back(); - App::I->render_task([&] - { - for (int i = 0; i < 6; i++) - { - rtt(i).create(width, height); - rtt(i).bindFramebuffer(); - rtt(i).clear(); - rtt(i).unbindFramebuffer(); - box(i) = glm::vec4(w, h, 0, 0); // reset bounding box - face(i) = false; - } - }); + frame().create(width, height); return true; } bool Layer::add_frame() { - return true; + m_frames.emplace_back(); + m_frame_index = m_frames.size() - 1; + return frame().create(w, h); } void Layer::resize(int width, int height) @@ -335,11 +298,52 @@ int Layer::Snapshot::memsize() const /////////////////////////////////////////////////////////////////////////////////////////// +/* +LayerFrame::LayerFrame(LayerFrame&& other) +{ + LOG("LayerFrame move-ctor"); + for (int i = 0; i < 6; i++) + { + m_rtt[i] = std::move(other.m_rtt[i]); + m_dirty_box[i] = other.m_dirty_box[i]; + m_dirty_face[i] = other.m_dirty_face[i]; + } + m_duration = other.m_duration; + w = other.w; + h = other.h; +} + +LayerFrame& LayerFrame::operator=(LayerFrame&& other) +{ + LOG("LayerFrame move-assignment"); + for (int i = 0; i < 6; i++) + { + m_rtt[i] = std::move(other.m_rtt[i]); + m_dirty_box[i] = other.m_dirty_box[i]; + m_dirty_face[i] = other.m_dirty_face[i]; + } + m_duration = other.m_duration; + w = other.w; + h = other.h; + return *this; +} +*/ + bool LayerFrame::create(int width, int height, int duration /*= 1*/) { - for (auto& rtt : m_rtt) - if (!rtt.create(width, height)) - return false; + App::I->render_task([&] + { + for (int i = 0; i < 6; i++) + { + if (!m_rtt[i].create(width, height)) + return false; + m_rtt[i].bindFramebuffer(); + m_rtt[i].clear(); + m_rtt[i].unbindFramebuffer(); + m_dirty_box[i] = glm::vec4(w, h, 0, 0); // reset bounding box + m_dirty_face[i] = false; + } + }); m_duration = duration; w = width; h = height; @@ -359,3 +363,37 @@ bool LayerFrame::resize(int width, int height) h = height; return true; } + +void LayerFrame::clear(const glm::vec4& c) +{ + App::I->render_task([&] + { + // push clear color state + GLfloat cc[4]; + glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); + glClearColor(c.r, c.g, c.b, c.a); + + bool erase = (c.a == 0.f); + + for (int i = 0; i < 6; i++) + { + m_rtt[i].bindFramebuffer(); + glClear(GL_COLOR_BUFFER_BIT); + m_rtt[i].unbindFramebuffer(); + + if (erase) + { + m_dirty_box[i] = glm::vec4(w, h, 0, 0); // reset bounding box + m_dirty_face[i] = false; + } + else + { + m_dirty_box[i] = glm::vec4(0, 0, w, h); // reset bounding box + m_dirty_face[i] = true; + } + } + + // restore clear color state + glClearColor(cc[0], cc[1], cc[2], cc[3]); + }); +} diff --git a/src/canvas_layer.h b/src/canvas_layer.h index c1f4f16..f49b145 100644 --- a/src/canvas_layer.h +++ b/src/canvas_layer.h @@ -10,9 +10,19 @@ struct LayerFrame std::array m_dirty_face = SIXPLETTE(false); int m_duration = 1; int w = 0, h = 0; - LayerFrame() = default; + + //// default + //LayerFrame() = default; + //// copy + //LayerFrame(const LayerFrame&) = delete; + //LayerFrame& operator=(const LayerFrame&) = delete; + //// move + //LayerFrame(LayerFrame&& other); + //LayerFrame& operator=(LayerFrame&&); + bool create(int width, int height, int duration = 1); bool resize(int width, int height); + void clear(const glm::vec4& c); }; class Layer diff --git a/src/rtt.cpp b/src/rtt.cpp index abef629..72e76de 100644 --- a/src/rtt.cpp +++ b/src/rtt.cpp @@ -4,8 +4,31 @@ #include "util.h" #include "app.h" +RTT& RTT::operator=(RTT&& other) +{ + LOG("RTT-move-assignment"); + int_fmt = other.int_fmt; + texID = other.texID; + fboID = other.fboID; + rboID = other.rboID; + w = other.w; + h = other.h; + bound = other.bound; + + other.int_fmt = 0; + other.texID = 0; + other.fboID = 0; + other.rboID = 0; + other.w = 0; + other.h = 0; + other.bound = false; + + return *this; +} + RTT::RTT() { + int_fmt = 0; fboID = 0; rboID = 0; w = 0; @@ -15,12 +38,18 @@ RTT::RTT() RTT::RTT(RTT&& other) { + LOG("RTT-move-ctor"); + + int_fmt = other.int_fmt; + texID = other.texID; fboID = other.fboID; rboID = other.rboID; w = other.w; h = other.h; bound = other.bound; + other.int_fmt = 0; + other.texID = 0; other.fboID = 0; other.rboID = 0; other.w = 0; @@ -30,6 +59,7 @@ RTT::RTT(RTT&& other) RTT::~RTT() { + LOG("RTT-dtor"); //destroy(); if (texID || rboID || fboID) LOG("RTT not destroyed"); diff --git a/src/rtt.h b/src/rtt.h index 66e1bd4..de77f1d 100644 --- a/src/rtt.h +++ b/src/rtt.h @@ -3,19 +3,24 @@ class RTT { + int w = 0; + int h = 0; + GLuint fboID = 0; + GLuint texID = 0; + GLuint rboID = 0; + GLint int_fmt = 0; bool bound = false; GLint oldRFboID = 0; GLint oldDFboID = 0; - GLuint fboID = 0; - GLuint rboID = 0; - GLuint texID = 0; - GLint int_fmt = 0; - int w = 0; - int h = 0; public: + // copy RTT(const RTT&) = delete; + RTT& operator=(const RTT&) = delete; + // move RTT(RTT&& other); + RTT& operator=(RTT&&); + // default RTT(); ~RTT();