Many small fixes
This commit is contained in:
parent
7bcab6f795
commit
be04751776
2 changed files with 89 additions and 61 deletions
|
@ -1,5 +1,4 @@
|
|||
#include "GLGizmoSimplify.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
|
@ -10,6 +9,10 @@
|
|||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/QuadricEdgeCollapse.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
|
||||
|
@ -27,22 +30,22 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
|
|||
{}
|
||||
|
||||
GLGizmoSimplify::~GLGizmoSimplify() {
|
||||
m_state.status = State::cancelling;
|
||||
if (m_worker.joinable()) m_worker.join();
|
||||
stop_worker_thread(true);
|
||||
m_glmodel.reset();
|
||||
}
|
||||
|
||||
bool GLGizmoSimplify::on_esc_key_down() {
|
||||
if (m_state.status != State::running)
|
||||
return false;
|
||||
/*if (!m_is_worker_running)
|
||||
return false;
|
||||
m_state.status = State::cancelling;
|
||||
return true;
|
||||
stop_worker_thread(false);
|
||||
return true;*/
|
||||
}
|
||||
|
||||
// while opening needs GLGizmoSimplify to set window position
|
||||
void GLGizmoSimplify::add_simplify_suggestion_notification(
|
||||
const std::vector<size_t> &object_ids,
|
||||
const ModelObjectPtrs & objects,
|
||||
const std::vector<ModelObject*>& objects,
|
||||
NotificationManager & manager)
|
||||
{
|
||||
std::vector<size_t> big_ids;
|
||||
|
@ -107,9 +110,18 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
return;
|
||||
}
|
||||
|
||||
bool is_cancelling = false;
|
||||
int progress = 0;
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
is_cancelling = m_state.status == State::cancelling;
|
||||
progress = m_state.progress;
|
||||
}
|
||||
|
||||
|
||||
// Check selection of new volume
|
||||
// Do not reselect object when processing
|
||||
if (act_volume != m_volume && m_state.status != State::Status::running) {
|
||||
if (act_volume != m_volume && ! m_is_worker_running) {
|
||||
bool change_window_position = (m_volume == nullptr);
|
||||
// select different model
|
||||
|
||||
|
@ -235,9 +247,8 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
|
||||
ImGui::Checkbox(_u8L("Show wireframe").c_str(), &m_show_wireframe);
|
||||
|
||||
bool is_cancelling = m_state.status == State::cancelling;
|
||||
m_imgui->disabled_begin(is_cancelling);
|
||||
if (m_imgui->button(_L("Cancel"))) {
|
||||
if (m_imgui->button(_L("Close"))) {
|
||||
close();
|
||||
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && is_cancelling)
|
||||
ImGui::SetTooltip("%s", _u8L("Operation already cancelling. Please wait few seconds.").c_str());
|
||||
|
@ -245,21 +256,20 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
|
||||
ImGui::SameLine();
|
||||
|
||||
bool is_processing = m_state.status == State::running;
|
||||
m_imgui->disabled_begin(is_processing);
|
||||
m_imgui->disabled_begin(m_is_worker_running);
|
||||
if (m_imgui->button(_L("Apply"))) {
|
||||
apply_simplify();
|
||||
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && is_processing)
|
||||
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && m_is_worker_running)
|
||||
ImGui::SetTooltip("%s", _u8L("Can't apply when proccess preview.").c_str());
|
||||
m_imgui->disabled_end(); // state !settings
|
||||
|
||||
// draw progress bar
|
||||
if (is_processing) { // apply or preview
|
||||
if (m_is_worker_running) { // apply or preview
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
// draw progress bar
|
||||
char buf[32];
|
||||
sprintf(buf, L("Process %d / 100"), m_state.progress);
|
||||
ImGui::ProgressBar(m_state.progress / 100., ImVec2(m_gui_cfg->input_width, 0.f), buf);
|
||||
sprintf(buf, L("Process %d / 100"), progress);
|
||||
ImGui::ProgressBar(progress / 100., ImVec2(m_gui_cfg->input_width, 0.f), buf);
|
||||
}
|
||||
m_imgui->end();
|
||||
|
||||
|
@ -287,15 +297,14 @@ void GLGizmoSimplify::close() {
|
|||
|
||||
void GLGizmoSimplify::stop_worker_thread(bool wait)
|
||||
{
|
||||
if (! m_is_worker_running)
|
||||
return;
|
||||
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::Status::running) {
|
||||
assert(m_worker.joinable());
|
||||
m_state.status = State::Status::cancelling;
|
||||
if (wait)
|
||||
m_worker.join();
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::running)
|
||||
m_state.status = State::Status::cancelling;
|
||||
}
|
||||
if (wait && m_worker.joinable()) {
|
||||
m_worker.join();
|
||||
m_is_worker_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,26 +313,53 @@ void GLGizmoSimplify::stop_worker_thread(bool wait)
|
|||
// worker calls it through a CallAfter.
|
||||
void GLGizmoSimplify::worker_finished()
|
||||
{
|
||||
assert(m_worker.joinable());
|
||||
m_worker.join();
|
||||
m_is_worker_running = false;
|
||||
if (! m_worker.joinable()) {
|
||||
// Probably stop_worker_thread waited after cancel.
|
||||
// Nobody cares about the result apparently.
|
||||
assert(! m_state.result);
|
||||
return;
|
||||
}
|
||||
m_worker.join();
|
||||
if (GLGizmoBase::m_state == Off)
|
||||
return;
|
||||
if (m_state.result)
|
||||
init_model(*m_state.result);
|
||||
if (m_state.config != m_configuration) {
|
||||
// Settings were changed, restart the worker immediately.
|
||||
process();
|
||||
}
|
||||
request_rerender();
|
||||
}
|
||||
|
||||
void GLGizmoSimplify::process()
|
||||
{
|
||||
if (m_is_worker_running || m_volume == nullptr || m_volume->mesh().its.indices.empty())
|
||||
if (m_volume == nullptr || m_volume->mesh().its.indices.empty())
|
||||
return;
|
||||
|
||||
assert(! m_worker.joinable());
|
||||
bool configs_match = false;
|
||||
bool result_valid = false;
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
configs_match = m_state.config == m_configuration;
|
||||
result_valid = bool(m_state.result);
|
||||
}
|
||||
|
||||
// Worker is not running now. No synchronization needed.
|
||||
if (m_state.result && m_state.config == m_configuration)
|
||||
return; // The result is still valid.
|
||||
|
||||
// We are about to actually start simplification.
|
||||
if ((result_valid || m_is_worker_running) && configs_match) {
|
||||
// Either finished or waiting for result already. Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_is_worker_running && m_state.config != m_configuration) {
|
||||
// Worker is running with outdated config. Stop it. It will
|
||||
// restart itself when cancellation is done.
|
||||
stop_worker_thread(false);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(! m_is_worker_running && ! m_worker.joinable());
|
||||
|
||||
// Copy configuration that will be used.
|
||||
m_state.config = m_configuration;
|
||||
|
||||
// Create a copy of current mesh to pass to the worker thread.
|
||||
|
@ -333,14 +369,14 @@ void GLGizmoSimplify::process()
|
|||
|
||||
m_worker = std::thread([this](std::unique_ptr<indexed_triangle_set> its) {
|
||||
|
||||
// Checks that the UI thread did not request cancellation, throw if so.
|
||||
// Checks that the UI thread did not request cancellation, throws if so.
|
||||
std::function<void(void)> throw_on_cancel = [this]() {
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::cancelling)
|
||||
throw SimplifyCanceledException();
|
||||
};
|
||||
|
||||
// Called by worker thread,
|
||||
// Called by worker thread, updates progress bar.
|
||||
std::function<void(int)> statusfn = [this](int percent) {
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
m_state.progress = percent;
|
||||
|
@ -351,10 +387,10 @@ void GLGizmoSimplify::process()
|
|||
float max_error = std::numeric_limits<float>::max();
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_configuration.use_count)
|
||||
triangle_count = m_configuration.wanted_count;
|
||||
if (! m_configuration.use_count)
|
||||
max_error = m_configuration.max_error;
|
||||
if (m_state.config.use_count)
|
||||
triangle_count = m_state.config.wanted_count;
|
||||
if (! m_state.config.use_count)
|
||||
max_error = m_state.config.max_error;
|
||||
m_state.progress = 0;
|
||||
m_state.result.reset();
|
||||
m_state.status = State::Status::running;
|
||||
|
@ -392,13 +428,13 @@ void GLGizmoSimplify::apply_simplify() {
|
|||
plater->take_snapshot(_u8L("Simplify ") + m_volume->name);
|
||||
plater->clear_before_change_mesh(object_idx);
|
||||
|
||||
m_volume->set_mesh(*m_state.result);
|
||||
m_volume->set_mesh(std::move(*m_state.result));
|
||||
m_state.result.reset();
|
||||
m_volume->calculate_convex_hull();
|
||||
m_volume->set_new_unique_id();
|
||||
m_volume->get_object()->invalidate_bounding_box();
|
||||
|
||||
// fix hollowing, sla support points, modifiers, ...
|
||||
|
||||
// fix hollowing, sla support points, modifiers, ...
|
||||
plater->changed_mesh(object_idx);
|
||||
close();
|
||||
}
|
||||
|
@ -414,14 +450,10 @@ void GLGizmoSimplify::on_set_state()
|
|||
if (GLGizmoBase::m_state == GLGizmoBase::Off) {
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
|
||||
// Stop worker but do not wait to join it.
|
||||
stop_worker_thread(false);
|
||||
|
||||
// invalidate selected model
|
||||
m_volume = nullptr;
|
||||
stop_worker_thread(false); // Stop worker, don't wait for it.
|
||||
m_volume = nullptr; // invalidate selected model
|
||||
m_glmodel.reset();
|
||||
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
|
||||
// Make sure the worker is not running and join it.
|
||||
stop_worker_thread(true);
|
||||
// when open by hyperlink it needs to show up
|
||||
request_rerender();
|
||||
}
|
||||
|
@ -507,6 +539,7 @@ void GLGizmoSimplify::init_model(const indexed_triangle_set& its)
|
|||
|
||||
m_glmodel.reset();
|
||||
m_glmodel.init_from(its);
|
||||
m_parent.toggle_model_objects_visibility(true); // selected volume may have changed
|
||||
m_parent.toggle_model_objects_visibility(false, m_c->selection_info()->model_object(),
|
||||
m_c->selection_info()->get_active_instance(), m_volume);
|
||||
|
||||
|
|
|
@ -4,21 +4,13 @@
|
|||
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code,
|
||||
// which overrides our localization "L" macro.
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "GLGizmoPainterBase.hpp" // for render wireframe
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "admesh/stl.h" // indexed_triangle_set
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <atomic>
|
||||
|
||||
#include <GL/glew.h> // GLUint
|
||||
|
||||
// for simplify suggestion
|
||||
class ModelObjectPtrs; // std::vector<ModelObject*>
|
||||
|
||||
namespace Slic3r {
|
||||
class ModelVolume;
|
||||
class Model;
|
||||
|
||||
namespace GUI {
|
||||
class NotificationManager; // for simplify suggestion
|
||||
|
@ -31,7 +23,7 @@ public:
|
|||
bool on_esc_key_down();
|
||||
static void add_simplify_suggestion_notification(
|
||||
const std::vector<size_t> &object_ids,
|
||||
const ModelObjectPtrs & objects,
|
||||
const std::vector<ModelObject*> & objects,
|
||||
NotificationManager & manager);
|
||||
|
||||
protected:
|
||||
|
@ -81,6 +73,9 @@ private:
|
|||
return (use_count == rhs.use_count && decimate_ratio == rhs.decimate_ratio
|
||||
&& wanted_count == rhs.wanted_count && max_error == rhs.max_error);
|
||||
}
|
||||
bool operator!=(const Configuration& rhs) {
|
||||
return ! (*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Configuration m_configuration;
|
||||
|
|
Loading…
Reference in a new issue