NEW: added per view camera

jira: STUDIO-11834

Change-Id: I436534ce9d9c4ad12e05162c69f67682e8ec1c7b
This commit is contained in:
jun.zhang 2025-04-24 19:02:53 +08:00 committed by lane.wei
parent 7c0215454f
commit e5cfc13c17
11 changed files with 304 additions and 87 deletions

View File

@ -708,19 +708,6 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& c
return std::min((double)m_viewport[2] / dx, (double)m_viewport[3] / dy);
}
void Camera::load_camera_view(Camera& cam)
{
m_target = cam.get_target();
m_zoom = cam.get_zoom();
m_scene_box = cam.get_scene_box();
m_viewport = cam.get_viewport();
m_view_matrix = cam.get_view_matrix();
m_projection_matrix = cam.get_projection_matrix();
m_view_rotation = cam.get_view_rotation();
m_frustrum_zs = cam.get_z_range();
m_zenit = cam.get_zenit();
}
void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up)
{
const Vec3d unit_z = (position - target).normalized();

View File

@ -164,9 +164,6 @@ public:
look_at(get_position(), m_target, Vec3d::UnitZ());
}
//BBS store and load camera view
void load_camera_view(Camera& cam);
void look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up);
double max_zoom() const { return 250.0; }

View File

@ -140,6 +140,11 @@ std::string& get_object_clashed_text() {
return object_clashed_text;
}
std::string& get_assembly_too_far_text() {
static std::string assembly_warning_too_far{};
return assembly_warning_too_far;
}
std::string& get_left_extruder_unprintable_text() {
static std::string left_unprintable_text;
return left_unprintable_text;
@ -1579,6 +1584,40 @@ static bool construct_error_string(ObjectFilamentResults& object_result, std::st
return false;
}
static bool construct_assembly_warning_string(std::vector<std::string>& object_result, std::string& error_string)
{
error_string.clear();
if (!object_result.size()) {
return false;
}
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
double koef = imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0f;
float distance_limit = 10000.0f;
if (imperial_units) {
distance_limit *= koef;
}
if (imperial_units) {
error_string += (boost::format(_utf8(L("Assembly's bounding box is too large ( max size >= %1% in ) which may cause rendering issues.\n"))) % distance_limit).str();
}
else {
error_string += (boost::format(_utf8(L("Assembly's bounding box is too large ( max size >= %1% mm ) which may cause rendering issues.\n"))) % distance_limit).str();
}
if (!object_result.empty()) {
if (imperial_units) {
error_string += (boost::format(_utf8(L("Following objects are too far ( distance >= %1% in ) from the original of the world coordinate system:\n"))) % distance_limit).str();
}
else {
error_string += (boost::format(_utf8(L("Following objects are too far ( distance >= %1% mm ) from the original of the world coordinate system:\n"))) % distance_limit).str();
}
for (const auto& t_name : object_result)
{
error_string += t_name;
error_string += "\n";
}
}
return true;
}
static std::pair<bool, bool> construct_extruder_unprintable_error(ObjectFilamentResults& object_result, std::string& left_extruder_unprintable_text, std::string& right_extruder_unprintable_text)
{
left_extruder_unprintable_text.clear();
@ -1830,11 +1869,6 @@ void GLCanvas3D::plates_count_changed()
m_dirty = true;
}
Camera& GLCanvas3D::get_camera()
{
return camera;
}
void GLCanvas3D::set_use_clipping_planes(bool use)
{
if (m_gizmos.get_current_type() == GLGizmosManager::EType::Text) {
@ -2458,7 +2492,6 @@ void GLCanvas3D::render(bool only_init)
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
float right_margin = SLIDER_DEFAULT_RIGHT_MARGIN;
float bottom_margin = SLIDER_DEFAULT_BOTTOM_MARGIN;
if (m_canvas_type == ECanvasType::CanvasPreview) {
@ -2466,6 +2499,7 @@ void GLCanvas3D::render(bool only_init)
bottom_margin = SLIDER_BOTTOM_MARGIN;
}
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin);
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->get_dailytips()->render();
}
@ -3289,6 +3323,53 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false));
}
}
else
{
bool flag = false;
if (!m_volumes.empty()) {
std::vector<std::string> object_results;
object_results.reserve(10);
struct TempVolumeData
{
BoundingBoxf3 m_aabb;
GLVolume* m_p_volume{ nullptr };
};
std::vector<TempVolumeData> temp_volume_data_list;
temp_volume_data_list.reserve(m_volumes.volumes.size());
BoundingBoxf3 assembly_bb;
for (GLVolume* volume : m_volumes.volumes) {
if (!m_apply_zoom_to_volumes_filter || ((volume != nullptr) && volume->zoom_to_volumes)) {
const auto v_bb = volume->transformed_bounding_box();
assembly_bb.merge(v_bb);
TempVolumeData t_volume_data;
t_volume_data.m_aabb = v_bb;
t_volume_data.m_p_volume = volume;
temp_volume_data_list.emplace_back(t_volume_data);
}
}
if (assembly_bb.max_size() >= 1e4f) { // 10m
for (const auto& t_volume_data : temp_volume_data_list) {
if (!t_volume_data.m_p_volume) {
continue;
}
const auto t_length = t_volume_data.m_aabb.center().norm();
if (t_length >= 1e4f) {
const auto& p_object = (*m_model).objects[t_volume_data.m_p_volume->object_idx()];
if (p_object) {
object_results.emplace_back(p_object->name);
}
}
}
flag = construct_assembly_warning_string(object_results, get_assembly_too_far_text());
}
}
else {
flag = false;
}
_set_warning_notification(EWarning::AsemblyInvalid, flag);
}
refresh_camera_scene_box();
@ -7673,7 +7754,6 @@ void GLCanvas3D::_render_overlays()
_check_and_update_toolbar_icon_scale();
_render_assemble_control();
_render_assemble_info();
// main toolbar and undoredo toolbar need to be both updated before rendering because both their sizes are needed
// to correctly place them
@ -10586,7 +10666,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
SLICING_SERIOUS_WARNING,
SLICING_ERROR,
SLICING_LIMIT_ERROR,
SLICING_HEIGHT_OUTSIDE
SLICING_HEIGHT_OUTSIDE,
ASSEMBLY_WARNNING
};
const std::vector<std::string> extruder_name_list= {_u8L("left nozzle"), _u8L("right nozzle")}; // in ui, we treat extruder as nozzle
std::string text;
@ -10755,6 +10836,11 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
case EWarning::MixUsePLAAndPETG:
text = _u8L("PLA and PETG filaments detected in the mixture. Adjust parameters according to the Wiki to ensure print quality.");
break;
case EWarning::AsemblyInvalid:
{
error = ErrorType::ASSEMBLY_WARNNING;
break;
}
}
//BBS: this may happened when exit the app, plater is null
if (!wxGetApp().plater())
@ -10869,6 +10955,15 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
else
notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationLevel::ErrorNotificationLevel);
break;
case ASSEMBLY_WARNNING:
{
text = get_assembly_too_far_text();
if (state)
notification_manager.push_assembly_warning_notification(text);
else
notification_manager.close_assembly_warning_notification(text);
break;
}
default:
break;
}

View File

@ -405,7 +405,8 @@ class GLCanvas3D
MultiExtruderPrintableError, // after slice
MultiExtruderHeightOutside, // after slice
FilamentUnPrintableOnFirstLayer,
MixUsePLAAndPETG
MixUsePLAAndPETG,
AsemblyInvalid // for asembly view only
};
class RenderStats
@ -639,8 +640,6 @@ private:
//BBS if explosion_ratio is changed, need to update volume bounding box
mutable float m_explosion_ratio = 1.0;
mutable Vec3d m_rotation_center{ 0.0, 0.0, 0.0};
//BBS store camera view
Camera camera;
// Following variable is obsolete and it should be safe to remove it.
// I just don't want to do it now before a release (Lukas Matena 24.3.2019)
@ -840,9 +839,6 @@ public:
//BBS: add part plate related logic
void plates_count_changed();
//BBS get camera
Camera& get_camera();
void set_clipping_plane(unsigned int id, const ClippingPlane& plane)
{
if (id < 2)

View File

@ -3764,6 +3764,7 @@ void ObjectList::part_selection_changed()
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers);
wxGetApp().plater()->show_object_info();
wxGetApp().plater()->show_assembly_info();
panel.Layout();
panel.Thaw();

View File

@ -60,6 +60,11 @@ bool BaseView::Show(bool show)
return rt;
}
const std::shared_ptr<Camera>& BaseView::get_override_camera() const
{
return m_p_override_camera;
}
View3D::View3D(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)
: BaseView()
{
@ -811,12 +816,15 @@ AssembleView::AssembleView(wxWindow* parent, Bed3D& bed, Model* model, DynamicPr
: BaseView()
{
init(parent, bed, model, config, process);
m_p_override_camera = std::make_shared<Camera>();
m_p_override_camera->enable_update_config_on_type_change(false);
}
AssembleView::~AssembleView()
{
delete m_canvas;
delete m_canvas_widget;
m_p_override_camera = nullptr;
}
bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process)

View File

@ -12,6 +12,7 @@
#include <string>
#include "libslic3r/GCode/GCodeProcessor.hpp"
#include <slic3r/GUI/GCodeViewer.hpp>
#include <memory>
class wxGLCanvas;
class wxBoxSizer;
@ -46,9 +47,11 @@ public:
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }
GLCanvas3D* get_canvas3d() { return m_canvas; }
bool Show(bool show);
const std::shared_ptr<Camera>& get_override_camera() const;
protected:
wxGLCanvas* m_canvas_widget;
GLCanvas3D* m_canvas;
std::shared_ptr<Camera> m_p_override_camera{ nullptr };
};
class View3D : public BaseView

View File

@ -1763,6 +1763,48 @@ void NotificationManager::close_slicing_customize_error_notification(Notificatio
}
}
void NotificationManager::push_assembly_warning_notification(const std::string& text)
{
NotificationData data{ NotificationType::AssemblyWarning, NotificationLevel::WarningNotificationLevel, 0, _u8L("Warning:") + "\n" + text };
auto notification = std::make_unique<NotificationManager::AssemblyWarningNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0);
}
void NotificationManager::close_assembly_warning_notification(const std::string& text)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::AssemblyWarning && notification->compare_text(_u8L("Warning:") + "\n" + text)) {
dynamic_cast<AssemblyWarningNotification*>(notification.get())->real_close();
}
}
}
void NotificationManager::show_assembly_info_notification(const std::string& text)
{
NotificationData data{ NotificationType::AssemblyInfo, NotificationLevel::PrintInfoNotificationLevel, BBL_NOTICE_MAX_INTERVAL, text, "", nullptr};
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
std::unique_ptr<PopNotification>& notification = *it;
if (notification->get_type() == NotificationType::AssemblyInfo) {
it = m_pop_notifications.erase(it);
break;
}
else
++it;
}
auto notification = std::make_unique<NotificationManager::PopNotification>(data, m_id_provider, m_evt_handler);
notification->set_Multiline(true);
push_notification_data(std::move(notification), 0);
}
void NotificationManager::close_assembly_info_notification()
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications)
if (notification->get_type() == NotificationType::AssemblyInfo) { notification->close(); }
}
void NotificationManager::push_plater_warning_notification(const std::string& text)
{
// Find if was not hidden
@ -1779,8 +1821,7 @@ void NotificationManager::push_plater_warning_notification(const std::string& te
auto notification = std::make_unique<NotificationManager::PlaterWarningNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0);
// dissaper if in preview
apply_in_preview();
apply_canvas_type();
}
void NotificationManager::close_plater_warning_notification(const std::string& text)
@ -2351,15 +2392,25 @@ void NotificationManager::render_notifications(GLCanvas3D &canvas, float overlay
int i = 0;
for (const auto& notification : m_pop_notifications) {
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
if (notification->get_type() != NotificationType::AssemblyInfo && notification->get_type() != NotificationType::AssemblyWarning) {
continue;
}
}
else {
if (notification->get_type() == NotificationType::AssemblyInfo || notification->get_type() == NotificationType::AssemblyWarning) {
continue;
}
}
if (notification->get_data().level == NotificationLevel::ErrorNotificationLevel || notification->get_data().level == NotificationLevel::SeriousWarningNotificationLevel) {
notification->bbl_render_block_notification(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
notification->bbl_render_block_notification(canvas, bottom_up_last_y, m_move_from_overlay && (m_canvas_type == GLCanvas3D::ECanvasType::CanvasView3D), overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
else {
if (notification->get_state() != PopNotification::EState::Hidden && notification->get_state() != PopNotification::EState::Finished) {
i++;
notification->render(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
notification->render(canvas, bottom_up_last_y, m_move_from_overlay && (m_canvas_type == GLCanvas3D::ECanvasType::CanvasView3D), overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
@ -2489,24 +2540,24 @@ bool NotificationManager::activate_existing(const NotificationManager::PopNotifi
return false;
}
void NotificationManager::set_in_preview(bool preview)
void NotificationManager::set_canvas_type(GLCanvas3D::ECanvasType t_canvas_type)
{
m_in_preview = preview;
m_canvas_type = t_canvas_type;
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::PlaterWarning)
notification->hide(preview);
notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D);
if (notification->get_type() == NotificationType::BBLPlateInfo)
notification->hide(preview);
notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D);
if (notification->get_type() == NotificationType::SignDetected)
notification->hide(!preview);
notification->hide(m_canvas_type == GLCanvas3D::ECanvasType::CanvasView3D);
if (notification->get_type() == NotificationType::BBLObjectInfo)
notification->hide(preview);
notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D);
if (notification->get_type() == NotificationType::BBLSeqPrintInfo)
notification->hide(preview);
if (m_in_preview && notification->get_type() == NotificationType::DidYouKnowHint)
notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D);
if ((m_canvas_type == GLCanvas3D::ECanvasType::CanvasPreview) && notification->get_type() == NotificationType::DidYouKnowHint)
notification->close();
if (notification->get_type() == NotificationType::ValidateWarning)
notification->hide(preview);
notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D);
}
}
@ -2905,4 +2956,14 @@ void NotificationManager::PlaterWarningNotification::close()
if(m_on_delete_callback)
m_on_delete_callback(this);
}
}}//namespace Slic3r
}
void GUI::NotificationManager::AssemblyWarningNotification::close()
{
if (is_finished())
return;
m_state = EState::Hidden;
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
if (m_on_delete_callback)
m_on_delete_callback(this);
}
}//namespace Slic3r

View File

@ -154,6 +154,8 @@ enum class NotificationType
BBLSliceMultiExtruderHeightOutside,
BBLBedFilamentIncompatible,
BBLMixUsePLAAndPETG,
AssemblyWarning,
AssemblyInfo,
NotificationTypeCount
};
@ -241,6 +243,12 @@ public:
void push_slicing_customize_error_notification(NotificationType type, NotificationLevel level, const std::string &text, const std::string &hypertext = "", std::function<bool(wxEvtHandler*)> callback = std::function<bool(wxEvtHandler*)>());
void close_slicing_customize_error_notification(NotificationType type, NotificationLevel level);
void push_assembly_warning_notification(const std::string& text);
void close_assembly_warning_notification(const std::string& text);
void show_assembly_info_notification(const std::string& text);
void close_assembly_info_notification();
// Object warning with ObjectID, closes when object is deleted. ID used is of object not print like in slicing warning.
void push_simplify_suggestion_notification(const std::string& text, ObjectID object_id, const std::string& hypertext = "",
std::function<bool(wxEvtHandler*)> callback = std::function<bool(wxEvtHandler*)>());
@ -299,9 +307,9 @@ public:
void remove_notification_of_type(const NotificationType type);
void clear_all();
// Hides warnings in G-code preview. Should be called from plater only when 3d view/ preview is changed
void set_in_preview(bool preview);
void set_canvas_type(GLCanvas3D::ECanvasType t_canvas_type);
// Calls set_in_preview to apply appearing or disappearing of some notificatons;
void apply_in_preview() { set_in_preview(m_in_preview); }
void apply_canvas_type() { set_canvas_type(m_canvas_type); }
// Move to left to avoid colision with variable layer height gizmo.
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
// perform update_state on each notification and ask for more frames if needed, return true for render needed
@ -778,6 +786,15 @@ private:
std::vector<std::pair<InfoItemType, size_t>> m_types_and_counts;
};
class AssemblyWarningNotification : public PopNotification
{
public:
AssemblyWarningNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) {}
void close() override;
void real_close() { m_state = EState::ClosePending; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); }
void show() { m_state = EState::Unknown; }
};
// in SlicingProgressNotification.hpp
class SlicingProgressNotification;
@ -846,9 +863,7 @@ private:
std::vector<DelayedNotification> m_waiting_notifications;
//timestamps used for slicing finished - notification could be gone so it needs to be stored here
std::unordered_set<int> m_used_timestamps;
// True if G-code preview is active. False if the Plater is active.
bool m_in_preview { false };
int m_in_view{ 0 };
GLCanvas3D::ECanvasType m_canvas_type { GLCanvas3D::ECanvasType::CanvasView3D };
// True if the layer editing is enabled in Plater, so that the notifications are shifted left of it.
bool m_move_from_overlay { false };
// Timestamp of last rendering

View File

@ -3719,6 +3719,9 @@ public:
// Plater / private
struct Plater::priv
{
private:
Camera camera;
public:
// PIMPL back pointer ("Q-Pointer")
Plater *q;
Sidebar * sidebar;
@ -3753,7 +3756,6 @@ struct Plater::priv
std::vector<wxPanel*> panels;
Bed3D bed;
Camera camera;
Camera picking_camera;
//BBS: partplate related structure
PartPlateList partplate_list;
@ -3784,7 +3786,6 @@ struct Plater::priv
GLToolbar collapse_toolbar;
Preview *preview;
AssembleView* assemble_view { nullptr };
bool first_enter_assemble{ true };
std::unique_ptr<NotificationManager> notification_manager;
ProjectDirtyStateManager dirty_state;
@ -3963,6 +3964,7 @@ struct Plater::priv
void reset_canvas_volumes();
bool check_ams_status_impl(bool is_slice_all); // Check whether the printer and ams status are consistent, for grouping algorithm
bool get_machine_sync_status(); // check whether the printer is linked and the printer type is same as selected profile
Camera& get_current_camera();
// BBS
bool init_collapse_toolbar();
@ -6742,6 +6744,13 @@ void Plater::priv::reset(bool apply_presets_change)
view3D->get_canvas3d()->reset_sequential_print_clearance();
if (assemble_view) {
const auto& p_camera = assemble_view->get_override_camera();
if (p_camera) {
p_camera->requires_zoom_to_volumes = true;
}
}
m_ui_jobs.cancel_all();
//BBS: clear the partplate list's object before object cleared
@ -8160,21 +8169,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
update_sidebar(true);
if (wxGetApp().plater()) {
Camera& cam = wxGetApp().plater()->get_camera();
if (old_panel == preview || old_panel == view3D) {
view3D->get_canvas3d()->get_camera().load_camera_view(cam);
} else if (old_panel == assemble_view) {
assemble_view->get_canvas3d()->get_camera().load_camera_view(cam);
}
if (current_panel == view3D || current_panel == preview) {
cam.load_camera_view(view3D->get_canvas3d()->get_camera());
}
else if (current_panel == assemble_view) {
cam.load_camera_view(assemble_view->get_canvas3d()->get_camera());
}
}
if (current_panel == view3D) {
if (old_panel == preview)
preview->get_canvas3d()->unbind_event_handlers();
@ -8196,6 +8190,9 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
view3D->get_canvas3d()->bind_event_handlers();
if (notification_manager != nullptr)
notification_manager->set_canvas_type(view3D->get_canvas3d()->get_canvas_type());
if (view3D->is_reload_delayed()) {
// Delayed loading of the 3D scene.
if (printer_technology == ptSLA) {
@ -8212,8 +8209,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
view3D->get_canvas3d()->reset_old_size();
// BBS
//view_toolbar.select_item("3D");
if (notification_manager != nullptr)
notification_manager->set_in_preview(false);
}
else if (current_panel == preview) {
q->invalid_all_plate_thumbnails();
@ -8260,9 +8255,11 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
// BBS
//view_toolbar.select_item("Preview");
if (notification_manager != nullptr)
notification_manager->set_in_preview(true);
notification_manager->set_canvas_type(preview->get_canvas3d()->get_canvas_type());
}
else if (current_panel == assemble_view) {
if (notification_manager != nullptr)
notification_manager->set_canvas_type(assemble_view->get_canvas3d()->get_canvas_type());
if (old_panel == view3D) {
view3D->get_canvas3d()->unbind_event_handlers();
}
@ -8286,12 +8283,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice)
}
}
// BBS set default view and zoom
if (first_enter_assemble) {
wxGetApp().plater()->get_camera().requires_zoom_to_volumes = true;
first_enter_assemble = false;
}
assemble_view->set_as_dirty();
// BBS
//view_toolbar.select_item("Assemble");
@ -10058,6 +10049,20 @@ bool Plater::priv::get_machine_sync_status()
return preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->printer_type;
}
Camera& Plater::priv::get_current_camera()
{
if (current_panel == assemble_view) {
if (assemble_view) {
const auto& p_camera = assemble_view->get_override_camera();
if (p_camera) {
p_camera->set_type(camera.get_type());
return *p_camera;
}
}
}
return camera;
}
bool Plater::priv::init_collapse_toolbar()
{
if (wxGetApp().is_gcode_viewer())
@ -11134,7 +11139,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString &project_
// BBS set default view and zoom
p->select_view_3D("3D");
p->select_view("topfront");
p->camera.requires_zoom_to_bed = true;
p->get_current_camera().requires_zoom_to_bed = true;
enable_sidebar(!m_only_gcode);
up_to_date(true, false);
@ -11318,7 +11323,7 @@ int Plater::load_project(wxString const &filename2,
//p->select_view_3D("3D");
if (!m_exported_file) {
p->select_view("topfront");
p->camera.requires_zoom_to_plate = REQUIRES_ZOOM_TO_ALL_PLATE;
p->get_current_camera().requires_zoom_to_plate = REQUIRES_ZOOM_TO_ALL_PLATE;
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
}
else {
@ -16142,12 +16147,12 @@ bool Plater::init_collapse_toolbar()
const Camera& Plater::get_camera() const
{
return p->camera;
return p->get_current_camera();
}
Camera& Plater::get_camera()
{
return p->camera;
return p->get_current_camera();
}
const Camera& Plater::get_picking_camera() const
@ -16985,6 +16990,54 @@ void Plater::show_object_info()
notify_manager->bbl_show_objectsinfo_notification(info_text, warning, !(p->current_panel == p->view3D), into_u8(hyper_text), callback);
}
void Plater::show_assembly_info()
{
auto p_notification_manager = get_notification_manager();
if (!p_notification_manager) {
return;
}
if (!p->assemble_view) {
return;
}
const auto& p_canvas = p->assemble_view->get_canvas3d();
if (!p_canvas) {
return;
}
const Selection& t_selection = p_canvas->get_selection();
if (t_selection.is_empty()) {
p_notification_manager->close_assembly_info_notification();
return;
}
std::string info_text;
info_text += _u8L("Assembly Info");
info_text += "\n";
double size0 = t_selection.get_bounding_box().size()(0);
double size1 = t_selection.get_bounding_box().size()(1);
double size2 = t_selection.get_bounding_box().size()(2);
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
double koef = imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0f;
if (imperial_units) {
size0 *= koef;
size1 *= koef;
size2 *= koef;
}
if (imperial_units)
info_text += (boost::format(_utf8(L("Volume: %1% in³\n"))) % (size0 * size1 * size2)).str();
else
info_text += (boost::format(_utf8(L("Volume: %1% mm³\n"))) % (size0 * size1 * size2)).str();
if (imperial_units)
info_text += (boost::format(_utf8(L("Size: %1% x %2% x %3% in\n"))) % size0 % size1 % size2).str();
else
info_text += (boost::format(_utf8(L("Size: %1% x %2% x %3% mm\n"))) % size0 % size1 % size2).str();
p_notification_manager->show_assembly_info_notification(info_text);
}
bool Plater::show_publish_dialog(bool show)
{
return p->show_publish_dlg(show);

View File

@ -671,6 +671,7 @@ public:
void update_slicing_context_to_current_partplate();
//BBS: show object info
void show_object_info();
void show_assembly_info();
//BBS
bool show_publish_dialog(bool show = true);
//BBS: post process string object exception strings by warning types