Add private member prefix m_
This commit is contained in:
parent
c04856e049
commit
090728b9d5
2 changed files with 142 additions and 136 deletions
|
@ -18,17 +18,17 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent,
|
|||
const std::string &icon_filename,
|
||||
unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, -1)
|
||||
, state(State::settings)
|
||||
, is_valid_result(false)
|
||||
, progress(0)
|
||||
, volume(nullptr)
|
||||
, obj_index(0)
|
||||
, need_reload(false)
|
||||
, m_state(State::settings)
|
||||
, m_is_valid_result(false)
|
||||
, m_progress(0)
|
||||
, m_volume(nullptr)
|
||||
, m_obj_index(0)
|
||||
, m_need_reload(false)
|
||||
{}
|
||||
|
||||
GLGizmoSimplify::~GLGizmoSimplify() {
|
||||
state = State::canceling;
|
||||
if (worker.joinable()) worker.join();
|
||||
m_state = State::canceling;
|
||||
if (m_worker.joinable()) m_worker.join();
|
||||
}
|
||||
|
||||
bool GLGizmoSimplify::on_init()
|
||||
|
@ -60,34 +60,34 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
|
||||
// Check selection of new volume
|
||||
// Do not reselect object when processing
|
||||
if (act_volume != volume && state == State::settings) {
|
||||
bool change_window_position = (volume == nullptr);
|
||||
if (act_volume != m_volume && m_state == State::settings) {
|
||||
bool change_window_position = (m_volume == nullptr);
|
||||
// select different model
|
||||
if (volume != nullptr && original_its.has_value()) {
|
||||
set_its(*original_its);
|
||||
if (m_volume != nullptr && m_original_its.has_value()) {
|
||||
set_its(*m_original_its);
|
||||
}
|
||||
|
||||
obj_index = object_idx; // to remember correct object
|
||||
volume = act_volume;
|
||||
original_its = {};
|
||||
const TriangleMesh &tm = volume->mesh();
|
||||
c.wanted_percent = 50.; // default value
|
||||
c.update_percent(tm.its.indices.size());
|
||||
is_valid_result = false;
|
||||
m_obj_index = object_idx; // to remember correct object
|
||||
m_volume = act_volume;
|
||||
m_original_its = {};
|
||||
const TriangleMesh &tm = m_volume->mesh();
|
||||
m_configuration.wanted_percent = 50.; // default value
|
||||
m_configuration.update_percent(tm.its.indices.size());
|
||||
m_is_valid_result = false;
|
||||
|
||||
if (change_window_position) {
|
||||
ImVec2 pos = ImGui::GetMousePos();
|
||||
pos.x -= gui_cfg->window_offset;
|
||||
pos.y -= gui_cfg->window_offset;
|
||||
pos.x -= m_gui_cfg->window_offset;
|
||||
pos.y -= m_gui_cfg->window_offset;
|
||||
// minimal top left value
|
||||
ImVec2 tl(gui_cfg->window_padding, gui_cfg->window_padding);
|
||||
ImVec2 tl(m_gui_cfg->window_padding, m_gui_cfg->window_padding);
|
||||
if (pos.x < tl.x) pos.x = tl.x;
|
||||
if (pos.y < tl.y) pos.y = tl.y;
|
||||
// maximal bottom right value
|
||||
auto parent_size = m_parent.get_canvas_size();
|
||||
ImVec2 br(
|
||||
parent_size.get_width() - (2 * gui_cfg->window_offset + gui_cfg->window_padding),
|
||||
parent_size.get_height() - (2 * gui_cfg->window_offset + gui_cfg->window_padding));
|
||||
parent_size.get_width() - (2 * m_gui_cfg->window_offset + m_gui_cfg->window_padding),
|
||||
parent_size.get_height() - (2 * m_gui_cfg->window_offset + m_gui_cfg->window_padding));
|
||||
if (pos.x > br.x) pos.x = br.x;
|
||||
if (pos.y > br.y) pos.y = br.y;
|
||||
ImGui::SetNextWindowPos(pos, ImGuiCond_Always);
|
||||
|
@ -98,98 +98,100 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
ImGuiWindowFlags_NoCollapse;
|
||||
m_imgui->begin(on_get_name(), flag);
|
||||
|
||||
size_t triangle_count = volume->mesh().its.indices.size();
|
||||
size_t triangle_count = m_volume->mesh().its.indices.size();
|
||||
// already reduced mesh
|
||||
if (original_its.has_value())
|
||||
triangle_count = original_its->indices.size();
|
||||
if (m_original_its.has_value())
|
||||
triangle_count = m_original_its->indices.size();
|
||||
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Mesh name") + ":");
|
||||
ImGui::SameLine(gui_cfg->top_left_width);
|
||||
std::string name = volume->name;
|
||||
ImGui::SameLine(m_gui_cfg->top_left_width);
|
||||
std::string name = m_volume->name;
|
||||
if (name.length() > max_char_in_name)
|
||||
name = name.substr(0, max_char_in_name-3) + "...";
|
||||
m_imgui->text(name);
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Triangles") + ":");
|
||||
ImGui::SameLine(gui_cfg->top_left_width);
|
||||
ImGui::SameLine(m_gui_cfg->top_left_width);
|
||||
m_imgui->text(std::to_string(triangle_count));
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text(_L("Limit by triangles").c_str());
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
// First initialization + fix triangle count
|
||||
if (m_imgui->checkbox("##UseCount", c.use_count)) {
|
||||
if (!c.use_count) c.use_error = true;
|
||||
is_valid_result = false;
|
||||
if (m_imgui->checkbox("##UseCount", m_configuration.use_count)) {
|
||||
if (!m_configuration.use_count) m_configuration.use_error = true;
|
||||
m_is_valid_result = false;
|
||||
}
|
||||
|
||||
m_imgui->disabled_begin(!c.use_count);
|
||||
m_imgui->disabled_begin(!m_configuration.use_count);
|
||||
ImGui::Text(_L("Triangle count").c_str());
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
int wanted_count = c.wanted_count;
|
||||
ImGui::SetNextItemWidth(gui_cfg->input_width);
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
int wanted_count = m_configuration.wanted_count;
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->input_width);
|
||||
if (ImGui::SliderInt("##triangle_count", &wanted_count, min_triangle_count, triangle_count, "%d")) {
|
||||
c.wanted_count = static_cast<uint32_t>(wanted_count);
|
||||
if (c.wanted_count < min_triangle_count)
|
||||
c.wanted_count = min_triangle_count;
|
||||
if (c.wanted_count > triangle_count)
|
||||
c.wanted_count = triangle_count;
|
||||
c.update_count(triangle_count);
|
||||
is_valid_result = false;
|
||||
m_configuration.wanted_count = static_cast<uint32_t>(wanted_count);
|
||||
if (m_configuration.wanted_count < min_triangle_count)
|
||||
m_configuration.wanted_count = min_triangle_count;
|
||||
if (m_configuration.wanted_count > triangle_count)
|
||||
m_configuration.wanted_count = triangle_count;
|
||||
m_configuration.update_count(triangle_count);
|
||||
m_is_valid_result = false;
|
||||
}
|
||||
ImGui::Text(_L("Ratio").c_str());
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
ImGui::SetNextItemWidth(gui_cfg->input_small_width);
|
||||
const char * precision = (c.wanted_percent > 10)? "%.0f": ((c.wanted_percent > 1)? "%.1f":"%.2f");
|
||||
float step = (c.wanted_percent > 10)? 1.f: ((c.wanted_percent > 1)? 0.1f : 0.01f);
|
||||
if (ImGui::InputFloat("%", &c.wanted_percent, step, 10*step, precision)) {
|
||||
if (c.wanted_percent > 100.f) c.wanted_percent = 100.f;
|
||||
c.update_percent(triangle_count);
|
||||
if (c.wanted_count < min_triangle_count) {
|
||||
c.wanted_count = min_triangle_count;
|
||||
c.update_count(triangle_count);
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->input_small_width);
|
||||
const char * precision = (m_configuration.wanted_percent > 10)? "%.0f":
|
||||
((m_configuration.wanted_percent > 1)? "%.1f":"%.2f");
|
||||
float step = (m_configuration.wanted_percent > 10)? 1.f:
|
||||
((m_configuration.wanted_percent > 1)? 0.1f : 0.01f);
|
||||
if (ImGui::InputFloat("%", &m_configuration.wanted_percent, step, 10*step, precision)) {
|
||||
if (m_configuration.wanted_percent > 100.f) m_configuration.wanted_percent = 100.f;
|
||||
m_configuration.update_percent(triangle_count);
|
||||
if (m_configuration.wanted_count < min_triangle_count) {
|
||||
m_configuration.wanted_count = min_triangle_count;
|
||||
m_configuration.update_count(triangle_count);
|
||||
}
|
||||
is_valid_result = false;
|
||||
m_is_valid_result = false;
|
||||
}
|
||||
m_imgui->disabled_end(); // use_count
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Text(_L("Limit by error").c_str());
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
if (m_imgui->checkbox("##UseError", c.use_error)) {
|
||||
if (!c.use_error) c.use_count = true;
|
||||
is_valid_result = false;
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
if (m_imgui->checkbox("##UseError", m_configuration.use_error)) {
|
||||
if (!m_configuration.use_error) m_configuration.use_count = true;
|
||||
m_is_valid_result = false;
|
||||
}
|
||||
|
||||
m_imgui->disabled_begin(!c.use_error);
|
||||
m_imgui->disabled_begin(!m_configuration.use_error);
|
||||
ImGui::Text(_L("Max. error").c_str());
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
ImGui::SetNextItemWidth(gui_cfg->input_small_width);
|
||||
if (ImGui::InputFloat("##maxError", &c.max_error, 0.01f, .1f, "%.2f")) {
|
||||
if (c.max_error < 0.f) c.max_error = 0.f;
|
||||
is_valid_result = false;
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->input_small_width);
|
||||
if (ImGui::InputFloat("##maxError", &m_configuration.max_error, 0.01f, .1f, "%.2f")) {
|
||||
if (m_configuration.max_error < 0.f) m_configuration.max_error = 0.f;
|
||||
m_is_valid_result = false;
|
||||
}
|
||||
m_imgui->disabled_end(); // use_error
|
||||
|
||||
if (state == State::settings) {
|
||||
if (m_state == State::settings) {
|
||||
if (m_imgui->button(_L("Cancel"))) {
|
||||
if (original_its.has_value()) {
|
||||
set_its(*original_its);
|
||||
state = State::close_on_end;
|
||||
if (m_original_its.has_value()) {
|
||||
set_its(*m_original_its);
|
||||
m_state = State::close_on_end;
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
if (m_imgui->button(_L("Preview"))) {
|
||||
state = State::simplifying;
|
||||
m_state = State::simplifying;
|
||||
// simplify but not aply on mesh
|
||||
process();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_L("Apply"))) {
|
||||
if (!is_valid_result) {
|
||||
state = State::close_on_end;
|
||||
if (!m_is_valid_result) {
|
||||
m_state = State::close_on_end;
|
||||
process();
|
||||
} else {
|
||||
// use preview and close
|
||||
|
@ -197,35 +199,35 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
|||
}
|
||||
}
|
||||
} else {
|
||||
m_imgui->disabled_begin(state == State::canceling);
|
||||
if (m_imgui->button(_L("Cancel"))) state = State::canceling;
|
||||
m_imgui->disabled_begin(m_state == State::canceling);
|
||||
if (m_imgui->button(_L("Cancel"))) m_state = State::canceling;
|
||||
m_imgui->disabled_end();
|
||||
|
||||
ImGui::SameLine(gui_cfg->bottom_left_width);
|
||||
ImGui::SameLine(m_gui_cfg->bottom_left_width);
|
||||
// draw progress bar
|
||||
char buf[32];
|
||||
sprintf(buf, L("Process %d / 100"), progress);
|
||||
ImGui::ProgressBar(progress / 100., ImVec2(gui_cfg->input_width, 0.f), buf);
|
||||
sprintf(buf, L("Process %d / 100"), m_progress);
|
||||
ImGui::ProgressBar(m_progress / 100., ImVec2(m_gui_cfg->input_width, 0.f), buf);
|
||||
}
|
||||
m_imgui->end();
|
||||
|
||||
if (need_reload) {
|
||||
need_reload = false;
|
||||
if (m_need_reload) {
|
||||
m_need_reload = false;
|
||||
|
||||
// Reload visualization of mesh - change VBO, FBO on GPU
|
||||
m_parent.reload_scene(true);
|
||||
if (state == State::close_on_end) {
|
||||
if (m_state == State::close_on_end) {
|
||||
// fix hollowing, sla support points, modifiers, ...
|
||||
auto plater = wxGetApp().plater();
|
||||
plater->changed_mesh(obj_index);
|
||||
plater->changed_mesh(m_obj_index);
|
||||
close();
|
||||
}
|
||||
|
||||
// change from simplifying | apply
|
||||
state = State::settings;
|
||||
m_state = State::settings;
|
||||
|
||||
// Fix warning icon in object list
|
||||
wxGetApp().obj_list()->update_item_error_icon(obj_index, -1);
|
||||
wxGetApp().obj_list()->update_item_error_icon(m_obj_index, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,51 +245,53 @@ void GLGizmoSimplify::process()
|
|||
const char* what() const throw() { return L("Model simplification has been canceled"); }
|
||||
};
|
||||
|
||||
if (!original_its.has_value())
|
||||
original_its = volume->mesh().its; // copy
|
||||
if (!m_original_its.has_value())
|
||||
m_original_its = m_volume->mesh().its; // copy
|
||||
|
||||
auto plater = wxGetApp().plater();
|
||||
plater->take_snapshot(_L("Simplify ") + volume->name);
|
||||
plater->clear_before_change_mesh(obj_index);
|
||||
progress = 0;
|
||||
if (worker.joinable()) worker.join();
|
||||
worker = std::thread([&]() {
|
||||
plater->take_snapshot(_L("Simplify ") + m_volume->name);
|
||||
plater->clear_before_change_mesh(m_obj_index);
|
||||
m_progress = 0;
|
||||
if (m_worker.joinable()) m_worker.join();
|
||||
m_worker = std::thread([&]() {
|
||||
// store original triangles
|
||||
uint32_t triangle_count = (c.use_count) ? c.wanted_count : 0;
|
||||
float max_error = (c.use_error) ? c.max_error : std::numeric_limits<float>::max();
|
||||
uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0;
|
||||
float max_error = (m_configuration.use_error) ?
|
||||
m_configuration.max_error : std::numeric_limits<float>::max();
|
||||
|
||||
std::function<void(void)> throw_on_cancel = [&]() {
|
||||
if (state == State::canceling) {
|
||||
if (m_state == State::canceling) {
|
||||
throw SimplifyCanceledException();
|
||||
}
|
||||
};
|
||||
std::function<void(int)> statusfn = [&](int percent) {
|
||||
progress = percent;
|
||||
m_progress = percent;
|
||||
m_parent.schedule_extra_frame(0);
|
||||
};
|
||||
|
||||
indexed_triangle_set collapsed;
|
||||
if (last_error.has_value()) {
|
||||
if (m_last_error.has_value()) {
|
||||
// is chance to continue with last reduction
|
||||
const indexed_triangle_set &its = volume->mesh().its;
|
||||
const indexed_triangle_set &its = m_volume->mesh().its;
|
||||
uint32_t last_triangle_count = static_cast<uint32_t>(its.indices.size());
|
||||
if ((!c.use_count || triangle_count <= last_triangle_count) &&
|
||||
(!c.use_error || c.max_error <= *last_error)) {
|
||||
if ((!m_configuration.use_count || triangle_count <= last_triangle_count) &&
|
||||
(!m_configuration.use_error || m_configuration.max_error <= *m_last_error)) {
|
||||
collapsed = its; // small copy
|
||||
} else {
|
||||
collapsed = *original_its; // copy
|
||||
collapsed = *m_original_its; // copy
|
||||
}
|
||||
} else {
|
||||
collapsed = *original_its; // copy
|
||||
collapsed = *m_original_its; // copy
|
||||
}
|
||||
|
||||
try {
|
||||
its_quadric_edge_collapse(collapsed, triangle_count, &max_error, throw_on_cancel, statusfn);
|
||||
set_its(collapsed);
|
||||
is_valid_result = true;
|
||||
last_error = max_error;
|
||||
m_is_valid_result = true;
|
||||
m_last_error = max_error;
|
||||
} catch (SimplifyCanceledException &) {
|
||||
state = State::settings;
|
||||
// set state out of main thread
|
||||
m_state = State::settings;
|
||||
}
|
||||
// need to render last status fn
|
||||
// without sleep it freezes until mouse move
|
||||
|
@ -299,10 +303,10 @@ void GLGizmoSimplify::process()
|
|||
void GLGizmoSimplify::set_its(indexed_triangle_set &its) {
|
||||
auto tm = std::make_unique<TriangleMesh>(its);
|
||||
tm->repair();
|
||||
volume->set_mesh(std::move(tm));
|
||||
volume->set_new_unique_id();
|
||||
volume->get_object()->invalidate_bounding_box();
|
||||
need_reload = true;
|
||||
m_volume->set_mesh(std::move(tm));
|
||||
m_volume->set_new_unique_id();
|
||||
m_volume->get_object()->invalidate_bounding_box();
|
||||
m_need_reload = true;
|
||||
}
|
||||
|
||||
bool GLGizmoSimplify::on_is_activable() const
|
||||
|
@ -313,13 +317,13 @@ bool GLGizmoSimplify::on_is_activable() const
|
|||
void GLGizmoSimplify::on_set_state()
|
||||
{
|
||||
// Closing gizmo. e.g. selecting another one
|
||||
if (m_state == GLGizmoBase::Off) {
|
||||
volume = nullptr;
|
||||
if (GLGizmoBase::m_state == GLGizmoBase::Off) {
|
||||
m_volume = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoSimplify::create_gui_cfg() {
|
||||
if (gui_cfg.has_value()) return;
|
||||
if (m_gui_cfg.has_value()) return;
|
||||
|
||||
int space_size = m_imgui->calc_text_size(":MM").x;
|
||||
GuiCfg cfg;
|
||||
|
@ -337,7 +341,7 @@ void GLGizmoSimplify::create_gui_cfg() {
|
|||
cfg.input_width = cfg.bottom_left_width;
|
||||
cfg.input_small_width = cfg.input_width * 0.8;
|
||||
cfg.window_offset = cfg.input_width;
|
||||
gui_cfg = cfg;
|
||||
m_gui_cfg = cfg;
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
|
|
@ -10,26 +10,7 @@ namespace Slic3r {
|
|||
namespace GUI {
|
||||
|
||||
class GLGizmoSimplify : public GLGizmoBase
|
||||
{
|
||||
enum class State {
|
||||
settings,
|
||||
simplifying, // start processing
|
||||
canceling, // canceled
|
||||
successfull, // successful simplified
|
||||
close_on_end
|
||||
} state;
|
||||
|
||||
bool is_valid_result; // differ what to do in apply
|
||||
int progress;
|
||||
|
||||
ModelVolume *volume;
|
||||
size_t obj_index;
|
||||
std::optional<indexed_triangle_set> original_its;
|
||||
|
||||
std::optional<float> last_error; // for use previous reduction
|
||||
|
||||
bool need_reload; // after simplify, glReload must be on main thread
|
||||
std::thread worker;
|
||||
{
|
||||
public:
|
||||
GLGizmoSimplify(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
virtual ~GLGizmoSimplify();
|
||||
|
@ -47,6 +28,28 @@ private:
|
|||
void close();
|
||||
void process();
|
||||
void set_its(indexed_triangle_set &its);
|
||||
void create_gui_cfg();
|
||||
|
||||
bool m_is_valid_result; // differ what to do in apply
|
||||
volatile int m_progress; // percent of done work
|
||||
ModelVolume *m_volume; //
|
||||
size_t m_obj_index;
|
||||
|
||||
std::optional<indexed_triangle_set> m_original_its;
|
||||
std::optional<float> m_last_error; // for use previous reduction
|
||||
|
||||
volatile bool m_need_reload; // after simplify, glReload must be on main thread
|
||||
std::thread m_worker;
|
||||
|
||||
enum class State {
|
||||
settings,
|
||||
simplifying, // start processing
|
||||
canceling, // canceled
|
||||
successfull, // successful simplified
|
||||
close_on_end
|
||||
};
|
||||
volatile State m_state;
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
bool use_count = true;
|
||||
|
@ -67,7 +70,7 @@ private:
|
|||
wanted_count = static_cast<uint32_t>(
|
||||
std::round(triangle_count * wanted_percent / 100.f));
|
||||
}
|
||||
} c;
|
||||
} m_configuration;
|
||||
|
||||
// This configs holds GUI layout size given by translated texts.
|
||||
// etc. When language changes, GUI is recreated and this class constructed again,
|
||||
|
@ -81,8 +84,7 @@ private:
|
|||
int window_offset = 100;
|
||||
int window_padding = 0;
|
||||
};
|
||||
std::optional<GuiCfg> gui_cfg;
|
||||
void create_gui_cfg();
|
||||
std::optional<GuiCfg> m_gui_cfg;
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
Loading…
Reference in a new issue