Merge branch 'master'

This commit is contained in:
2019-08-28 12:10:58 +02:00
19 changed files with 174 additions and 250 deletions

View File

@@ -1483,6 +1483,9 @@ Here's a list of what's available in this release.
<button-custom id="file-submenu-export-layers" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
<text text="Separate Layers" grow="1" margin="0 0 0 5"/>
</button-custom>
<button-custom id="file-submenu-export-cube" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
<text text="Cube Faces" grow="1" margin="0 0 0 5"/>
</button-custom>
<button-custom id="file-submenu-export-depth" height="40" align="center" color=".2" pad="0 0 0 10" dir="row">
<text text="3D View + Depth" grow="1" margin="0 0 0 5"/>
</button-custom>

View File

@@ -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);

View File

@@ -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<NodeMessageBox> 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<void(float)> progress = nullptr);
bool check_license();
std::shared_ptr<NodeProgressBar> show_progress(const std::string& title);
std::shared_ptr<NodeProgressBar> 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<typename T, typename R = void>
std::future<R> render_task_async(T task, bool unique = false)
template<typename T>
std::future<void> render_task_async(T task, bool unique = false)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -308,8 +308,8 @@ public:
return f;
}
template<typename T, typename R = void>
R render_task(T task)
template<typename T>
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<typename T, typename R = void>
std::future<R> ui_task_async(T task, bool unique = false)
template<typename T>
std::future<void> ui_task_async(T task, bool unique = false)
{
AppTask pt(task);
auto f = pt.get_future();
@@ -378,8 +379,8 @@ public:
return f;
}
template<typename T, typename R = void>
R ui_task(T task)
template<typename T>
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()

View File

@@ -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<NodeProgressBar> 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();
}

View File

@@ -13,7 +13,7 @@
#include "oculus_vr.h"
#endif
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title)
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title, int total /*= 0*/)
{
auto pb = std::make_shared<NodeProgressBar>();
pb->m_manager = &layout;
@@ -22,18 +22,25 @@ std::shared_ptr<NodeProgressBar> 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<NodeMessageBox> App::message_box(const std::string &title, const std::string& text, bool cancel_button)
{
auto* m = layout[main_id]->add_child<NodeMessageBox>();
auto m = std::make_shared<NodeMessageBox>();
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()

View File

@@ -636,6 +636,13 @@ void App::init_menu_file()
popup->mouse_release();
popup->destroy();
};
subpopup->find<NodeButtonCustom>("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<NodeButtonCustom>("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<NodeButtonCustom>("file-export-cubes"))
b->on_click = [this, popup](Node*) {
dialog_export_cubes();
popup->mouse_release();
popup->destroy();
};
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
b->on_click = [this, popup](Node*) {
cloud_upload();
popup->mouse_release();

View File

@@ -1921,183 +1921,69 @@ void Canvas::export_layers(std::string file_name, std::function<void()> on_compl
void Canvas::export_layers_thread(std::string file_name)
{
std::shared_ptr<NodeProgressBar> 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<NodeProgressBar>();
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<void()> 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<uint8_t[]>(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<std::string, 6> names {
"pz", "px", "nz", "nx",
"py", "ny"
};
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_layers.size(); layer++)
static std::array<const char*, 6> 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
}

View File

@@ -204,10 +204,11 @@ public:
void export_equirectangular(std::string file_path, std::function<void()> on_complete = nullptr);
void export_equirectangular_thread(std::string file_path);
void export_layers(std::string file_name, std::function<void()> 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<void()> on_complete = nullptr);
void export_depth_thread(std::string file_name);
void export_cubes();
void export_cube_faces(std::string file_name, std::function<void()> on_complete);
void export_cube_faces_thread(std::string file_name);
void project_save(std::function<void(bool)> on_complete = nullptr);
void project_save(std::string file_path, std::function<void(bool)> on_complete = nullptr);
bool project_save_thread(std::string file_path, bool show_progress);

View File

@@ -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<bool(Node*)> 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<MouseEvent*>(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<MouseEvent*>(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

View File

@@ -103,9 +103,9 @@ public:
uint16_t m_nodeID;
std::string m_nodeID_s;
std::vector<std::shared_ptr<Node>> m_children;
Node* current_mouse_capture = nullptr;
Node* current_key_capture = nullptr;
Node* child_mouse_focus = nullptr;
std::shared_ptr<Node> current_mouse_capture = nullptr;
std::shared_ptr<Node> current_key_capture = nullptr;
std::shared_ptr<Node> 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<Node*> m_capture_stack;
std::vector<std::shared_ptr<Node>> m_capture_stack;
bool m_mouse_ignore = true;
float m_zoom = 1.f;

View File

@@ -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;

View File

@@ -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();
};
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();

View File

@@ -20,5 +20,17 @@ void NodeProgressBar::init()
btn_cancel->on_click = [&](Node*) { destroy(); };
m_progress = find<NodeBorder>("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);
}

View File

@@ -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;
};

View File

@@ -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<glm::u8vec4[]>(reinterpret_cast<glm::u8vec4*>(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;
}

View File

@@ -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;
};