Measuring: prototype for uniformly scale a volume by editing the value of the shown distance
This commit is contained in:
parent
836b45a2ed
commit
1922213725
@ -220,6 +220,7 @@ void GLGizmoMeasure::data_changed()
|
||||
m_last_plane_idx = -1;
|
||||
m_selected_features.reset();
|
||||
m_selection_raycasters.clear();
|
||||
m_editing_distance = false;
|
||||
}
|
||||
|
||||
bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
||||
@ -256,6 +257,7 @@ void GLGizmoMeasure::on_set_state()
|
||||
m_curr_feature.reset();
|
||||
m_curr_point_on_feature_position.reset();
|
||||
restore_scene_raycasters_state();
|
||||
m_editing_distance = false;
|
||||
}
|
||||
else {
|
||||
m_mode = EMode::BasicSelection;
|
||||
@ -840,18 +842,79 @@ void GLGizmoMeasure::render_dimensioning()
|
||||
ss_to_ndc_matrix * Geometry::translation_transform(v2ss_3) * q12ss);
|
||||
m_dimensioning.triangle.render();
|
||||
|
||||
const bool use_inches = wxGetApp().app_config->get("use_inches") == "1";
|
||||
const double value = use_inches ? ObjectManipulation::mm_to_in * distance : distance;
|
||||
const std::string value_str = format_double(value);
|
||||
const std::string units = use_inches ? _u8L("in") : _u8L("mm");
|
||||
const float value_str_width = 20.0f + ImGui::CalcTextSize(value_str.c_str()).x;
|
||||
static double edit_value = 0.0;
|
||||
|
||||
const Vec2d label_position = 0.5 * (v1ss + v2ss);
|
||||
m_imgui->set_next_window_pos(label_position.x(), viewport[3] - label_position.y(), ImGuiCond_Always, 0.0f, 1.0f);
|
||||
m_imgui->set_next_window_bg_alpha(0.0f);
|
||||
|
||||
if (!m_editing_distance) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 1.0f, 1.0f });
|
||||
m_imgui->begin(std::string("distance"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(value_str + " " + units);
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->image_button(ImGui::SliderFloatEditBtnIcon, _L("Edit to scale"))) {
|
||||
m_editing_distance = true;
|
||||
edit_value = value;
|
||||
m_imgui->requires_extra_frame();
|
||||
}
|
||||
m_imgui->end();
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
auto perform_scale = [this, value](double new_value, double old_value) {
|
||||
if (new_value == old_value || new_value <= 0.0)
|
||||
return;
|
||||
|
||||
const double ratio = new_value / old_value;
|
||||
wxGetApp().plater()->take_snapshot(_L("Scale"));
|
||||
|
||||
TransformationType type;
|
||||
type.set_world();
|
||||
type.set_relative();
|
||||
type.set_joint();
|
||||
|
||||
// apply scale
|
||||
Selection& selection = m_parent.get_selection();
|
||||
selection.setup_cache();
|
||||
selection.scale(ratio * Vec3d::Ones(), type);
|
||||
wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
};
|
||||
|
||||
if (m_editing_distance && !ImGui::IsPopupOpen("distance_popup"))
|
||||
ImGui::OpenPopup("distance_popup");
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
m_imgui->begin(_L("##distance"), ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||
const bool use_inches = wxGetApp().app_config->get("use_inches") == "1";
|
||||
const std::string txt = use_inches ? format_double(ObjectManipulation::mm_to_in * distance) + " " + _u8L("in") :
|
||||
format_double(distance) + " " + _u8L("mm");
|
||||
m_imgui->text(txt);
|
||||
m_imgui->end();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 1.0f, 1.0f });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 4.0f, 0.0f });
|
||||
if (ImGui::BeginPopupModal("distance_popup", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration)) {
|
||||
ImGui::PushItemWidth(value_str_width);
|
||||
if (ImGui::InputDouble("##distance", &edit_value, 0.0f, 0.0f, "%.3f")) {
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_u8L("Scale"))) {
|
||||
perform_scale(edit_value, value);
|
||||
m_editing_distance = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_u8L("Cancel"))) {
|
||||
m_editing_distance = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar(4);
|
||||
};
|
||||
|
||||
auto point_edge = [this, shader](const Measure::SurfaceFeature& f1, const Measure::SurfaceFeature& f2) {
|
||||
@ -1194,7 +1257,10 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
static float last_y = 0.0f;
|
||||
static float last_h = 0.0f;
|
||||
|
||||
m_imgui->begin(_L("Measure tool"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
if (m_editing_distance)
|
||||
return;
|
||||
|
||||
m_imgui->begin(_u8L("Measure tool"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// adjust window position to avoid overlap the view toolbar
|
||||
const float win_h = ImGui::GetWindowHeight();
|
||||
@ -1341,28 +1407,11 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
m_imgui->text_colored(col_2_color, col_2);
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
const ImTextureID tex_id = io.Fonts->TexID;
|
||||
assert(io.Fonts->TexWidth > 0 && io.Fonts->TexHeight > 0);
|
||||
float inv_tex_w = 1.0f / float(io.Fonts->TexWidth);
|
||||
float inv_tex_h = 1.0f / float(io.Fonts->TexHeight);
|
||||
const ImFontAtlasCustomRect* const rect = m_imgui->GetTextureCustomRect(ImGui::ClipboardBtnIcon);
|
||||
const ImVec2 size = { float(rect->Width), float(rect->Height) };
|
||||
const ImVec2 uv0 = ImVec2(float(rect->X) * inv_tex_w, float(rect->Y) * inv_tex_h);
|
||||
const ImVec2 uv1 = ImVec2(float(rect->X + rect->Width) * inv_tex_w, float(rect->Y + rect->Height) * inv_tex_h);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.4f, 0.4f, 0.4f, 1.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.25f, 0.25f, 0.25f, 1.0f });
|
||||
if (m_imgui->image_button(tex_id, size, uv0, uv1)) {
|
||||
if (m_imgui->image_button(ImGui::ClipboardBtnIcon, _L("Copy to clipboard"))) {
|
||||
wxTheClipboard->Open();
|
||||
wxTheClipboard->SetData(new wxTextDataObject(col_1 + ": " + col_2));
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
m_imgui->tooltip(into_u8(_L("Copy to clipboard")).c_str(), max_tooltip_width);
|
||||
}
|
||||
};
|
||||
|
||||
if (m_selected_features.second.feature.has_value()) {
|
||||
@ -1373,7 +1422,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
m_imgui->text(_u8L("Measure") + ":");
|
||||
if (ImGui::BeginTable("Measure", 3)) {
|
||||
if (measure.angle.has_value()) {
|
||||
ImGui::PushID((void*)(intptr_t)1);
|
||||
ImGui::PushID("ClipboardAngle");
|
||||
add_measure_row_to_table(_u8L("Angle"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(Geometry::rad2deg(measure.angle->angle)) + "°",
|
||||
ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
ImGui::PopID();
|
||||
@ -1382,7 +1431,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
double distance = measure.distance_infinite->dist;
|
||||
if (use_inches)
|
||||
distance = ObjectManipulation::mm_to_in * distance;
|
||||
ImGui::PushID((void*)(intptr_t)2);
|
||||
ImGui::PushID("ClipboardDistanceInfinite");
|
||||
add_measure_row_to_table(_u8L("Distance Infinite"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units,
|
||||
ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
ImGui::PopID();
|
||||
@ -1392,7 +1441,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
double distance = measure.distance_strict->dist;
|
||||
if (use_inches)
|
||||
distance = ObjectManipulation::mm_to_in * distance;
|
||||
ImGui::PushID((void*)(intptr_t)3);
|
||||
ImGui::PushID("ClipboardDistanceStrict");
|
||||
add_measure_row_to_table(_u8L("Distance Strict"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units,
|
||||
ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
ImGui::PopID();
|
||||
@ -1401,7 +1450,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
||||
Vec3d distance = *measure.distance_xyz;
|
||||
if (use_inches)
|
||||
distance = ObjectManipulation::mm_to_in * distance;
|
||||
ImGui::PushID((void*)(intptr_t)4);
|
||||
ImGui::PushID("ClipboardDistanceXYZ");
|
||||
add_measure_row_to_table(_u8L("Distance XYZ"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(distance),
|
||||
ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
ImGui::PopID();
|
||||
|
@ -118,6 +118,7 @@ class GLGizmoMeasure : public GLGizmoBase
|
||||
KeyAutoRepeatFilter m_ctrl_kar_filter;
|
||||
|
||||
SelectedFeatures m_selected_features;
|
||||
bool m_editing_distance{ false };
|
||||
|
||||
void update_if_needed();
|
||||
|
||||
|
@ -431,36 +431,6 @@ bool ImGuiWrapper::draw_radio_button(const std::string& name, float size, bool a
|
||||
}
|
||||
#endif // ENABLE_PREVIEW_LAYOUT
|
||||
|
||||
bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format)
|
||||
{
|
||||
return ImGui::InputDouble(label.c_str(), const_cast<double*>(&value), 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal);
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::input_double(const wxString &label, const double &value, const std::string &format)
|
||||
{
|
||||
auto label_utf8 = into_u8(label);
|
||||
return input_double(label_utf8, value, format);
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format)
|
||||
{
|
||||
bool value_changed = false;
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
std::string item_label = (i == 0) ? "X" : ((i == 1) ? "Y" : "Z");
|
||||
ImGui::PushID(i);
|
||||
ImGui::PushItemWidth(width);
|
||||
value_changed |= ImGui::InputDouble(item_label.c_str(), const_cast<double*>(&value(i)), 0.0f, 0.0f, format.c_str());
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::checkbox(const wxString &label, bool &value)
|
||||
{
|
||||
auto label_utf8 = into_u8(label);
|
||||
@ -519,20 +489,20 @@ void ImGuiWrapper::text_wrapped(const wxString &label, float wrap_width)
|
||||
|
||||
void ImGuiWrapper::tooltip(const char *label, float wrap_width)
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8.0f, 8.0f });
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(wrap_width);
|
||||
ImGui::TextUnformatted(label);
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
void ImGuiWrapper::tooltip(const wxString &label, float wrap_width)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(wrap_width);
|
||||
ImGui::TextUnformatted(label.ToUTF8().data());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
tooltip(label.ToUTF8().data(), wrap_width);
|
||||
}
|
||||
|
||||
ImVec2 ImGuiWrapper::get_slider_icon_size() const
|
||||
@ -684,6 +654,29 @@ bool ImGuiWrapper::image_button(ImTextureID user_texture_id, const ImVec2& size,
|
||||
return image_button_ex(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col, flags);
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::image_button(const wchar_t icon, const wxString& tooltip)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
const ImTextureID tex_id = io.Fonts->TexID;
|
||||
assert(io.Fonts->TexWidth > 0 && io.Fonts->TexHeight > 0);
|
||||
const float inv_tex_w = 1.0f / float(io.Fonts->TexWidth);
|
||||
const float inv_tex_h = 1.0f / float(io.Fonts->TexHeight);
|
||||
const ImFontAtlasCustomRect* const rect = GetTextureCustomRect(icon);
|
||||
const ImVec2 size = { float(rect->Width), float(rect->Height) };
|
||||
const ImVec2 uv0 = ImVec2(float(rect->X) * inv_tex_w, float(rect->Y) * inv_tex_h);
|
||||
const ImVec2 uv1 = ImVec2(float(rect->X + rect->Width) * inv_tex_w, float(rect->Y + rect->Height) * inv_tex_h);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.4f, 0.4f, 0.4f, 1.0f });
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.25f, 0.25f, 0.25f, 1.0f });
|
||||
const bool res = image_button(tex_id, size, uv0, uv1);
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
if (!tooltip.empty() && ImGui::IsItemHovered())
|
||||
this->tooltip(tooltip, ImGui::GetFontSize() * 20.0f);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags)
|
||||
{
|
||||
// this is to force the label to the left of the widget:
|
||||
|
@ -95,9 +95,6 @@ public:
|
||||
#if ENABLE_PREVIEW_LAYOUT
|
||||
bool draw_radio_button(const std::string& name, float size, bool active, std::function<void(ImGuiWindow& window, const ImVec2& pos, float size)> draw_callback);
|
||||
#endif // ENABLE_PREVIEW_LAYOUT
|
||||
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
|
||||
bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f");
|
||||
bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f");
|
||||
bool checkbox(const wxString &label, bool &value);
|
||||
void text(const char *label);
|
||||
void text(const std::string &label);
|
||||
@ -118,6 +115,7 @@ public:
|
||||
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
|
||||
|
||||
bool image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0.0, 0.0), const ImVec2& uv1 = ImVec2(1.0, 1.0), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0.0, 0.0, 0.0, 0.0), const ImVec4& tint_col = ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags flags = 0);
|
||||
bool image_button(const wchar_t icon, const wxString& tooltip = L"");
|
||||
|
||||
// Use selection = -1 to not mark any option as selected
|
||||
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags = 0);
|
||||
|
Loading…
Reference in New Issue
Block a user