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"> <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"/> <text text="Separate Layers" grow="1" margin="0 0 0 5"/>
</button-custom> </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"> <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"/> <text text="3D View + Depth" grow="1" margin="0 0 0 5"/>
</button-custom> </button-custom>

View File

@@ -495,7 +495,7 @@ bool App::update_ui_observer(Node *n)
n->handle_on_screen(false, true); n->handle_on_screen(false, true);
n->m_on_screen = 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)); glScissor(floorf(c.x + off_x), floorf(c.y + off_y), ceilf(c.z), ceilf(c.w));
n->draw(); n->draw();
return true; return true;
@@ -532,7 +532,7 @@ void App::draw(float dt)
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif #endif
glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height); 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++) for (int i = 0; i < layout[main_id]->m_children.size(); i++)
layout[main_id]->m_children[i]->watch(observer); layout[main_id]->m_children[i]->watch(observer);
//msgbox->watch(observer); //msgbox->watch(observer);

View File

@@ -205,7 +205,7 @@ public:
bool key_char(char key); bool key_char(char key);
void toggle_ui(); void toggle_ui();
void set_stylus(); 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_clear();
void rec_loop(); void rec_loop();
@@ -232,7 +232,7 @@ public:
void dialog_export(std::string ext); void dialog_export(std::string ext);
void dialog_export_layers(); void dialog_export_layers();
void dialog_export_depth(); void dialog_export_depth();
void dialog_export_cubes(); void dialog_export_cube_faces();
void dialog_layer_rename(); void dialog_layer_rename();
void dialog_resize(); void dialog_resize();
@@ -243,7 +243,7 @@ public:
void download(std::string url, std::string dest_filepath, std::function<void(float)> progress = nullptr); void download(std::string url, std::string dest_filepath, std::function<void(float)> progress = nullptr);
bool check_license(); 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 brush_update(bool update_color, bool update_brush);
void title_update(); void title_update();
@@ -284,8 +284,8 @@ public:
// don't capture a reference to this ptr as the object may be destroyed // don't capture a reference to this ptr as the object may be destroyed
// by the time the task is executed // by the time the task is executed
template<typename T, typename R = void> template<typename T>
std::future<R> render_task_async(T task, bool unique = false) std::future<void> render_task_async(T task, bool unique = false)
{ {
AppTask pt(task); AppTask pt(task);
auto f = pt.get_future(); auto f = pt.get_future();
@@ -308,8 +308,8 @@ public:
return f; return f;
} }
template<typename T, typename R = void> template<typename T>
R render_task(T task) void render_task(T task)
{ {
AppTask pt(task); AppTask pt(task);
auto f = pt.get_future(); auto f = pt.get_future();
@@ -325,7 +325,8 @@ public:
} }
render_cv.notify_all(); render_cv.notify_all();
} }
return render_running ? f.get() : R(); if (render_running)
f.get();
} }
void render_sync() void render_sync()
@@ -354,8 +355,8 @@ public:
// don't capture a reference to this ptr as the object may be destroyed // don't capture a reference to this ptr as the object may be destroyed
// by the time the task is executed // by the time the task is executed
template<typename T, typename R = void> template<typename T>
std::future<R> ui_task_async(T task, bool unique = false) std::future<void> ui_task_async(T task, bool unique = false)
{ {
AppTask pt(task); AppTask pt(task);
auto f = pt.get_future(); auto f = pt.get_future();
@@ -378,8 +379,8 @@ public:
return f; return f;
} }
template<typename T, typename R = void> template<typename T>
R ui_task(T task) void ui_task(T task)
{ {
AppTask pt(task); AppTask pt(task);
auto f = pt.get_future(); auto f = pt.get_future();
@@ -395,7 +396,9 @@ public:
} }
ui_cv.notify_all(); ui_cv.notify_all();
} }
return ui_running ? f.get() : R(); if (ui_running)
f.get();
redraw = true;
} }
void ui_sync() void ui_sync()

View File

@@ -31,7 +31,7 @@ void App::cloud_upload()
auto pb = show_progress("Uploading"); auto pb = show_progress("Uploading");
upload(doc_path, doc_filename, [this,pb](float p){ upload(doc_path, doc_filename, [this,pb](float p){
pb->m_progress->SetWidthP(p * 100.f); pb->set_progress(p);
}); });
pb->destroy(); pb->destroy();
@@ -70,32 +70,20 @@ void App::cloud_upload_all()
gl_state gl; gl_state gl;
std::shared_ptr<NodeProgressBar> pb; std::shared_ptr<NodeProgressBar> pb;
if (layout.m_loaded) if (layout.m_loaded)
{ pb = show_progress("Export Pano Image", names.size());
pb = show_progress("Export Pano Image");
}
int progress = 0;
int total = (int)names.size();
for (const auto& n : names) for (const auto& n : names)
{ {
std::string path = data_path + "/" + n; std::string path = data_path + "/" + n;
upload(path); upload(path);
progress++;
float p = (float)progress / total * 100.f;
LOG("progress: %f", p);
if (layout.m_loaded) if (layout.m_loaded)
{ pb->increment();
pb->m_progress->SetWidthP(p);
}
} }
if (layout.m_loaded) if (layout.m_loaded)
{
pb->destroy(); pb->destroy();
}
}).detach(); }).detach();
} }

View File

@@ -13,7 +13,7 @@
#include "oculus_vr.h" #include "oculus_vr.h"
#endif #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>(); auto pb = std::make_shared<NodeProgressBar>();
pb->m_manager = &layout; pb->m_manager = &layout;
@@ -22,18 +22,25 @@ std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title)
pb->loaded(); pb->loaded();
pb->m_progress->SetWidthP(0); pb->m_progress->SetWidthP(0);
pb->m_title->set_text(title.c_str()); pb->m_title->set_text(title.c_str());
pb->m_total = total;
pb->m_count = 0;
layout[main_id]->add_child(pb); layout[main_id]->add_child(pb);
return 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_title->set_text(title.c_str());
m->m_message->set_text(text.c_str()); m->m_message->set_text(text.c_str());
m->btn_ok->m_text->set_text("Ok"); m->btn_ok->m_text->set_text("Ok");
if (!cancel_button) if (!cancel_button)
m->btn_cancel->destroy(); m->btn_cancel->destroy();
layout[main_id]->add_child(m);
return m; return m;
} }
@@ -501,12 +508,20 @@ void App::dialog_resize()
}; };
} }
void App::dialog_export_cubes() void App::dialog_export_cube_faces()
{ {
if (canvas) 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() void App::dialog_layer_rename()

View File

@@ -636,6 +636,13 @@ void App::init_menu_file()
popup->mouse_release(); popup->mouse_release();
popup->destroy(); 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*) { subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) {
dialog_export_depth(); dialog_export_depth();
subpopup->mouse_release(); subpopup->mouse_release();
@@ -656,13 +663,7 @@ void App::init_menu_file()
popup->mouse_release(); popup->mouse_release();
popup->destroy(); popup->destroy();
}; };
if (auto b = popup->find<NodeButtonCustom>("file-export-cubes")) if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
b->on_click = [this, popup](Node*) {
dialog_export_cubes();
popup->mouse_release();
popup->destroy();
};
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup](Node*) {
cloud_upload(); cloud_upload();
popup->mouse_release(); 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) void Canvas::export_layers_thread(std::string file_name)
{ {
std::shared_ptr<NodeProgressBar> pb; auto pb = App::I->show_progress("Export Layers", m_layers.size());
if (App::I->layout.m_loaded) for (int i = 0; i < m_layers.size(); i++)
{ {
pb = std::make_shared<NodeProgressBar>(); auto l = m_layers[i];
pb->m_manager = &App::I->layout; Image img = l->gen_equirect().get_image();
pb->init(); img.save_png(fmt::format("{}/{}-layer{:02d}-{}.png", App::I->work_path, file_name, i, l->m_name));
pb->create(); pb->increment();
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);
} }
int progress = 0; pb->destroy();
int total = (int)(m_layers.size() + 1) * 6; }
RTT m_latlong; void Canvas::export_cube_faces(std::string file_name, std::function<void()> on_complete)
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense {
if (App::I->check_license())
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([&]
{ {
glGenTextures(1, &cube_id); std::thread t([=] {
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); BT_SetTerminate();
for (GLuint i = 0; i < 6; i++) export_cube_faces_thread(file_name);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); if (on_complete)
}); on_complete();
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();
}); });
t.detach();
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();
} }
} }
void Canvas::export_cubes() void Canvas::export_cube_faces_thread(std::string file_name)
{ {
if (!App::I->check_license())
return;
#ifdef __OBJC__ #ifdef __OBJC__
NSMutableArray* files = [NSMutableArray array]; NSMutableArray* files = [NSMutableArray array];
#endif #endif
std::array<std::string, 6> names { static std::array<const char*, 6> plane_names{ "front", "right", "back", "left", "top", "bottom" };
"pz", "px", "nz", "nx",
"py", "ny" auto pb = App::I->show_progress("Export Cube Faces", 7);
};
const int stride = m_width * 4; App::I->render_task([this] {
auto buffer = std::make_unique<uint8_t[]>(m_width * m_height * 4); draw_merge(false);
auto flipped = std::make_unique<uint8_t[]>(m_width * m_height * 4); });
for (int layer = 0; layer < m_layers.size(); layer++) pb->increment();
for (int i = 0; i < 6; i++)
{ {
for (int plane = 0; plane < 6; plane++) 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]);
auto& l = m_layers[layer]; face.save_png(path);
l->m_rtt[plane].bindFramebuffer(); pb->increment();
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);
#ifdef __IOS__ #ifdef __IOS__
save_image_library(name); save_image_library(path);
#endif #endif
#ifdef __OBJC__ #ifdef __OBJC__
[files addObject:[NSString stringWithUTF8String : name]]; [files addObject : [NSString stringWithUTF8String:path.c_str()] ];
#endif #endif
} }
}
pb->destroy();
#ifdef __OBJC__ #ifdef __OBJC__
static char name[128]; static char name[128];
sprintf(name, "%s.zip", App::I->work_path.c_str()); 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]; //[SSZipArchive createZipFileAtPath:zip_path withFilesAtPaths:files];
for (NSString* f : files) //for (NSString* f : files)
[[NSFileManager defaultManager] removeItemAtPath:f error:nil]; // [[NSFileManager defaultManager] removeItemAtPath:f error:nil];
#endif #endif
} }

View File

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

View File

@@ -40,7 +40,7 @@
void Node::app_redraw() void Node::app_redraw()
{ {
App::I->redraw = true; App::I->redraw = true;
App::I->ui_cv.notify_all(); App::I->render_cv.notify_all();
} }
void Node::watch(std::function<bool(Node*)> observer) void Node::watch(std::function<bool(Node*)> observer)
@@ -82,11 +82,11 @@ kEventResult Node::on_event(Event* e)
{ {
kEventResult ret = kEventResult::Available; 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 && if (e->m_cat == kEventCategory::MouseEvent &&
child_mouse_focus != current_mouse_capture && child_mouse_focus != current_mouse_capture &&
is_child(current_mouse_capture)) is_child(current_mouse_capture.get()))
{ {
MouseEvent* me = static_cast<MouseEvent*>(e); MouseEvent* me = static_cast<MouseEvent*>(e);
if (child_mouse_focus) 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) && 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 }))) if (!m_display || glm::any(glm::lessThanEqual(zw(m_clip), { 0, 0 })))
return kEventResult::Available; return kEventResult::Available;
@@ -134,7 +134,7 @@ kEventResult Node::on_event(Event* e)
} }
else 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); MouseEvent* me = static_cast<MouseEvent*>(e);
if (child_mouse_focus) if (child_mouse_focus)
@@ -147,7 +147,7 @@ kEventResult Node::on_event(Event* e)
MouseEvent e2 = *me; MouseEvent e2 = *me;
e2.m_type = kEventType::MouseFocus; e2.m_type = kEventType::MouseFocus;
(*it)->handle_event(&e2); (*it)->handle_event(&e2);
child_mouse_focus = it->get(); child_mouse_focus = *it;
child_mouse_focus->m_mouse_focus = true; child_mouse_focus->m_mouse_focus = true;
} }
ret = kEventResult::Consumed; ret = kEventResult::Consumed;
@@ -401,7 +401,7 @@ void Node::remove_child(Node* n)
YGNodeRemoveChild(y_node, n->y_node); YGNodeRemoveChild(y_node, n->y_node);
on_child_removed(n); on_child_removed(n);
m_children.erase(i); m_children.erase(i);
if (child_mouse_focus == n) if (child_mouse_focus.get() == n)
child_mouse_focus = nullptr; child_mouse_focus = nullptr;
}); });
} }
@@ -542,7 +542,8 @@ void Node::mouse_capture()
auto& s = root()->m_capture_stack; auto& s = root()->m_capture_stack;
// already owner of capture // 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; return;
if (c) if (c)
@@ -570,7 +571,7 @@ void Node::mouse_capture()
} }
// make current // make current
c = this; c = shared_from_this();
m_mouse_captured = true; m_mouse_captured = true;
} }
@@ -582,8 +583,9 @@ void Node::mouse_release()
auto& c = root()->current_mouse_capture; auto& c = root()->current_mouse_capture;
auto& s = root()->m_capture_stack; auto& s = root()->m_capture_stack;
s.erase(std::remove(s.begin(), s.end(), this), s.end()); s.erase(std::remove_if(s.begin(), s.end(),
if (c == this) [this](const auto& a) { return a.get() == this; }), s.end());
if (c.get() == this)
{ {
if (s.empty()) if (s.empty())
{ {
@@ -604,7 +606,7 @@ void Node::key_capture()
if (!m_parent) if (!m_parent)
return; return;
root()->current_key_capture = this; root()->current_key_capture = shared_from_this();
m_key_captured = true; 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 = m_pos_offset;
dest->m_pos_offset_childred = m_pos_offset_childred; dest->m_pos_offset_childred = m_pos_offset_childred;
dest->m_clip_uncut = m_clip_uncut; dest->m_clip_uncut = m_clip_uncut;
} }
void Node::clone_children(Node* dest) const void Node::clone_children(Node* dest) const

View File

@@ -103,9 +103,9 @@ public:
uint16_t m_nodeID; uint16_t m_nodeID;
std::string m_nodeID_s; std::string m_nodeID_s;
std::vector<std::shared_ptr<Node>> m_children; std::vector<std::shared_ptr<Node>> m_children;
Node* current_mouse_capture = nullptr; std::shared_ptr<Node> current_mouse_capture = nullptr;
Node* current_key_capture = nullptr; std::shared_ptr<Node> current_key_capture = nullptr;
Node* child_mouse_focus = nullptr; std::shared_ptr<Node> child_mouse_focus = nullptr;
bool m_mouse_captured = false; bool m_mouse_captured = false;
bool m_key_captured = false; bool m_key_captured = false;
@@ -117,7 +117,7 @@ public:
bool m_force_mouse_capture = false; bool m_force_mouse_capture = false;
bool m_capture_children = true; // wether to capture children events when xx_capture() is used bool m_capture_children = true; // wether to capture children events when xx_capture() is used
bool m_destroyed = false; bool m_destroyed = false;
std::vector<Node*> m_capture_stack; std::vector<std::shared_ptr<Node>> m_capture_stack;
bool m_mouse_ignore = true; bool m_mouse_ignore = true;
float m_zoom = 1.f; float m_zoom = 1.f;

View File

@@ -63,6 +63,14 @@ void NodeCanvas::clear_context()
void NodeCanvas::draw() 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]; GLint vp[4];
GLfloat cc[4]; GLfloat cc[4];
glGetIntegerv(GL_VIEWPORT, vp); glGetIntegerv(GL_VIEWPORT, vp);
@@ -73,8 +81,6 @@ void NodeCanvas::draw()
glDisable(GL_SCISSOR_TEST); 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); 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; //m_canvas->m_cam_rot = m_pan * 0.003f;

View File

@@ -53,10 +53,10 @@ void NodeComboBox::loaded()
m_current_index = index; m_current_index = index;
m_selected_child_index = popup->get_child_index(target); m_selected_child_index = popup->get_child_index(target);
m_text->set_text(m_items[index].c_str()); m_text->set_text(m_items[index].c_str());
popup->mouse_release();
popup->destroy();
if (on_select) if (on_select)
on_select(btn, index); on_select(btn, index);
popup->mouse_release();
popup->destroy();
}; };
} }
} }

View File

@@ -442,8 +442,7 @@ void NodePanelBrushPreset::init()
if (!m_current) if (!m_current)
return; return;
int index = m_container->get_child_index(m_current); int index = m_container->get_child_index(m_current);
m_current->destroy_immediate(); m_current->destroy();
m_container->remove_child(m_current);
if (m_container->m_children.empty()) if (m_container->m_children.empty())
{ {
m_current = nullptr; m_current = nullptr;

View File

@@ -467,7 +467,7 @@ void NodePanelGrid::bake_uvs()
); );
while (pb_value < fb.getHeight()) 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)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
worker.join(); worker.join();

View File

@@ -76,8 +76,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
brush->m_user_brush = true; brush->m_user_brush = true;
brush->on_click = std::bind(&NodePanelBrush::handle_click, m_brush_popup, std::placeholders::_1); brush->on_click = std::bind(&NodePanelBrush::handle_click, m_brush_popup, std::placeholders::_1);
count++; count++;
float prog = (float)count / (float)tot; pb->set_progress((float)count / (float)tot);
pb->m_progress->SetWidthP(prog * 100.f);
}); });
m_brush_popup->save(); m_brush_popup->save();
@@ -105,8 +104,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
brush->m_user_brush = true; brush->m_user_brush = true;
brush->on_click = std::bind(&NodePanelBrush::handle_click, m_pattern_popup, std::placeholders::_1); brush->on_click = std::bind(&NodePanelBrush::handle_click, m_pattern_popup, std::placeholders::_1);
count++; count++;
float prog = (float)count / (float)tot; pb->set_progress((float)count / (float)tot);
pb->m_progress->SetWidthP(prog * 100.f);
}); });
m_pattern_popup->save(); m_pattern_popup->save();
@@ -119,8 +117,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
App::I->presets->add_brush(pr); App::I->presets->add_brush(pr);
} }
count++; count++;
float prog = (float)count / (float)tot; pb->set_progress((float)count / (float)tot);
pb->m_progress->SetWidthP(prog * 100.f);
} }
App::I->presets->save(); App::I->presets->save();

View File

@@ -20,5 +20,17 @@ void NodeProgressBar::init()
btn_cancel->on_click = [&](Node*) { destroy(); }; btn_cancel->on_click = [&](Node*) { destroy(); };
m_progress = find<NodeBorder>("progress"); 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; NodeButton* btn_cancel;
NodeText* m_title; NodeText* m_title;
NodeBorder* m_progress; NodeBorder* m_progress;
int m_total = 0;
int m_count = 0;
virtual Node* clone_instantiate() const override; virtual Node* clone_instantiate() const override;
virtual void init() 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]); 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())); auto data = std::unique_ptr<glm::u8vec4[]>(reinterpret_cast<glm::u8vec4*>(readTextureData()));
glm::ivec2 bbmin(w, h); glm::ivec2 bbmin(w, h);
@@ -293,7 +293,7 @@ glm::ivec4 RTT::calc_bounds()
return { bbmin, bbmax }; return { bbmin, bbmax };
} }
uint8_t* RTT::readTextureData(uint8_t* buffer) uint8_t* RTT::readTextureData(uint8_t* buffer) const noexcept
{ {
if (!buffer) if (!buffer)
buffer = createBuffer(); buffer = createBuffer();
@@ -308,7 +308,7 @@ uint8_t* RTT::readTextureData(uint8_t* buffer)
return buffer; return buffer;
} }
float* RTT::readTextureDataFloat(float* buffer) float* RTT::readTextureDataFloat(float* buffer) const noexcept
{ {
if (!buffer) if (!buffer)
buffer = createBufferFloat(); buffer = createBufferFloat();
@@ -323,12 +323,12 @@ float* RTT::readTextureDataFloat(float* buffer)
return buffer; return buffer;
} }
uint8_t* RTT::createBuffer() uint8_t* RTT::createBuffer() const noexcept
{ {
return new uint8_t[w * h * 4]; return new uint8_t[w * h * 4];
} }
float * RTT::createBufferFloat() float * RTT::createBufferFloat() const noexcept
{ {
return new float[w * h * 4]; return new float[w * h * 4];
} }
@@ -345,4 +345,10 @@ void RTT::unbindTexture()
glBindTexture(GL_TEXTURE_2D, 0); 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 #pragma once
#include "image.h"
class RTT class RTT
{ {
@@ -28,20 +29,21 @@ public:
bool recreate() { return create(w, h); } bool recreate() { return create(w, h); }
void clear(glm::vec4 color = glm::vec4(0)); void clear(glm::vec4 color = glm::vec4(0));
void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0)); void clear_mask(glm::bool4 mask, glm::vec4 color = glm::vec4(0));
glm::ivec4 calc_bounds(); glm::ivec4 calc_bounds() const noexcept;
uint8_t* readTextureData(uint8_t* buffer = nullptr); uint8_t* readTextureData(uint8_t* buffer = nullptr) const noexcept;
float* readTextureDataFloat(float* buffer = nullptr); float* readTextureDataFloat(float* buffer = nullptr) const noexcept;
uint8_t* createBuffer(); uint8_t* createBuffer() const noexcept;
float* createBufferFloat(); float* createBufferFloat() const noexcept;
void bindFramebuffer(); void bindFramebuffer();
void unbindFramebuffer(); void unbindFramebuffer();
void bindTexture(); void bindTexture();
void unbindTexture(); void unbindTexture();
GLuint getTextureID() const { return texID; } GLuint getTextureID() const noexcept { return texID; }
int getWidth() const { return w; } int getWidth() const noexcept { return w; }
int getHeight() const { return h; } int getHeight() const noexcept { return h; }
glm::ivec2 getSize() const { return { w, h }; } glm::ivec2 getSize() const noexcept { return { w, h }; }
int bytes() const { return w * h * 4; } int bytes() const noexcept { return w * h * 4; }
int stride() const { return w * 4; } int stride() const noexcept { return w * 4; }
GLuint getFBO() const { return fboID; } GLuint getFBO() const noexcept { return fboID; }
Image get_image() const noexcept;
}; };