mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-23 14:44:19 -06:00
Feat: 1. Vertical and horizontal mode for painting 2. Optimize Camera behavior (#2424)
* fix camera and update locale * Paint horizontally or vertically
This commit is contained in:
parent
53c416b819
commit
388b483774
28 changed files with 557 additions and 336 deletions
|
@ -226,9 +226,7 @@ void Camera::debug_render() const
|
|||
|
||||
std::string type = get_type_as_string();
|
||||
if (wxGetApp().plater()->get_mouse3d_controller().connected()
|
||||
#ifdef SUPPORT_FREE_CAMERA
|
||||
|| (wxGetApp().app_config->get("use_free_camera") == "1")
|
||||
#endif
|
||||
|| (wxGetApp().app_config->get_bool("use_free_camera"))
|
||||
)
|
||||
type += "/free";
|
||||
else
|
||||
|
|
|
@ -4181,29 +4181,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
}
|
||||
// do not process the dragging if the left mouse was set down in another canvas
|
||||
else if (evt.LeftIsDown()) {
|
||||
// Orca: Sphere rotation for painting view
|
||||
// if dragging over blank area with left button, rotate
|
||||
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
|
||||
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
|
||||
if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports ||
|
||||
m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
|
||||
//BBS rotate around target
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
Vec3d rotate_target = Vec3d::Zero();
|
||||
if (!m_selection.is_empty())
|
||||
rotate_target = m_selection.get_bounding_box().center();
|
||||
else
|
||||
rotate_target = volumes_bounding_box().center();
|
||||
//BBS do not limit rotate in assemble view
|
||||
camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target);
|
||||
//camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, rotate_target);
|
||||
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, rotate_target);
|
||||
}
|
||||
else {
|
||||
#ifdef SUPPORT_FEEE_CAMERA
|
||||
if (wxGetApp().app_config->get("use_free_camera") == "1")
|
||||
if (wxGetApp().app_config->get_bool("use_free_camera"))
|
||||
// Virtual track ball (similar to the 3DConnexion mouse).
|
||||
wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.));
|
||||
else {
|
||||
#endif
|
||||
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
|
||||
// It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
|
||||
// which checks an atomics (flushes CPU caches).
|
||||
|
@ -4211,38 +4207,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
|
||||
bool rotate_limit = current_printer_technology() != ptSLA;
|
||||
Vec3d rotate_target = m_selection.get_bounding_box().center();
|
||||
|
||||
camera.recover_from_free_camera();
|
||||
//BBS modify rotation
|
||||
//if (m_gizmos.get_current_type() == GLGizmosManager::FdmSupports
|
||||
// || m_gizmos.get_current_type() == GLGizmosManager::Seam
|
||||
// || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
|
||||
// //camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target);
|
||||
// //camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, rotate_target);
|
||||
//}
|
||||
//else
|
||||
if (evt.ControlDown() || evt.CmdDown()) {
|
||||
if ((m_rotation_center.x() == 0.f) && (m_rotation_center.y() == 0.f) && (m_rotation_center.z() == 0.f)) {
|
||||
auto canvas_w = float(get_canvas_size().get_width());
|
||||
auto canvas_h = float(get_canvas_size().get_height());
|
||||
Point screen_center(canvas_w/2, canvas_h/2);
|
||||
//camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, wxGetApp().plater()->get_partplate_list().get_bounding_box().center());
|
||||
m_rotation_center = _mouse_to_3d(screen_center);
|
||||
m_rotation_center(2) = 0.f;
|
||||
}
|
||||
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, m_rotation_center);
|
||||
} else {
|
||||
//BBS rotate with current plate center
|
||||
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
if (plate)
|
||||
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, plate->get_bounding_box().center());
|
||||
else
|
||||
camera.rotate_on_sphere(rot.x(), rot.y(), rotate_limit);
|
||||
}
|
||||
#ifdef SUPPORT_FEEE_CAMERA
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
|
@ -4257,16 +4236,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
const Vec3d& cur_pos = _mouse_to_3d(pos, &z);
|
||||
Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
|
||||
Camera& camera = wxGetApp().plater()->get_camera();
|
||||
#ifdef SUPPORT_FREE_CAMERA
|
||||
if (this->m_canvas_type != ECanvasType::CanvasAssembleView) {
|
||||
if (wxGetApp().app_config->get("use_free_camera") != "1")
|
||||
if (wxGetApp().app_config->get_bool("use_free_camera"))
|
||||
// Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
|
||||
// It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
|
||||
// which checks an atomics (flushes CPU caches).
|
||||
// See GH issue #3816.
|
||||
camera.recover_from_free_camera();
|
||||
}
|
||||
#endif
|
||||
|
||||
camera.set_target(camera.get_target() + orig - cur_pos);
|
||||
m_dirty = true;
|
||||
|
|
|
@ -711,6 +711,18 @@ 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_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)){
|
||||
if(m_horizontal_only){
|
||||
m_vertical_only = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
|
||||
|
|
|
@ -25,6 +25,8 @@ 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)
|
||||
|
@ -527,6 +529,7 @@ std::vector<GLGizmoPainterBase::ProjectedHeightRange> GLGizmoPainterBase::get_pr
|
|||
// concludes that the event was not intended for it, it should return false.
|
||||
bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
||||
{
|
||||
Vec2d _mouse_position = mouse_position;
|
||||
if (action == SLAGizmoEventType::MouseWheelUp
|
||||
|| action == SLAGizmoEventType::MouseWheelDown) {
|
||||
if (control_down) {
|
||||
|
@ -648,7 +651,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
// BBS
|
||||
if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::HEIGHT_RANGE)
|
||||
{
|
||||
std::vector<ProjectedHeightRange> projected_height_range_by_mesh = get_projected_height_range(mouse_position, 1., part_volumes, trafo_matrices);
|
||||
std::vector<ProjectedHeightRange> projected_height_range_by_mesh = get_projected_height_range(_mouse_position, 1., part_volumes, trafo_matrices);
|
||||
m_last_mouse_click = Vec2d::Zero();
|
||||
|
||||
for (int i = 0; i < projected_height_range_by_mesh.size(); i++) {
|
||||
|
@ -675,13 +678,20 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
m_triangle_splitting_enabled, m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f);
|
||||
|
||||
m_triangle_selectors[mesh_idx]->request_update_render_data(true);
|
||||
m_last_mouse_click = mouse_position;
|
||||
m_last_mouse_click = _mouse_position;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::vector<ProjectedMousePosition>> projected_mouse_positions_by_mesh = get_projected_mouse_positions(mouse_position, 1., trafo_matrices);
|
||||
if (action == SLAGizmoEventType::Dragging && m_tool_type == ToolType::BRUSH ){
|
||||
if(m_vertical_only)
|
||||
_mouse_position.x() = m_last_mouse_click.x();
|
||||
else if(m_horizontal_only)
|
||||
_mouse_position.y() = m_last_mouse_click.y();
|
||||
}
|
||||
|
||||
std::vector<std::vector<ProjectedMousePosition>> projected_mouse_positions_by_mesh = get_projected_mouse_positions(_mouse_position, 1., trafo_matrices);
|
||||
m_last_mouse_click = Vec2d::Zero(); // only actual hits should be saved
|
||||
|
||||
for (const std::vector<ProjectedMousePosition> &projected_mouse_positions : projected_mouse_positions_by_mesh) {
|
||||
|
@ -749,7 +759,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
|
||||
m_triangle_selectors[mesh_idx]->request_update_render_data(true);
|
||||
|
||||
m_last_mouse_click = mouse_position;
|
||||
m_last_mouse_click = _mouse_position;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -787,7 +797,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
}
|
||||
|
||||
// Now "click" into all the prepared points and spill paint around them.
|
||||
update_raycast_cache(mouse_position, camera, trafo_matrices);
|
||||
update_raycast_cache(_mouse_position, camera, trafo_matrices);
|
||||
|
||||
auto seed_fill_unselect_all = [this]() {
|
||||
for (auto &triangle_selector : m_triangle_selectors) {
|
||||
|
|
|
@ -304,6 +304,10 @@ protected:
|
|||
static constexpr float SmartFillAngleMax = 90.f;
|
||||
static constexpr float SmartFillAngleStep = 1.f;
|
||||
|
||||
// Orca: paint behavior enchancement
|
||||
bool m_vertical_only = false;
|
||||
bool m_horizontal_only = false;
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -312,6 +312,9 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
|
|||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
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);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
|
|
|
@ -35,6 +35,7 @@ protected:
|
|||
std::string get_gizmo_entering_text() const override { return "Entering Seam painting"; }
|
||||
std::string get_gizmo_leaving_text() const override { return "Leaving Seam painting"; }
|
||||
std::string get_action_snapshot_name() override { return "Paint-on seam editing"; }
|
||||
static const constexpr float CursorRadiusMin = 0.1f; // cannot be zero
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
|
|
|
@ -2862,11 +2862,7 @@ void Plater::priv::apply_free_camera_correction(bool apply/* = true*/)
|
|||
camera.set_type(Camera::EType::Perspective);
|
||||
else
|
||||
camera.set_type(Camera::EType::Ortho);
|
||||
if (apply
|
||||
#ifdef SUPPORT_FREE_CAMERA
|
||||
&& wxGetApp().app_config->get("use_free_camera") != "1"
|
||||
#endif
|
||||
)
|
||||
if (apply && wxGetApp().app_config->get_bool("use_free_camera"))
|
||||
camera.recover_from_free_camera();
|
||||
}
|
||||
|
||||
|
|
|
@ -980,6 +980,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units);
|
||||
|
||||
auto item_mouse_zoom_settings = create_item_checkbox(_L("Zoom to mouse position"), page, _L("Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."), 50, "zoom_to_mouse");
|
||||
auto item_use_free_camera_settings = create_item_checkbox(_L("Use free camera"), page, _L("If enabled, use free camera. If not enabled, use constrained camera."), 50, "use_free_camera");
|
||||
|
||||
auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints");
|
||||
auto item_gcode_window = create_item_checkbox(_L("Show g-code window"), page, _L("If enabled, g-code window will be displayed."), 50, "show_gcode_window");
|
||||
|
@ -1039,6 +1040,7 @@ wxWindow* PreferencesDialog::create_general_page()
|
|||
sizer_page->Add(item_region, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_currency, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_use_free_camera_settings, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(item_gcode_window, 0, wxTOP, FromDIP(3));
|
||||
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue