mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 23:01:17 +00:00
Keep the Design tab's bed, grid and reference planes aligned on every plate
This commit is contained in:
@@ -246,6 +246,15 @@ The tab is a page of Orca's main window and answers to the same settings as Prep
|
||||
`DesignRowList` rather than a `wxTreeCtrl`, so each row carries its own actions — Edit,
|
||||
Show/hide and Delete on a feature, Move, Show/hide and Delete on a body — and the eye shows
|
||||
whether that row is hidden.
|
||||
- **Plates.** This is the one thing the tab does not follow. The canvas has a bed of its own at
|
||||
the printer bed's home position, whichever plate Prepare has current, and a new document's
|
||||
modeling origin is that bed's centre. A bed that followed the current plate would slide out
|
||||
from under a design: the origin is fixed once per document, baked into every sketch plane and
|
||||
saved in the recipe, while the current plate can change between visits. Commit to Plate does
|
||||
not need it either, since the committed object is placed on an empty spot of the current
|
||||
plate. What the canvas does read from the plate is moved onto its bed: the exclude areas, the
|
||||
plate box the camera orbits about when nothing is picked (`GLCanvas3D::_current_plate_box`),
|
||||
and the first view, which starts as a copy of Prepare's camera.
|
||||
- **Viewport text.** The status line and the active tool's values are drawn by the canvas in
|
||||
its ImGui pass, so they go with the canvas: a top-level window over GL does not follow its
|
||||
frame and was left floating over other applications.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "slic3r/GUI/Camera.hpp" // N: look down the sketch plane normal
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/PartPlate.hpp" // the current plate's origin: the first view's offset
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/GLToolbar.hpp"
|
||||
#include "slic3r/GUI/Event.hpp"
|
||||
@@ -190,8 +191,11 @@ DesignCanvas::DesignCanvas(wxWindow* parent)
|
||||
refresh_bed();
|
||||
|
||||
// The view this canvas opens on. Built lazily, on the way into the Design tab, so this
|
||||
// is the view the user is looking at right now.
|
||||
// is the view the user is looking at right now — moved off the current plate onto the
|
||||
// Design bed, which stays at the printer bed's home whichever plate is current.
|
||||
m_parked_camera = wxGetApp().plater()->get_camera();
|
||||
if (PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate())
|
||||
m_parked_camera.translate_world(-plate->get_origin());
|
||||
|
||||
// Before any of this class's own Binds below: wx calls dynamically bound handlers in
|
||||
// reverse order of binding, and GLCanvas3D swallows several events without skipping them —
|
||||
@@ -554,6 +558,7 @@ void DesignCanvas::refresh_bed()
|
||||
double printable_height = 100.0;
|
||||
const auto* ph_opt = config->opt<ConfigOptionFloat>("printable_height");
|
||||
if (ph_opt) printable_height = ph_opt->value;
|
||||
// No position: the Design bed stays at the printer bed's home, whichever plate is current.
|
||||
m_bed.set_shape(bed_shape_opt->values, printable_height, {}, {}, "", false); // mainline added extruder_areas/heights params
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include <utility>
|
||||
#include <wx/colour.h>
|
||||
@@ -83,6 +84,8 @@ public:
|
||||
void finish_sketch();
|
||||
bool is_sketching() const;
|
||||
void refresh_bed(); // re-sync the bed to the current printer (call on tab activation)
|
||||
// Centre of the Design bed: the printer bed at its home position, whichever plate is current.
|
||||
Vec2d bed_center() const { return m_bed.build_volume().bed_center(); }
|
||||
// The Camera is Plater-owned and shared with Prepare/Preview/Assemble; GLCanvas3D has no
|
||||
// per-canvas camera, so every orbit here would otherwise overwrite what the editor tabs
|
||||
// show. Exactly one of the two views is live at a time, so entering and leaving are the
|
||||
|
||||
@@ -104,7 +104,6 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/Shortcuts.hpp"
|
||||
@@ -7345,8 +7344,12 @@ void DesignPanel::hydrate_from_model()
|
||||
// that has none yet. A design in progress keeps its origin: its sketches have it baked into
|
||||
// their planes, so moving it under them (a printer change between visits) would slide the
|
||||
// datum planes off the geometry. A loaded project brings its own (load_recipe).
|
||||
// The centre of the Design bed, not the plater's: the plater moves its bed onto the current
|
||||
// plate, so on plate 2+ the origin would land one plate stride away from the bed drawn here.
|
||||
// Re-synced first because the control socket calls this without on_tab_shown().
|
||||
if (!m_doc.origin_from_recipe) {
|
||||
const Vec2d bc = plater->build_volume().bed_center();
|
||||
m_viewport->refresh_bed();
|
||||
const Vec2d bc = m_viewport->bed_center();
|
||||
m_doc.modeling_origin = Vec3d(bc.x(), bc.y(), 0.0);
|
||||
// A document started here takes the weld rule from the preference; a loaded one
|
||||
// brings its own (load_recipe).
|
||||
|
||||
@@ -1875,7 +1875,7 @@ BoundingBoxf3 GLCanvas3D::volumes_bounding_box(bool current_plate_only) const
|
||||
bool is_limit = m_canvas_type != ECanvasType::CanvasAssembleView;
|
||||
if (is_limit) {
|
||||
if (current_plate_only) {
|
||||
expand_part_plate_list_box = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_bounding_box();
|
||||
expand_part_plate_list_box = _current_plate_box();
|
||||
} else {
|
||||
auto plate_list_box = wxGetApp().plater()->get_partplate_list().get_bounding_box();
|
||||
auto horizontal_radius = 0.5 * sqrt(std::pow(plate_list_box.min[0] - plate_list_box.max[0], 2) + std::pow(plate_list_box.min[1] - plate_list_box.max[1], 2));
|
||||
@@ -8267,7 +8267,30 @@ void GLCanvas3D::_render_bed(const Transform3d& view_matrix, const Transform3d&
|
||||
|
||||
void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali, bool show_grid)
|
||||
{
|
||||
wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid, !m_plate_chrome_enabled);
|
||||
PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
|
||||
// Design tab: its bed stays at the printer bed's home whichever plate is current, so the
|
||||
// current plate's exclude areas are moved from that plate onto it.
|
||||
PartPlate* curr_plate = plate_list.get_curr_plate();
|
||||
const Transform3d plate_view_matrix = m_axes_at_bed_center && curr_plate != nullptr ?
|
||||
Transform3d(view_matrix * Geometry::translation_transform(-curr_plate->get_origin())) : view_matrix;
|
||||
plate_list.render(plate_view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid, !m_plate_chrome_enabled);
|
||||
}
|
||||
|
||||
BoundingBoxf3 GLCanvas3D::_current_plate_box() const
|
||||
{
|
||||
// Design tab: its own bed stands in for the current plate (see _render_platelist).
|
||||
const BuildVolume& build_volume = m_bed.build_volume();
|
||||
if (m_axes_at_bed_center && build_volume.valid()) {
|
||||
// Flat at z = 0 like the plate's own box. Merged, as PartPlate builds it: the min/max
|
||||
// constructor leaves a flat box undefined.
|
||||
const BoundingBoxf bb = build_volume.bounding_volume2d();
|
||||
BoundingBoxf3 box;
|
||||
box.merge(Vec3d(bb.min.x(), bb.min.y(), 0.));
|
||||
box.merge(Vec3d(bb.max.x(), bb.max.y(), 0.));
|
||||
return box;
|
||||
}
|
||||
PartPlate* curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
return curr_plate != nullptr ? curr_plate->get_bounding_box() : BoundingBoxf3();
|
||||
}
|
||||
|
||||
// Design tab: CAD grid on the bed plane, drawn in place of the plate's corner-origin grid.
|
||||
@@ -11061,10 +11084,9 @@ std::optional<Vec3d> GLCanvas3D::get_camera_orbit_target(ECameraNavigationType n
|
||||
{
|
||||
// Orca: Centralize the pre-existing pivot rules so orbiting and pan fallback cannot
|
||||
// choose different reference depths for the same canvas and active tool.
|
||||
PartPlate* current_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
const BoundingBoxf3 plate_box = _current_plate_box();
|
||||
if (navigation_type == ECameraNavigationType::Gesture)
|
||||
return current_plate == nullptr ? std::nullopt :
|
||||
std::make_optional(current_plate->get_bounding_box().center());
|
||||
return plate_box.defined ? std::make_optional(plate_box.center()) : std::nullopt;
|
||||
|
||||
const GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
|
||||
const bool use_scene_target = m_canvas_type == ECanvasType::CanvasAssembleView ||
|
||||
@@ -11084,15 +11106,15 @@ std::optional<Vec3d> GLCanvas3D::get_camera_orbit_target(ECameraNavigationType n
|
||||
|
||||
Vec3d target = Vec3d::Zero();
|
||||
if (m_canvas_type == ECanvasType::CanvasPreview) {
|
||||
if (current_plate != nullptr)
|
||||
target = current_plate->get_bounding_box().center();
|
||||
if (plate_box.defined)
|
||||
target = plate_box.center();
|
||||
} else if (!m_selection.is_empty()) {
|
||||
target = m_selection.get_bounding_box().center();
|
||||
} else {
|
||||
// Orca: Match regular mouse orbit: objects on the active plate, then the plate itself.
|
||||
BoundingBoxf3 bbox = volumes_bounding_box(true);
|
||||
if (!bbox.defined && current_plate != nullptr)
|
||||
bbox = current_plate->get_bounding_box();
|
||||
if (!bbox.defined)
|
||||
bbox = plate_box;
|
||||
if (bbox.defined)
|
||||
target = bbox.center();
|
||||
}
|
||||
|
||||
@@ -1441,6 +1441,8 @@ private:
|
||||
void _render_shadows(const Transform3d& view_matrix, const Transform3d& projection_matrix);
|
||||
//BBS: add part plate related logic
|
||||
void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true);
|
||||
// The current plate's box (XY, at z = 0); in the Design tab, its own bed's.
|
||||
BoundingBoxf3 _current_plate_box() const;
|
||||
// Design tab: draw the CAD grid (minor 10 mm + major 50 mm) in place of the plate's
|
||||
// corner-origin grid when the axes sit at the bed centre (modeling origin). Rebuilds its
|
||||
// GLModels lazily, only when the bed shape changed.
|
||||
|
||||
Reference in New Issue
Block a user