diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index f2cee748e..f522c6cb4 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -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(); diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 2322d5bfe..c2b4a0d65 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -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; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 61e81c4a7..41c43767a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -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& 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 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,14 +2492,14 @@ void GLCanvas3D::render(bool only_init) wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this); + float right_margin = SLIDER_DEFAULT_RIGHT_MARGIN; + float bottom_margin = SLIDER_DEFAULT_BOTTOM_MARGIN; + if (m_canvas_type == ECanvasType::CanvasPreview) { + right_margin = SLIDER_RIGHT_MARGIN; + 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) { - float right_margin = SLIDER_DEFAULT_RIGHT_MARGIN; - float bottom_margin = SLIDER_DEFAULT_BOTTOM_MARGIN; - if (m_canvas_type == ECanvasType::CanvasPreview) { - right_margin = SLIDER_RIGHT_MARGIN; - bottom_margin = SLIDER_BOTTOM_MARGIN; - } - wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin); wxGetApp().plater()->get_dailytips()->render(); } @@ -3289,6 +3323,53 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } } + else + { + bool flag = false; + if (!m_volumes.empty()) { + std::vector object_results; + object_results.reserve(10); + struct TempVolumeData + { + BoundingBoxf3 m_aabb; + GLVolume* m_p_volume{ nullptr }; + }; + std::vector 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 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; } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index cc92fbaf8..31682cc0b 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -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) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index be3dcefd7..5768cb2ed 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -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(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index a63c44947..c05aae527 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -60,6 +60,11 @@ bool BaseView::Show(bool show) return rt; } +const std::shared_ptr& 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(); + 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) diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 1aacf6e83..329c16bc9 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -12,6 +12,7 @@ #include #include "libslic3r/GCode/GCodeProcessor.hpp" #include +#include 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& get_override_camera() const; protected: wxGLCanvas* m_canvas_widget; GLCanvas3D* m_canvas; + std::shared_ptr m_p_override_camera{ nullptr }; }; class View3D : public BaseView diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index b7c704e1d..61a804f90 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1583,7 +1583,7 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) : void NotificationManager::on_change_color_mode(bool is_dark) { m_is_dark = is_dark; for (std::unique_ptr& notification : m_pop_notifications){ - notification->on_change_color_mode(is_dark); + notification->on_change_color_mode(is_dark); } } @@ -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(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& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::AssemblyWarning && notification->compare_text(_u8L("Warning:") + "\n" + text)) { + dynamic_cast(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& notification = *it; + if (notification->get_type() == NotificationType::AssemblyInfo) { + it = m_pop_notifications.erase(it); + break; + } + else + ++it; + } + + auto notification = std::make_unique(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& 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(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 ¬ification : 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->close(); + 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 diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 9be8f70ff..c1b2c89cc 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -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 callback = std::function()); 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 callback = std::function()); @@ -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> 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 m_waiting_notifications; //timestamps used for slicing finished - notification could be gone so it needs to be stored here std::unordered_set 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 diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8d736abec..196eff2e9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -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 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 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); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 28dc28773..d13aa72e7 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -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