Shared data packed in a struct

This commit is contained in:
Lukas Matena 2021-10-29 12:35:57 +02:00
parent ba56a79795
commit 6661967f9f
2 changed files with 55 additions and 78 deletions

View File

@ -16,10 +16,9 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
const std::string &icon_filename,
unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, -1)
, m_state(State::settings)
, m_state({ State::settings, 0 })
, m_is_valid_result(false)
, m_exist_preview(false)
, m_progress(0)
, m_volume(nullptr)
, m_obj_index(0)
, m_need_reload(false)
@ -34,16 +33,16 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
{}
GLGizmoSimplify::~GLGizmoSimplify() {
m_state = State::canceling;
m_state.status = State::canceling;
if (m_worker.joinable()) m_worker.join();
m_glmodel.reset();
}
bool GLGizmoSimplify::on_esc_key_down() {
if (m_state == State::settings || m_state == State::canceling)
if (m_state.status == State::settings || m_state.status == State::canceling)
return false;
m_state = State::canceling;
m_state.status = State::canceling;
return true;
}
@ -111,17 +110,17 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
int obj_index = selection.get_object_idx();
ModelVolume *act_volume = get_volume(selection, wxGetApp().plater()->model());
if (act_volume == nullptr) {
switch (m_state) {
switch (m_state.status) {
case State::settings: close(); break;
case State::canceling: break;
default: m_state = State::canceling;
default: m_state.status = State::canceling;
}
return;
}
// Check selection of new volume
// Do not reselect object when processing
if (act_volume != m_volume && m_state == State::settings) {
if (act_volume != m_volume && m_state.status == State::settings) {
bool change_window_position = (m_volume == nullptr);
// select different model
if (m_volume != nullptr && m_original_its.has_value()) {
@ -264,18 +263,18 @@ 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_canceling = m_state == State::canceling;
bool is_canceling = m_state.status == State::canceling;
m_imgui->disabled_begin(is_canceling);
if (m_imgui->button(_L("Cancel"))) {
if (m_state == State::settings) {
if (m_state.status == State::settings) {
if (m_original_its.has_value()) {
set_its(*m_original_its);
m_state = State::close_on_end;
m_state.status = State::close_on_end;
} else {
close();
}
} else {
m_state = State::canceling;
m_state.status = State::canceling;
}
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && is_canceling)
ImGui::SetTooltip("%s", _u8L("Operation already canceling. Please wait few seconds.").c_str());
@ -283,11 +282,11 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
ImGui::SameLine();
bool is_processing = m_state != State::settings;
bool is_processing = m_state.status != State::settings;
m_imgui->disabled_begin(is_processing);
if (m_imgui->button(_L("Apply"))) {
if (!m_is_valid_result) {
m_state = State::close_on_end;
m_state.status = State::close_on_end;
process();
} else if (m_exist_preview) {
// use preview and close
@ -304,20 +303,18 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
ImGui::SameLine(m_gui_cfg->bottom_left_width);
// draw progress bar
char buf[32];
int progress = m_progress;
sprintf(buf, L("Process %d / 100"), progress);
ImGui::ProgressBar(progress / 100., ImVec2(m_gui_cfg->input_width, 0.f), buf);
sprintf(buf, L("Process %d / 100"), m_state.progress);
ImGui::ProgressBar(m_state.progress / 100., ImVec2(m_gui_cfg->input_width, 0.f), buf);
}
m_imgui->end();
// refresh view when needed
if (m_need_reload) {
m_need_reload = false;
bool close_on_end = (m_state == State::close_on_end);
// Reload visualization of mesh - change VBO, FBO on GPU
bool close_on_end = (m_state.status == State::close_on_end);
request_rerender();
// set m_state must be before close() !!!
m_state = State::settings;
// set m_state.status must be before close() !!!
m_state.status = State::settings;
if (close_on_end) after_apply();
else init_model();
// Fix warning icon in object list
@ -330,6 +327,7 @@ void GLGizmoSimplify::after_apply() {
m_exist_preview = false;
// fix hollowing, sla support points, modifiers, ...
auto plater = wxGetApp().plater();
plater->take_snapshot(_u8L("Simplify ") + m_volume->name);
plater->changed_mesh(m_obj_index);
close();
}
@ -342,19 +340,12 @@ void GLGizmoSimplify::close() {
void GLGizmoSimplify::live_preview() {
m_is_valid_result = false;
if (m_state != State::settings) {
if (m_state.status != State::settings) {
// already canceling process
if (m_state == State::canceling) return;
// wait until cancel
if (m_worker.joinable()) {
m_state = State::canceling;
m_dealy_process_cv.notify_one();
m_worker.join();
}
if (m_state.status == State::canceling) return;
}
m_state = State::preview;
m_state.status = State::preview;
process();
}
@ -387,48 +378,29 @@ void GLGizmoSimplify::process()
// store previous state
auto plater = wxGetApp().plater();
plater->take_snapshot(_u8L("Simplify ") + m_volume->name);
// LUKAS: ???
plater->clear_before_change_mesh(m_obj_index);
}
m_progress = 0;
m_state.progress = 0;
if (m_worker.joinable()) m_worker.join();
m_worker = std::thread([this]() {
{// delay before process
std::unique_lock<std::mutex> lk(m_state_mutex);
auto is_modify = [this]() { return m_state == State::canceling; };
if (m_dealy_process_cv.wait_for(lk, m_gui_cfg->prcess_delay, is_modify)) {
// exist modification
m_state = State::settings;
request_rerender();
return;
}
}
m_worker = std::thread([this]() {
// store original triangles
uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0;
float max_error = (!m_configuration.use_count) ? m_configuration.max_error : std::numeric_limits<float>::max();
std::function<void(void)> throw_on_cancel = [&]() {
if (m_state == State::canceling) {
// Checks that the UI thread did not request cancellation, throw if so.
std::function<void(void)> throw_on_cancel = [this]() {
if (m_state.status == State::canceling)
throw SimplifyCanceledException();
}
};
int64_t last = 0;
std::function<void(int)> statusfn = [this, &last](int percent) {
m_progress = percent;
// check max 4fps
int64_t now = m_parent.timestamp_now();
if ((now - last) < 250) return;
last = now;
request_rerender();
// Called by worker thread,
std::function<void(int)> statusfn = [this](int percent) {
m_state.progress = percent;
};
indexed_triangle_set collapsed = *m_original_its; // copy
uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0;
float max_error = (!m_configuration.use_count) ? m_configuration.max_error : std::numeric_limits<float>::max();
try {
its_quadric_edge_collapse(collapsed, triangle_count, &max_error, throw_on_cancel, statusfn);
@ -437,7 +409,7 @@ void GLGizmoSimplify::process()
m_exist_preview = true;
} catch (SimplifyCanceledException &) {
// set state out of main thread
m_state = State::settings;
m_state.status = State::settings;
}
// need to render last status fn to change bar graph to buttons
request_rerender();
@ -469,13 +441,13 @@ void GLGizmoSimplify::on_set_state()
// cancel processing
if (empty_selection &&
m_state != State::settings &&
m_state != State::canceling)
m_state = State::canceling;
m_state.status != State::settings &&
m_state.status != State::canceling)
m_state.status = State::canceling;
// refuse outgoing during simlification
// object is not selected when it is deleted(cancel and close gizmo)
if (m_state != State::settings && !empty_selection) {
if (m_state.status != State::settings && !empty_selection) {
GLGizmoBase::m_state = GLGizmoBase::On;
auto notification_manager = wxGetApp().plater()->get_notification_manager();
notification_manager->push_notification(

View File

@ -4,13 +4,11 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code,
// which overrides our localization "L" macro.
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLModel.hpp"
#include "GLGizmoPainterBase.hpp" // for render wireframe
#include "slic3r/GUI/GLModel.hpp"
#include "admesh/stl.h" // indexed_triangle_set
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <optional>
#include <atomic>
@ -35,6 +33,7 @@ public:
const std::vector<size_t> &object_ids,
const ModelObjectPtrs & objects,
NotificationManager & manager);
protected:
virtual std::string on_get_name() const override;
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
@ -48,6 +47,7 @@ protected:
virtual void on_render_for_picking() override{};
virtual CommonGizmosDataID on_get_requirements() const;
private:
void after_apply();
void close();
@ -70,7 +70,7 @@ private:
bool m_move_to_center; // opening gizmo
std::atomic<int> m_progress; // percent of done work
ModelVolume *m_volume; // keep pointer to actual working volume
size_t m_obj_index;
@ -81,17 +81,22 @@ private:
std::atomic<bool> m_need_reload; // after simplify, glReload must be on main thread
std::thread m_worker;
// wait before process
std::mutex m_state_mutex;
std::condition_variable m_dealy_process_cv;
enum class State {
settings,
preview, // simplify to show preview
close_on_end, // simplify with close on end
canceling // after button click, before canceled
struct State {
enum Status {
settings,
preview, // simplify to show preview
close_on_end, // simplify with close on end
canceling // after button click, before canceled
};
Status status;
int progress; // percent of done work
indexed_triangle_set result;
};
std::atomic<State> m_state;
State m_state;
struct Configuration
{