ENH:paint along line function auto enter front view perspective
Jira: STUDIO-5678 Change-Id: Ie93e8080fd4f45a8e21ff79a0248d85821797a83
This commit is contained in:
parent
044919252b
commit
1f75cd846f
|
@ -139,7 +139,7 @@ public:
|
|||
|
||||
// returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis
|
||||
bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; }
|
||||
|
||||
bool is_looking_front() const { return abs(get_dir_up().dot(Vec3d::UnitZ())-1) < 0.001; }
|
||||
// forces camera right vector to be parallel to XY plane
|
||||
void recover_from_free_camera() {
|
||||
if (std::abs(get_dir_right()(2)) > EPSILON)
|
||||
|
|
|
@ -334,11 +334,6 @@ private:
|
|||
|
||||
bool render_combo(const std::string &label, const std::vector<std::string> &lines, size_t &selection_idx, float label_width, float item_width);
|
||||
bool render_slider_double_input(const std::string &label, float &value_in, float &tolerance_in);
|
||||
enum DoubleShowType {
|
||||
Normal, // origin data
|
||||
PERCENTAGE,
|
||||
DEGREE,
|
||||
};
|
||||
bool render_slider_double_input_by_format(const std::string &label, float &value_in, float value_min, float value_max, DoubleShowType show_type = DoubleShowType::Normal);
|
||||
bool cut_line_processing() const;
|
||||
void discard_cut_line_processing();
|
||||
|
|
|
@ -145,7 +145,52 @@ void GLGizmoBase::Grabber::render(float size, const std::array<float, 4>& render
|
|||
}
|
||||
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
bool GLGizmoBase::render_slider_double_input_by_format(
|
||||
const SliderInputLayout &layout, const std::string &label, float &value_in, float value_min, float value_max, int keep_digit, DoubleShowType show_type)
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(label);
|
||||
ImGui::SameLine(layout.sliders_left_width);
|
||||
ImGui::PushItemWidth(layout.sliders_width);
|
||||
|
||||
float old_val = value_in; // (show_type == DoubleShowType::Normal)
|
||||
float value = value_in; // (show_type == DoubleShowType::Normal)
|
||||
std::string format = "%." + std::to_string(keep_digit) + "f";
|
||||
if (show_type == DoubleShowType::PERCENTAGE) {
|
||||
format = "%." + std::to_string(keep_digit) + "f %%";
|
||||
old_val = value_in;
|
||||
value = value_in * 100;
|
||||
} else if (show_type == DoubleShowType::DEGREE) {
|
||||
format = "%." + std::to_string(keep_digit) + "f " + _u8L("°");
|
||||
old_val = value_in;
|
||||
value = Geometry::rad2deg(value_in);
|
||||
}
|
||||
|
||||
if (m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, value_min, value_max, format.c_str())) {
|
||||
if (show_type == DoubleShowType::PERCENTAGE) {
|
||||
value_in = value * 0.01f;
|
||||
} else if (show_type == DoubleShowType::DEGREE) {
|
||||
value_in = Geometry::deg2rad(value);
|
||||
} else { //(show_type == DoubleShowType::Normal)
|
||||
value_in = value;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine(layout.input_left_width);
|
||||
ImGui::PushItemWidth(layout.input_width);
|
||||
if (ImGui::BBLDragFloat(("##input_" + label).c_str(), &value, 0.05f, value_min, value_max, format.c_str())) {
|
||||
if (show_type == DoubleShowType::PERCENTAGE) {
|
||||
value_in = value * 0.01f;
|
||||
} else if (show_type == DoubleShowType::DEGREE) {
|
||||
value_in = Geometry::deg2rad(value);
|
||||
} else { //(show_type == DoubleShowType::Normal)
|
||||
value_in = value;
|
||||
}
|
||||
}
|
||||
return !is_approx(old_val, value_in);
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
|
||||
: m_parent(parent)
|
||||
, m_group_id(-1)
|
||||
, m_state(Off)
|
||||
|
|
|
@ -129,6 +129,25 @@ protected:
|
|||
bool m_is_dark_mode = false;
|
||||
|
||||
std::chrono::system_clock::time_point start;
|
||||
enum DoubleShowType {
|
||||
Normal, // origin data
|
||||
PERCENTAGE,
|
||||
DEGREE,//input must is radian
|
||||
};
|
||||
struct SliderInputLayout
|
||||
{
|
||||
float sliders_left_width;
|
||||
float sliders_width;
|
||||
float input_left_width;
|
||||
float input_width;
|
||||
};
|
||||
bool render_slider_double_input_by_format(const SliderInputLayout & layout,
|
||||
const std::string & label,
|
||||
float & value_in,
|
||||
float value_min,
|
||||
float value_max,
|
||||
int keep_digit ,
|
||||
DoubleShowType show_type = DoubleShowType::Normal);
|
||||
|
||||
public:
|
||||
GLGizmoBase(GLCanvas3D& parent,
|
||||
|
|
|
@ -393,8 +393,11 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
|||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float space_size = m_imgui->get_style_scaling() * 8;
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f),
|
||||
float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f),
|
||||
m_imgui->calc_text_size(m_desc.at("reset_direction")).x + m_imgui->scaled(1.5f) + ImGui::GetStyle().FramePadding.x * 2);
|
||||
float rotate_horizontal_text= m_imgui->calc_text_size(_L("Rotate horizontally")).x + m_imgui->scaled(1.5f);
|
||||
clipping_slider_left = std::max(rotate_horizontal_text, clipping_slider_left);
|
||||
|
||||
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.5f);
|
||||
const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f);
|
||||
const float edge_detect_slider_left = m_imgui->calc_text_size(m_desc.at("edge_detection")).x + m_imgui->scaled(1.f);
|
||||
|
@ -442,6 +445,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
|||
|
||||
float color_button = ImGui::GetCursorPos().y;
|
||||
|
||||
float textbox_width = 1.5 * slider_icon_width;
|
||||
SliderInputLayout slider_input_layout = {clipping_slider_left, sliders_width, drag_left_width + circle_max_width, textbox_width};
|
||||
|
||||
m_imgui->text(m_desc.at("filaments"));
|
||||
|
||||
float start_pos_x = ImGui::GetCursorPos().x;
|
||||
|
@ -712,17 +718,49 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
|||
ImGui::BBLDragFloat("##gap_area_input", &TriangleSelectorPatch::gap_area, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only)) {
|
||||
if (m_vertical_only) {
|
||||
m_horizontal_only = false;
|
||||
if (m_current_tool == ImGui::CircleButtonIcon || m_current_tool == ImGui::SphereButtonIcon) {
|
||||
float vertical_text_width = m_imgui->calc_button_size(_L("Vertical")).x;
|
||||
float horizontal_text_width = m_imgui->calc_button_size(_L("Horizontal")).x;
|
||||
if (!wxGetApp().plater()->get_camera().is_looking_front()) {
|
||||
m_is_front_view = false;
|
||||
}
|
||||
}
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)) {
|
||||
if (m_horizontal_only) {
|
||||
m_vertical_only = false;
|
||||
auto vertical_only = m_vertical_only;
|
||||
if (m_imgui->bbl_checkbox(_L("Vertical"), vertical_only)) {
|
||||
m_vertical_only = vertical_only;
|
||||
if (m_vertical_only) {
|
||||
m_horizontal_only = false;
|
||||
m_is_front_view = true;
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine(vertical_text_width * 2.0);
|
||||
ImGui::PushItemWidth(horizontal_text_width * 2.0);
|
||||
auto horizontal_only = m_horizontal_only;
|
||||
if (m_imgui->bbl_checkbox(_L("Horizontal"), horizontal_only)) {
|
||||
m_horizontal_only = horizontal_only;
|
||||
if (m_horizontal_only) {
|
||||
m_vertical_only = false;
|
||||
m_is_front_view = true;
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
}
|
||||
|
||||
auto is_front_view = m_is_front_view;
|
||||
m_imgui->bbl_checkbox(_L("View: keep horizontal"), is_front_view);
|
||||
if (m_is_front_view != is_front_view) {
|
||||
m_is_front_view = is_front_view;
|
||||
if (m_is_front_view) {
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
}
|
||||
m_imgui->disabled_begin(!m_is_front_view);
|
||||
|
||||
if (render_slider_double_input_by_format(slider_input_layout, _u8L("Rotate horizontally"), m_front_view_radian, 0.f, 360.f, 0, DoubleShowType::DEGREE)) {
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
m_imgui->disabled_end();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
|
||||
|
|
|
@ -28,8 +28,6 @@ GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& ic
|
|||
// Make sphere and save it into a vertex buffer.
|
||||
m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.));
|
||||
m_vbo_sphere.finalize_geometry(true);
|
||||
m_vertical_only = false;
|
||||
m_horizontal_only = false;
|
||||
}
|
||||
|
||||
void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection)
|
||||
|
@ -1094,6 +1092,10 @@ void GLGizmoPainterBase::on_set_state()
|
|||
//camera.recover_from_free_camera();
|
||||
}
|
||||
m_old_state = m_state;
|
||||
m_vertical_only = false;
|
||||
m_horizontal_only = false;
|
||||
m_is_front_view = false;
|
||||
m_front_view_radian = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1127,6 +1129,14 @@ TriangleSelector::ClippingPlane GLGizmoPainterBase::get_clipping_plane_in_volume
|
|||
return TriangleSelector::ClippingPlane({float(normal_transformed.x()), float(normal_transformed.y()), float(normal_transformed.z()), offset_transformed});
|
||||
}
|
||||
|
||||
void GLGizmoPainterBase::change_camera_view_angle(float front_view_radian)
|
||||
{
|
||||
wxGetApp().plater()->get_camera().select_view("front");
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
auto rotate_target = selection.get_bounding_box().center();
|
||||
wxGetApp().plater()->get_camera().rotate_local_with_target(Vec3d(0, front_view_radian, 0), rotate_target);
|
||||
}
|
||||
|
||||
std::array<float, 4> TriangleSelectorGUI::get_seed_fill_color(const std::array<float, 4> &base_color)
|
||||
{
|
||||
// BBS
|
||||
|
|
|
@ -305,9 +305,10 @@ protected:
|
|||
static constexpr float SmartFillAngleStep = 1.f;
|
||||
|
||||
// BBL: paint behavior enchancement
|
||||
bool m_vertical_only = false;
|
||||
bool m_horizontal_only = false;
|
||||
|
||||
bool m_vertical_only = false;
|
||||
bool m_horizontal_only = false;
|
||||
bool m_is_front_view = false;
|
||||
float m_front_view_radian = 0;
|
||||
// It stores the value of the previous mesh_id to which the seed fill was applied.
|
||||
// It is used to detect when the mouse has moved from one volume to another one.
|
||||
int m_seed_fill_last_mesh_id = -1;
|
||||
|
@ -328,7 +329,8 @@ protected:
|
|||
|
||||
TriangleSelector::ClippingPlane get_clipping_plane_in_volume_coordinates(const Transform3d &trafo) const;
|
||||
|
||||
private:
|
||||
void change_camera_view_angle(float front_view_radian);
|
||||
private:
|
||||
std::vector<std::vector<ProjectedMousePosition>> get_projected_mouse_positions(const Vec2d &mouse_position, double resolution, const std::vector<Transform3d> &trafo_matrices) const;
|
||||
|
||||
std::vector<ProjectedHeightRange> get_projected_height_range(const Vec2d& mouse_position, double resolution, const std::vector<const ModelVolume*>& part_volumes, const std::vector<Transform3d>& trafo_matrices) const;
|
||||
|
|
|
@ -201,9 +201,11 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
|
|||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float space_size = m_imgui->get_style_scaling() * 8;
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("reset_direction")).x + ImGui::GetStyle().FramePadding.x * 2)
|
||||
+ m_imgui->scaled(1.5f);
|
||||
float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("reset_direction")).x + ImGui::GetStyle().FramePadding.x * 2) +
|
||||
m_imgui->scaled(1.5f);
|
||||
float rotate_horizontal_text = m_imgui->calc_text_size(_L("Rotate horizontally")).x + m_imgui->scaled(1.5f);
|
||||
clipping_slider_left = std::max(rotate_horizontal_text, clipping_slider_left);
|
||||
const float cursor_size_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
|
||||
const float empty_button_width = m_imgui->calc_button_size("").x;
|
||||
|
||||
|
@ -222,6 +224,9 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
|
|||
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
|
||||
float textbox_width = 1.5 * slider_icon_width;
|
||||
SliderInputLayout slider_input_layout = {sliders_left_width, sliders_width, drag_left_width, textbox_width};
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("cursor_type"));
|
||||
std::array<wchar_t, 2> tool_ids = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon };
|
||||
|
@ -313,8 +318,31 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
|
|||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position(clp_dist, true); }
|
||||
|
||||
ImGui::Separator();
|
||||
m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only);
|
||||
|
||||
if (!wxGetApp().plater()->get_camera().is_looking_front()){
|
||||
m_is_front_view = false;
|
||||
}
|
||||
auto vertical_only = m_vertical_only;
|
||||
if (m_imgui->bbl_checkbox(_L("Vertical"), vertical_only)) {
|
||||
m_vertical_only = vertical_only;
|
||||
if (m_vertical_only) {
|
||||
m_is_front_view = true;
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
}
|
||||
auto is_front_view = m_is_front_view;
|
||||
m_imgui->bbl_checkbox(_L("View: keep horizontal"), is_front_view);
|
||||
if (m_is_front_view != is_front_view) {
|
||||
m_is_front_view = is_front_view;
|
||||
if (m_is_front_view) {
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
}
|
||||
m_imgui->disabled_begin(!m_is_front_view);
|
||||
if (render_slider_double_input_by_format(slider_input_layout, _u8L("Rotate horizontally"), m_front_view_radian, 0.f, 360.f, 0, DoubleShowType::DEGREE)) {
|
||||
change_camera_view_angle(m_front_view_radian);
|
||||
}
|
||||
m_imgui->disabled_end();
|
||||
ImGui::Separator();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
|
||||
|
|
Loading…
Reference in New Issue