diff --git a/data/layout.xml b/data/layout.xml
index 41e58d2..da48052 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -1483,6 +1483,9 @@ Here's a list of what's available in this release.
+
diff --git a/src/app.cpp b/src/app.cpp
index 596ece9..15cc3d9 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -495,7 +495,7 @@ bool App::update_ui_observer(Node *n)
n->handle_on_screen(false, true);
n->m_on_screen = true;
}
- glm::ivec4 c = glm::vec4(box.x, (height / zoom - box.y - box.w), box.z, box.w) * zoom;
+ glm::ivec4 c = glm::vec4(box.x - 1, (height / zoom - box.y - box.w - 1), box.z + 2, box.w + 2) * zoom;
glScissor(floorf(c.x + off_x), floorf(c.y + off_y), ceilf(c.z), ceilf(c.w));
n->draw();
return true;
@@ -532,7 +532,7 @@ void App::draw(float dt)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height);
- //glEnable(GL_SCISSOR_TEST);
+ glEnable(GL_SCISSOR_TEST);
for (int i = 0; i < layout[main_id]->m_children.size(); i++)
layout[main_id]->m_children[i]->watch(observer);
//msgbox->watch(observer);
diff --git a/src/app.h b/src/app.h
index 2a5f967..c06dd70 100644
--- a/src/app.h
+++ b/src/app.h
@@ -205,7 +205,7 @@ public:
bool key_char(char key);
void toggle_ui();
void set_stylus();
- NodeMessageBox* message_box(const std::string& title, const std::string& text, bool cancel_button = false);
+ std::shared_ptr message_box(const std::string& title, const std::string& text, bool cancel_button = false);
void rec_clear();
void rec_loop();
@@ -232,7 +232,7 @@ public:
void dialog_export(std::string ext);
void dialog_export_layers();
void dialog_export_depth();
- void dialog_export_cubes();
+ void dialog_export_cube_faces();
void dialog_layer_rename();
void dialog_resize();
@@ -243,7 +243,7 @@ public:
void download(std::string url, std::string dest_filepath, std::function progress = nullptr);
bool check_license();
- std::shared_ptr show_progress(const std::string& title);
+ std::shared_ptr show_progress(const std::string& title, int total = 0);
void brush_update(bool update_color, bool update_brush);
void title_update();
@@ -284,8 +284,8 @@ public:
// don't capture a reference to this ptr as the object may be destroyed
// by the time the task is executed
- template
- std::future render_task_async(T task, bool unique = false)
+ template
+ std::future render_task_async(T task, bool unique = false)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -308,8 +308,8 @@ public:
return f;
}
- template
- R render_task(T task)
+ template
+ void render_task(T task)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -325,7 +325,8 @@ public:
}
render_cv.notify_all();
}
- return render_running ? f.get() : R();
+ if (render_running)
+ f.get();
}
void render_sync()
@@ -354,8 +355,8 @@ public:
// don't capture a reference to this ptr as the object may be destroyed
// by the time the task is executed
- template
- std::future ui_task_async(T task, bool unique = false)
+ template
+ std::future ui_task_async(T task, bool unique = false)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -378,8 +379,8 @@ public:
return f;
}
- template
- R ui_task(T task)
+ template
+ void ui_task(T task)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -395,7 +396,9 @@ public:
}
ui_cv.notify_all();
}
- return ui_running ? f.get() : R();
+ if (ui_running)
+ f.get();
+ redraw = true;
}
void ui_sync()
diff --git a/src/app_cloud.cpp b/src/app_cloud.cpp
index aadf262..d79e45c 100644
--- a/src/app_cloud.cpp
+++ b/src/app_cloud.cpp
@@ -31,7 +31,7 @@ void App::cloud_upload()
auto pb = show_progress("Uploading");
upload(doc_path, doc_filename, [this,pb](float p){
- pb->m_progress->SetWidthP(p * 100.f);
+ pb->set_progress(p);
});
pb->destroy();
@@ -70,32 +70,20 @@ void App::cloud_upload_all()
gl_state gl;
std::shared_ptr pb;
if (layout.m_loaded)
- {
- pb = show_progress("Export Pano Image");
- }
-
- int progress = 0;
- int total = (int)names.size();
+ pb = show_progress("Export Pano Image", names.size());
for (const auto& n : names)
{
std::string path = data_path + "/" + n;
upload(path);
- progress++;
- float p = (float)progress / total * 100.f;
- LOG("progress: %f", p);
-
if (layout.m_loaded)
- {
- pb->m_progress->SetWidthP(p);
- }
+ pb->increment();
}
if (layout.m_loaded)
- {
pb->destroy();
- }
+
}).detach();
}
diff --git a/src/app_dialogs.cpp b/src/app_dialogs.cpp
index def5f1a..acb70f9 100644
--- a/src/app_dialogs.cpp
+++ b/src/app_dialogs.cpp
@@ -13,7 +13,7 @@
#include "oculus_vr.h"
#endif
-std::shared_ptr App::show_progress(const std::string& title)
+std::shared_ptr App::show_progress(const std::string& title, int total /*= 0*/)
{
auto pb = std::make_shared();
pb->m_manager = &layout;
@@ -22,18 +22,25 @@ std::shared_ptr App::show_progress(const std::string& title)
pb->loaded();
pb->m_progress->SetWidthP(0);
pb->m_title->set_text(title.c_str());
+ pb->m_total = total;
+ pb->m_count = 0;
layout[main_id]->add_child(pb);
return pb;
}
-NodeMessageBox* App::message_box(const std::string &title, const std::string& text, bool cancel_button)
+std::shared_ptr App::message_box(const std::string &title, const std::string& text, bool cancel_button)
{
- auto* m = layout[main_id]->add_child();
+ auto m = std::make_shared();
+ m->m_manager = &layout;
+ m->init();
+ m->create();
+ m->loaded();
m->m_title->set_text(title.c_str());
m->m_message->set_text(text.c_str());
m->btn_ok->m_text->set_text("Ok");
if (!cancel_button)
m->btn_cancel->destroy();
+ layout[main_id]->add_child(m);
return m;
}
@@ -501,12 +508,20 @@ void App::dialog_resize()
};
}
-void App::dialog_export_cubes()
+void App::dialog_export_cube_faces()
{
if (canvas)
{
- canvas->m_canvas->export_cubes();
- }
+ canvas->m_canvas->export_cube_faces(doc_name, [this] {
+#if defined(__IOS__)
+ message_box("Export Cube Faces", "Image and depth exported to Files/PanoPainter");
+#elif defined(__OSX__)
+ message_box("Export Cube Faces", "Image and depth exported to Pictures/PanoPainter folder");
+#elif defined(_WIN32)
+ message_box("Export Cube Faces", "Image and depth exported to " + work_path);
+#endif
+ });
+ }
}
void App::dialog_layer_rename()
diff --git a/src/app_layout.cpp b/src/app_layout.cpp
index 4e43ad5..48c5a76 100644
--- a/src/app_layout.cpp
+++ b/src/app_layout.cpp
@@ -636,6 +636,13 @@ void App::init_menu_file()
popup->mouse_release();
popup->destroy();
};
+ subpopup->find("file-submenu-export-cube")->on_click = [this, subpopup, popup](Node*) {
+ dialog_export_cube_faces();
+ subpopup->mouse_release();
+ subpopup->destroy();
+ popup->mouse_release();
+ popup->destroy();
+ };
subpopup->find("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
dialog_export_depth();
subpopup->mouse_release();
@@ -656,13 +663,7 @@ void App::init_menu_file()
popup->mouse_release();
popup->destroy();
};
- if (auto b = popup->find("file-export-cubes"))
- b->on_click = [this, popup](Node*) {
- dialog_export_cubes();
- popup->mouse_release();
- popup->destroy();
- };
- if (auto b = popup->find("file-cloud-upload"))
+ if (auto b = popup->find("file-cloud-upload"))
b->on_click = [this, popup](Node*) {
cloud_upload();
popup->mouse_release();
diff --git a/src/canvas.cpp b/src/canvas.cpp
index 9beb7d2..a85a0b2 100644
--- a/src/canvas.cpp
+++ b/src/canvas.cpp
@@ -1921,183 +1921,69 @@ void Canvas::export_layers(std::string file_name, std::function on_compl
void Canvas::export_layers_thread(std::string file_name)
{
- std::shared_ptr pb;
- if (App::I->layout.m_loaded)
+ auto pb = App::I->show_progress("Export Layers", m_layers.size());
+ for (int i = 0; i < m_layers.size(); i++)
{
- pb = std::make_shared();
- pb->m_manager = &App::I->layout;
- pb->init();
- pb->create();
- pb->loaded();
- pb->m_progress->SetWidthP(0);
- pb->m_title->set_text("Export Pano Layers");
- App::I->layout[App::I->main_id]->add_child(pb);
+ auto l = m_layers[i];
+ Image img = l->gen_equirect().get_image();
+ img.save_png(fmt::format("{}/{}-layer{:02d}-{}.png", App::I->work_path, file_name, i, l->m_name));
+ pb->increment();
}
- int progress = 0;
- int total = (int)(m_layers.size() + 1) * 6;
+ pb->destroy();
+}
- RTT m_latlong;
- m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
-
- GLuint cube_id;
- int faces[]{
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // back
- GL_TEXTURE_CUBE_MAP_POSITIVE_X, // left
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // top
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom
- };
- App::I->render_task([&]
+void Canvas::export_cube_faces(std::string file_name, std::function on_complete)
+{
+ if (App::I->check_license())
{
- glGenTextures(1, &cube_id);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
- for (GLuint i = 0; i < 6; i++)
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- });
-
- int seq = 0;
- for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
- {
- for (int i = 0; i < 6; i++)
- {
- App::I->render_task([&]
- {
- // copy layer to cubemap
- m_layers[layer_index]->m_rtt[i].bindFramebuffer();
- glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
- glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0);
- glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
- m_layers[layer_index]->m_rtt[i].unbindFramebuffer();
+ std::thread t([=] {
+ BT_SetTerminate();
+ export_cube_faces_thread(file_name);
+ if (on_complete)
+ on_complete();
});
-
- progress++;
- float p = (float)progress / total * 100.f;
- LOG("progress: %f", p);
-
- if (App::I->layout.m_loaded)
- {
- pb->m_progress->SetWidthP(p);
- }
- }
-
- App::I->render_task([&]
- {
- glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight());
- glActiveTexture(GL_TEXTURE0);
- m_latlong.bindFramebuffer();
- m_latlong.clear({ 1, 1, 1, 0 });
- ShaderManager::use(kShader::Equirect);
- ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
- ShaderManager::u_int(kShaderUniform::Tex, 0);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
- glDisable(GL_BLEND);
- m_sampler_linear.bind(0);
- m_plane.draw_fill();
- glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
- m_latlong.unbindFramebuffer();
- });
-
- {
- auto latlong_data = std::make_unique(m_latlong.bytes());
- m_latlong.readTextureData(latlong_data.get());
- static char name[128];
- sprintf(name, "%s/%s-layer-%02d.png", App::I->work_path.c_str(), file_name.c_str(), seq);
- seq++;
- LOG("writing %s", name);
- int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
- }
-
- progress++;
- float p = (float)progress / total * 100.f;
- LOG("progress: %f", p);
-
- if (App::I->layout.m_loaded)
- {
- pb->m_progress->SetWidthP(p);
- }
- }
-
- App::I->render_task([&]
- {
- glDeleteTextures(1, &cube_id);
- m_latlong.destroy();
- });
-
- if (App::I->layout.m_loaded)
- {
- pb->destroy();
+ t.detach();
}
}
-void Canvas::export_cubes()
+void Canvas::export_cube_faces_thread(std::string file_name)
{
- if (!App::I->check_license())
- return;
#ifdef __OBJC__
NSMutableArray* files = [NSMutableArray array];
#endif
- std::array names {
- "pz", "px", "nz", "nx",
- "py", "ny"
- };
- const int stride = m_width * 4;
- auto buffer = std::make_unique(m_width * m_height * 4);
- auto flipped = std::make_unique(m_width * m_height * 4);
- for (int layer = 0; layer < m_layers.size(); layer++)
+ static std::array plane_names{ "front", "right", "back", "left", "top", "bottom" };
+
+ auto pb = App::I->show_progress("Export Cube Faces", 7);
+
+ App::I->render_task([this] {
+ draw_merge(false);
+ });
+ pb->increment();
+
+ for (int i = 0; i < 6; i++)
{
- for (int plane = 0; plane < 6; plane++)
- {
- 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();
-
- if (plane < 4)
- {
- for (int y = 0; y < m_height; y++)
- {
- int y_rev = m_height - y - 1;
- std::copy_n(buffer.get() + y * stride, stride, flipped.get() + y_rev * stride);
- }
- std::swap(buffer, flipped);
- }
- else
- {
- for (int y = 0; y < m_height; y++)
- {
- auto src = (glm::u8vec4*)(buffer.get() + y * stride);
- auto dst = (glm::u8vec4*)(flipped.get() + y * stride);
- for (int x = 0; x < m_width; x++)
- {
- int x_rev = m_width - x - 1;
- dst[x_rev] = src[x];
- }
- //std::copy_backward(src + stride, src, dst + stride);
- }
- std::swap(buffer, flipped);
- }
-
- static char name[128];
- sprintf(name, "%s-%02d-%d.png", App::I->work_path.c_str(), layer, plane);
- int ret = stbi_write_png(name, m_width, m_height, 4, buffer.get(), 0);
-
+ Image face = m_layers_merge.m_rtt[i].get_image();
+ std::string path = fmt::format("{}/{}-{}.png", App::I->work_path, file_name, plane_names[i]);
+ face.save_png(path);
+ pb->increment();
#ifdef __IOS__
- save_image_library(name);
+ save_image_library(path);
#endif
#ifdef __OBJC__
- [files addObject:[NSString stringWithUTF8String : name]];
+ [files addObject : [NSString stringWithUTF8String:path.c_str()] ];
#endif
- }
- }
+ }
+
+ pb->destroy();
+
#ifdef __OBJC__
static char name[128];
sprintf(name, "%s.zip", App::I->work_path.c_str());
- auto zip_path = [NSString stringWithUTF8String : name];
+ auto zip_path = [NSString stringWithUTF8String:name];
//[SSZipArchive createZipFileAtPath:zip_path withFilesAtPaths:files];
- for (NSString* f : files)
- [[NSFileManager defaultManager] removeItemAtPath:f error:nil];
+ //for (NSString* f : files)
+ // [[NSFileManager defaultManager] removeItemAtPath:f error:nil];
#endif
}
diff --git a/src/canvas.h b/src/canvas.h
index 2fd7ba3..9d54f61 100644
--- a/src/canvas.h
+++ b/src/canvas.h
@@ -204,10 +204,11 @@ public:
void export_equirectangular(std::string file_path, std::function on_complete = nullptr);
void export_equirectangular_thread(std::string file_path);
void export_layers(std::string file_name, std::function on_complete = nullptr);
- void export_layers_thread(std::string file_name);
+ void export_layers_thread(std::string file_name);
void export_depth(std::string file_name, std::function on_complete = nullptr);
void export_depth_thread(std::string file_name);
- void export_cubes();
+ void export_cube_faces(std::string file_name, std::function on_complete);
+ void export_cube_faces_thread(std::string file_name);
void project_save(std::function on_complete = nullptr);
void project_save(std::string file_path, std::function on_complete = nullptr);
bool project_save_thread(std::string file_path, bool show_progress);
diff --git a/src/node.cpp b/src/node.cpp
index 02984fa..47b182b 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -40,7 +40,7 @@
void Node::app_redraw()
{
App::I->redraw = true;
- App::I->ui_cv.notify_all();
+ App::I->render_cv.notify_all();
}
void Node::watch(std::function observer)
@@ -82,11 +82,11 @@ kEventResult Node::on_event(Event* e)
{
kEventResult ret = kEventResult::Available;
- if (current_mouse_capture && current_mouse_capture != this)
+ if (current_mouse_capture && current_mouse_capture.get() != this)
{
if (e->m_cat == kEventCategory::MouseEvent &&
child_mouse_focus != current_mouse_capture &&
- is_child(current_mouse_capture))
+ is_child(current_mouse_capture.get()))
{
MouseEvent* me = static_cast(e);
if (child_mouse_focus)
@@ -115,7 +115,7 @@ kEventResult Node::on_event(Event* e)
}
skip_children |= (e->m_cat == kEventCategory::MouseEvent || e->m_cat == kEventCategory::GestureEvent) &&
- (m_mouse_captured) && (root()->current_mouse_capture == this) && m_capture_children; // <-- THIS IS WRONG "!m_capture_children" is correct, but it breaks everything if changed
+ (m_mouse_captured) && (root()->current_mouse_capture.get() == this) && m_capture_children; // <-- THIS IS WRONG "!m_capture_children" is correct, but it breaks everything if changed
if (!m_display || glm::any(glm::lessThanEqual(zw(m_clip), { 0, 0 })))
return kEventResult::Available;
@@ -134,7 +134,7 @@ kEventResult Node::on_event(Event* e)
}
else
{
- if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus != it->get())
+ if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus.get() != it->get())
{
MouseEvent* me = static_cast(e);
if (child_mouse_focus)
@@ -147,7 +147,7 @@ kEventResult Node::on_event(Event* e)
MouseEvent e2 = *me;
e2.m_type = kEventType::MouseFocus;
(*it)->handle_event(&e2);
- child_mouse_focus = it->get();
+ child_mouse_focus = *it;
child_mouse_focus->m_mouse_focus = true;
}
ret = kEventResult::Consumed;
@@ -401,7 +401,7 @@ void Node::remove_child(Node* n)
YGNodeRemoveChild(y_node, n->y_node);
on_child_removed(n);
m_children.erase(i);
- if (child_mouse_focus == n)
+ if (child_mouse_focus.get() == n)
child_mouse_focus = nullptr;
});
}
@@ -542,7 +542,8 @@ void Node::mouse_capture()
auto& s = root()->m_capture_stack;
// already owner of capture
- if (c == this || std::find(s.begin(), s.end(), this) != s.end())
+ if (c.get() == this || std::find_if(s.begin(), s.end(),
+ [this](const auto& a) { return a.get() == this; }) != s.end())
return;
if (c)
@@ -570,7 +571,7 @@ void Node::mouse_capture()
}
// make current
- c = this;
+ c = shared_from_this();
m_mouse_captured = true;
}
@@ -582,8 +583,9 @@ void Node::mouse_release()
auto& c = root()->current_mouse_capture;
auto& s = root()->m_capture_stack;
- s.erase(std::remove(s.begin(), s.end(), this), s.end());
- if (c == this)
+ s.erase(std::remove_if(s.begin(), s.end(),
+ [this](const auto& a) { return a.get() == this; }), s.end());
+ if (c.get() == this)
{
if (s.empty())
{
@@ -604,7 +606,7 @@ void Node::key_capture()
if (!m_parent)
return;
- root()->current_key_capture = this;
+ root()->current_key_capture = shared_from_this();
m_key_captured = true;
}
@@ -1376,8 +1378,6 @@ void Node::clone_copy(Node* dest) const
dest->m_pos_offset = m_pos_offset;
dest->m_pos_offset_childred = m_pos_offset_childred;
dest->m_clip_uncut = m_clip_uncut;
-
-
}
void Node::clone_children(Node* dest) const
diff --git a/src/node.h b/src/node.h
index 1d9b3bb..2b25c5b 100644
--- a/src/node.h
+++ b/src/node.h
@@ -103,9 +103,9 @@ public:
uint16_t m_nodeID;
std::string m_nodeID_s;
std::vector> m_children;
- Node* current_mouse_capture = nullptr;
- Node* current_key_capture = nullptr;
- Node* child_mouse_focus = nullptr;
+ std::shared_ptr current_mouse_capture = nullptr;
+ std::shared_ptr current_key_capture = nullptr;
+ std::shared_ptr child_mouse_focus = nullptr;
bool m_mouse_captured = false;
bool m_key_captured = false;
@@ -117,7 +117,7 @@ public:
bool m_force_mouse_capture = false;
bool m_capture_children = true; // wether to capture children events when xx_capture() is used
bool m_destroyed = false;
- std::vector m_capture_stack;
+ std::vector> m_capture_stack;
bool m_mouse_ignore = true;
float m_zoom = 1.f;
diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp
index bacff9b..1cf2194 100644
--- a/src/node_canvas.cpp
+++ b/src/node_canvas.cpp
@@ -63,6 +63,14 @@ void NodeCanvas::clear_context()
void NodeCanvas::draw()
{
+ // sanity checks
+ float zoom = root()->m_zoom;
+ if (zoom == 0.f)
+ zoom = 1.f;
+ auto box = m_clip * zoom;
+ if (box.z == 0 || box.w == 0)
+ return;
+
GLint vp[4];
GLfloat cc[4];
glGetIntegerv(GL_VIEWPORT, vp);
@@ -73,8 +81,6 @@ void NodeCanvas::draw()
glDisable(GL_SCISSOR_TEST);
- float zoom = root()->m_zoom;
- auto box = m_clip * zoom;
glm::ivec4 c = (glm::ivec4)glm::vec4(box.x, (int)(vp[3] - box.y - box.w), box.z, box.w);
//m_canvas->m_cam_rot = m_pan * 0.003f;
diff --git a/src/node_combobox.cpp b/src/node_combobox.cpp
index 2240f27..3c742ea 100644
--- a/src/node_combobox.cpp
+++ b/src/node_combobox.cpp
@@ -53,10 +53,10 @@ void NodeComboBox::loaded()
m_current_index = index;
m_selected_child_index = popup->get_child_index(target);
m_text->set_text(m_items[index].c_str());
- popup->mouse_release();
- popup->destroy();
if (on_select)
on_select(btn, index);
+ popup->mouse_release();
+ popup->destroy();
};
}
}
diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp
index ea5f4eb..ea51c91 100644
--- a/src/node_panel_brush.cpp
+++ b/src/node_panel_brush.cpp
@@ -442,8 +442,7 @@ void NodePanelBrushPreset::init()
if (!m_current)
return;
int index = m_container->get_child_index(m_current);
- m_current->destroy_immediate();
- m_container->remove_child(m_current);
+ m_current->destroy();
if (m_container->m_children.empty())
{
m_current = nullptr;
diff --git a/src/node_panel_grid.cpp b/src/node_panel_grid.cpp
index eb1ae31..69e3dd1 100644
--- a/src/node_panel_grid.cpp
+++ b/src/node_panel_grid.cpp
@@ -467,7 +467,7 @@ void NodePanelGrid::bake_uvs()
);
while (pb_value < fb.getHeight())
{
- pb->m_progress->SetWidthP((float)pb_value / (float)fb.getHeight() * 100.f);
+ pb->set_progress((float)pb_value / (float)fb.getHeight());
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
worker.join();
diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp
index 4f14009..8fb93f4 100644
--- a/src/node_panel_stroke.cpp
+++ b/src/node_panel_stroke.cpp
@@ -76,8 +76,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
brush->m_user_brush = true;
brush->on_click = std::bind(&NodePanelBrush::handle_click, m_brush_popup, std::placeholders::_1);
count++;
- float prog = (float)count / (float)tot;
- pb->m_progress->SetWidthP(prog * 100.f);
+ pb->set_progress((float)count / (float)tot);
});
m_brush_popup->save();
@@ -105,8 +104,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
brush->m_user_brush = true;
brush->on_click = std::bind(&NodePanelBrush::handle_click, m_pattern_popup, std::placeholders::_1);
count++;
- float prog = (float)count / (float)tot;
- pb->m_progress->SetWidthP(prog * 100.f);
+ pb->set_progress((float)count / (float)tot);
});
m_pattern_popup->save();
@@ -119,8 +117,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
App::I->presets->add_brush(pr);
}
count++;
- float prog = (float)count / (float)tot;
- pb->m_progress->SetWidthP(prog * 100.f);
+ pb->set_progress((float)count / (float)tot);
}
App::I->presets->save();
diff --git a/src/node_progress_bar.cpp b/src/node_progress_bar.cpp
index 32e98d9..f3a5501 100644
--- a/src/node_progress_bar.cpp
+++ b/src/node_progress_bar.cpp
@@ -20,5 +20,17 @@ void NodeProgressBar::init()
btn_cancel->on_click = [&](Node*) { destroy(); };
m_progress = find("progress");
- m_progress->SetWidthP(10);
+ m_progress->SetWidthP(0);
+}
+
+void NodeProgressBar::increment() noexcept
+{
+ m_count++;
+ if (m_total != 0)
+ m_progress->SetWidthP(((float)m_count / m_total) * 100.f);
+}
+
+void NodeProgressBar::set_progress(float p) noexcept
+{
+ m_progress->SetWidthP(p * 100.f);
}
diff --git a/src/node_progress_bar.h b/src/node_progress_bar.h
index f5133e3..f8436e1 100644
--- a/src/node_progress_bar.h
+++ b/src/node_progress_bar.h
@@ -11,6 +11,11 @@ public:
NodeButton* btn_cancel;
NodeText* m_title;
NodeBorder* m_progress;
+ int m_total = 0;
+ int m_count = 0;
virtual Node* clone_instantiate() const override;
virtual void init() override;
+ void increment() noexcept;
+ // set progress where p [0, 1]
+ void set_progress(float p) noexcept;
};
diff --git a/src/rtt.cpp b/src/rtt.cpp
index d8e7cd7..9da0f1d 100644
--- a/src/rtt.cpp
+++ b/src/rtt.cpp
@@ -274,7 +274,7 @@ void RTT::clear_mask(glm::bool4 mask, glm::vec4 color)
glColorMask(old_mask[0], old_mask[1], old_mask[2], old_mask[3]);
}
-glm::ivec4 RTT::calc_bounds()
+glm::ivec4 RTT::calc_bounds() const noexcept
{
auto data = std::unique_ptr(reinterpret_cast(readTextureData()));
glm::ivec2 bbmin(w, h);
@@ -293,7 +293,7 @@ glm::ivec4 RTT::calc_bounds()
return { bbmin, bbmax };
}
-uint8_t* RTT::readTextureData(uint8_t* buffer)
+uint8_t* RTT::readTextureData(uint8_t* buffer) const noexcept
{
if (!buffer)
buffer = createBuffer();
@@ -308,7 +308,7 @@ uint8_t* RTT::readTextureData(uint8_t* buffer)
return buffer;
}
-float* RTT::readTextureDataFloat(float* buffer)
+float* RTT::readTextureDataFloat(float* buffer) const noexcept
{
if (!buffer)
buffer = createBufferFloat();
@@ -323,12 +323,12 @@ float* RTT::readTextureDataFloat(float* buffer)
return buffer;
}
-uint8_t* RTT::createBuffer()
+uint8_t* RTT::createBuffer() const noexcept
{
return new uint8_t[w * h * 4];
}
-float * RTT::createBufferFloat()
+float * RTT::createBufferFloat() const noexcept
{
return new float[w * h * 4];
}
@@ -345,4 +345,10 @@ void RTT::unbindTexture()
glBindTexture(GL_TEXTURE_2D, 0);
}
+Image RTT::get_image() const noexcept
+{
+ Image ret;
+ ret.create(w, h, readTextureData());
+ return ret;
+}
diff --git a/src/rtt.h b/src/rtt.h
index e17405f..aeaa869 100644
--- a/src/rtt.h
+++ b/src/rtt.h
@@ -1,4 +1,5 @@
#pragma once
+#include "image.h"
class RTT
{
@@ -28,20 +29,21 @@ public:
bool recreate() { return create(w, h); }
void clear(glm::vec4 color = glm::vec4(0));
void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0));
- glm::ivec4 calc_bounds();
- uint8_t* readTextureData(uint8_t* buffer = nullptr);
- float* readTextureDataFloat(float* buffer = nullptr);
- uint8_t* createBuffer();
- float* createBufferFloat();
+ glm::ivec4 calc_bounds() const noexcept;
+ uint8_t* readTextureData(uint8_t* buffer = nullptr) const noexcept;
+ float* readTextureDataFloat(float* buffer = nullptr) const noexcept;
+ uint8_t* createBuffer() const noexcept;
+ float* createBufferFloat() const noexcept;
void bindFramebuffer();
void unbindFramebuffer();
void bindTexture();
void unbindTexture();
- GLuint getTextureID() const { return texID; }
- int getWidth() const { return w; }
- int getHeight() const { return h; }
- glm::ivec2 getSize() const { return { w, h }; }
- int bytes() const { return w * h * 4; }
- int stride() const { return w * 4; }
- GLuint getFBO() const { return fboID; }
+ GLuint getTextureID() const noexcept { return texID; }
+ int getWidth() const noexcept { return w; }
+ int getHeight() const noexcept { return h; }
+ glm::ivec2 getSize() const noexcept { return { w, h }; }
+ int bytes() const noexcept { return w * h * 4; }
+ int stride() const noexcept { return w * 4; }
+ GLuint getFBO() const noexcept { return fboID; }
+ Image get_image() const noexcept;
};